Pass a struct sd_node array instead of an unformatted buffer to all
epoch_log_read variants, and cut down the epoch_log_read/epoch_log_read_nr
split down to a single variant, which returns the number of nodes,
but is called epoch_log_read.  Also make epoch_log_read_remote return
the number of nodes, as that's what most callers want.

Signed-off-by: Christoph Hellwig <hch@lst.de>

diff --git a/sheep/farm/snap.c b/sheep/farm/snap.c
index 1e5917d..5a7a642 100644
--- a/sheep/farm/snap.c
+++ b/sheep/farm/snap.c
@@ -161,21 +161,21 @@ int snap_file_write(uint32_t epoch, unsigned char *trunksha1, unsigned char *out
 	struct strbuf buf = STRBUF_INIT;
 	struct sd_node nodes[SD_MAX_NODES];
 	int tgt_epoch = user ? sys_epoch() : epoch;
-	uint64_t epoch_size;
+	int nr_nodes;
 	struct sha1_file_hdr hdr;
 
-	epoch_size = epoch_log_read(tgt_epoch, (char *)nodes, sizeof(nodes));
-	if (epoch_size == -1)
+	nr_nodes = epoch_log_read(tgt_epoch, nodes, sizeof(nodes));
+	if (nr_nodes == -1)
 		return -1;
 
 	memcpy(hdr.tag, TAG_SNAP, TAG_LEN);
-	hdr.size = epoch_size + SHA1_LEN;
+	hdr.size = nr_nodes * sizeof(*nodes) + SHA1_LEN;
 	hdr.priv = tgt_epoch;
 	hdr.reserved = 0;
 
 	strbuf_add(&buf, &hdr, sizeof(hdr));
 	strbuf_add(&buf, trunksha1, SHA1_LEN);
-	strbuf_add(&buf, (char *)nodes, epoch_size);
+	strbuf_add(&buf, (char *)nodes, nr_nodes * sizeof(*nodes));
 	if (sha1_file_write((void *)buf.buf, buf.len, outsha1) < 0) {
 		ret = -1;
 		goto err;
diff --git a/sheep/group.c b/sheep/group.c
index 4715651..96dea8d 100644
--- a/sheep/group.c
+++ b/sheep/group.c
@@ -224,10 +224,9 @@ struct vnode_info *get_vnode_info_epoch(uint32_t epoch)
 	struct sd_node nodes[SD_MAX_NODES];
 	int nr_nodes;
 
-	nr_nodes = epoch_log_read_nr(epoch, (void *)nodes, sizeof(nodes));
+	nr_nodes = epoch_log_read(epoch, nodes, sizeof(nodes));
 	if (nr_nodes < 0) {
-		nr_nodes = epoch_log_read_remote(epoch, (void *)nodes,
-						 sizeof(nodes));
+		nr_nodes = epoch_log_read_remote(epoch, nodes, sizeof(nodes));
 		if (nr_nodes == 0)
 			return NULL;
 		nr_nodes /= sizeof(nodes[0]);
@@ -383,11 +382,8 @@ static inline int get_nodes_nr_from(struct list_head *l)
 static int get_nodes_nr_epoch(uint32_t epoch)
 {
 	struct sd_node nodes[SD_MAX_NODES];
-	int nr;
 
-	nr = epoch_log_read(epoch, (char *)nodes, sizeof(nodes));
-	nr /= sizeof(nodes[0]);
-	return nr;
+	return epoch_log_read(epoch, nodes, sizeof(nodes));
 }
 
 static struct sd_node *find_entry_list(struct sd_node *entry,
@@ -408,7 +404,7 @@ static struct sd_node *find_entry_epoch(struct sd_node *entry,
 	struct sd_node nodes[SD_MAX_NODES];
 	int nr, i;
 
-	nr = epoch_log_read_nr(epoch, (char *)nodes, sizeof(nodes));
+	nr = epoch_log_read(epoch, nodes, sizeof(nodes));
 
 	for (i = 0; i < nr; i++)
 		if (node_eq(&nodes[i], entry))
@@ -452,9 +448,8 @@ static int cluster_sanity_check(struct sd_node *entries,
 		goto out;
 	}
 
-	nr_local_entries = epoch_log_read_nr(epoch, (char *)local_entries,
-			sizeof(local_entries));
-
+	nr_local_entries = epoch_log_read(epoch, local_entries,
+					  sizeof(local_entries));
 	if (nr_entries != nr_local_entries ||
 	    memcmp(entries, local_entries, sizeof(entries[0]) * nr_entries) != 0) {
 		ret = SD_RES_INVALID_EPOCH;
@@ -500,7 +495,7 @@ static int get_cluster_status(struct sd_node *from,
 		else
 			nr = current_vnode_info->nr_nodes + 1;
 
-		nr_local_entries = epoch_log_read_nr(epoch, (char *)local_entries,
+		nr_local_entries = epoch_log_read(epoch, local_entries,
 						  sizeof(local_entries));
 
 		if (nr != nr_local_entries) {
diff --git a/sheep/ops.c b/sheep/ops.c
index 2fe6fb4..59df88e 100644
--- a/sheep/ops.c
+++ b/sheep/ops.c
@@ -349,14 +349,12 @@ static int local_stat_cluster(struct request *req)
 		log = (struct epoch_log *)req->data + i;
 		log->epoch = epoch;
 		log->ctime = get_cluster_ctime();
-		log->nr_nodes = epoch_log_read_nr(epoch, (char *)log->nodes,
+		log->nr_nodes = epoch_log_read(epoch, log->nodes,
 					       sizeof(log->nodes));
-		if (log->nr_nodes == -1) {
-			log->nr_nodes = epoch_log_read_remote(epoch,
-							      (char *)log->nodes,
+		if (log->nr_nodes == -1)
+			log->nr_nodes = epoch_log_read_remote(epoch, log->nodes,
 							      sizeof(log->nodes));
-			log->nr_nodes /= sizeof(log->nodes[0]);
-		}
+
 		log->nr_copies = get_max_nr_copies_from(log->nodes, log->nr_nodes);
 
 		rsp->data_length += sizeof(*log);
@@ -397,19 +395,18 @@ static int local_get_obj_list(struct request *req)
 static int local_get_epoch(struct request *req)
 {
 	uint32_t epoch = req->rq.obj.tgt_epoch;
-	int len, ret;
+	int nr_nodes;
 
 	dprintf("%d\n", epoch);
 
-	len = epoch_log_read(epoch, req->data, req->rq.data_length);
-	if (len == -1) {
-		ret = SD_RES_NO_TAG;
+	nr_nodes = epoch_log_read(epoch, req->data, req->rq.data_length);
+	if (nr_nodes == -1) {
 		req->rp.data_length = 0;
-	} else {
-		ret = SD_RES_SUCCESS;
-		req->rp.data_length = len;
+		return SD_RES_NO_TAG;
 	}
-	return ret;
+
+	req->rp.data_length = nr_nodes * sizeof(struct sd_node);
+	return SD_RES_SUCCESS;
 }
 
 static int cluster_manual_recover(const struct sd_req *req, struct sd_rsp *rsp,
diff --git a/sheep/sheep_priv.h b/sheep/sheep_priv.h
index f38259e..94cf98d 100644
--- a/sheep/sheep_priv.h
+++ b/sheep/sheep_priv.h
@@ -276,9 +276,8 @@ int store_file_write(void *buffer, size_t len);
 void *store_file_read(void);
 int get_max_nr_copies_from(struct sd_node *entries, int nr);
 
-int epoch_log_read(uint32_t epoch, char *buf, int len);
-int epoch_log_read_nr(uint32_t epoch, char *buf, int len);
-int epoch_log_read_remote(uint32_t epoch, char *buf, int len);
+int epoch_log_read(uint32_t epoch, struct sd_node *nodes, int len);
+int epoch_log_read_remote(uint32_t epoch, struct sd_node *nodes, int len);
 uint32_t get_latest_epoch(void);
 int set_cluster_ctime(uint64_t ctime);
 uint64_t get_cluster_ctime(void);
diff --git a/sheep/store.c b/sheep/store.c
index cd7d16c..8f343b4 100644
--- a/sheep/store.c
+++ b/sheep/store.c
@@ -112,22 +112,20 @@ void do_io_request(struct work *work)
 	req->rp.result = ret;
 }
 
-int epoch_log_read_remote(uint32_t epoch, char *buf, int len)
+int epoch_log_read_remote(uint32_t epoch, struct sd_node *nodes, int len)
 {
 	int i, ret;
 	unsigned int nr, le;
-	struct sd_node nodes[SD_MAX_NODES];
+	struct sd_node local_nodes[SD_MAX_NODES];
 
 	le = get_latest_epoch();
 	if (!le)
 		return 0;
 
-	nr = epoch_log_read(le, (char *)nodes, sizeof(nodes));
+	nr = epoch_log_read(le, local_nodes, sizeof(local_nodes));
 	if (nr < 0)
 		return -1;
 
-	nr /= sizeof(nodes[0]);
-
 	for (i = 0; i < nr; i++) {
 		struct sd_req hdr;
 		struct sd_rsp *rsp = (struct sd_rsp *)&hdr;
@@ -135,11 +133,11 @@ int epoch_log_read_remote(uint32_t epoch, char *buf, int len)
 		unsigned int rlen, wlen;
 		int fd;
 
-		if (is_myself(nodes[i].addr, nodes[i].port))
+		if (is_myself(local_nodes[i].addr, local_nodes[i].port))
 			continue;
 
-		addr_to_str(host, sizeof(host), nodes[i].addr, 0);
-		fd = connect_to(host, nodes[i].port);
+		addr_to_str(host, sizeof(host), local_nodes[i].addr, 0);
+		fd = connect_to(host, local_nodes[i].port);
 		if (fd < 0) {
 			vprintf(SDOG_ERR, "failed to connect to %s: %m\n", host);
 			continue;
@@ -152,11 +150,11 @@ int epoch_log_read_remote(uint32_t epoch, char *buf, int len)
 
 		wlen = 0;
 
-		ret = exec_req(fd, &hdr, buf, &wlen, &rlen);
+		ret = exec_req(fd, &hdr, nodes, &wlen, &rlen);
 		close(fd);
 
 		if (!ret && rsp->result == SD_RES_SUCCESS)
-			return rsp->data_length;
+			return rsp->data_length / sizeof(*nodes);
 	}
 
 	/*
@@ -166,32 +164,27 @@ int epoch_log_read_remote(uint32_t epoch, char *buf, int len)
 	return 0;
 }
 
-int epoch_log_read_nr(uint32_t epoch, char *buf, int len)
-{
-	int nr;
-
-	nr = epoch_log_read(epoch, buf, len);
-	if (nr < 0)
-		return nr;
-	nr /= sizeof(struct sd_node);
-	return nr;
-}
-
-int epoch_log_read(uint32_t epoch, char *buf, int len)
+int epoch_log_read(uint32_t epoch, struct sd_node *nodes, int len)
 {
 	int fd;
 	char path[PATH_MAX];
 
 	snprintf(path, sizeof(path), "%s%08u", epoch_path, epoch);
 	fd = open(path, O_RDONLY);
-	if (fd < 0)
+	if (fd < 0) {
+		eprintf("failed to open epoch %"PRIu32" log\n", epoch);
 		return -1;
+	}
 
-	len = read(fd, buf, len);
+	len = read(fd, nodes, len);
 
 	close(fd);
 
-	return len;
+	if (len < 0) {
+		eprintf("failed to read epoch %"PRIu32" log\n", epoch);
+		return -1;
+	}
+	return len / sizeof(*nodes);
 }
 
 uint32_t get_latest_epoch(void)
@@ -525,14 +518,14 @@ int read_epoch(uint32_t *epoch, uint64_t *ct,
 	int ret;
 
 	*epoch = get_latest_epoch();
-	ret = epoch_log_read(*epoch, (char *)entries,
-			     *nr_entries * sizeof(*entries));
+
+	ret = epoch_log_read(*epoch, entries, *nr_entries * sizeof(*entries));
 	if (ret == -1) {
 		eprintf("failed to read epoch %"PRIu32"\n", *epoch);
 		*nr_entries = 0;
 		return SD_RES_EIO;
 	}
-	*nr_entries = ret / sizeof(*entries);
+	*nr_entries = ret;
 
 	*ct = get_cluster_ctime();
 


