[sheepdog] [PATCH] sheep: fix local_get_node_list before the node joined a cluster

Christoph Hellwig hch at infradead.org
Thu May 31 17:04:26 CEST 2012


The GET_NODE_LIST command has the force flag and thus can be executed
before the cluster has started, which includes the short time before
the sheep even has any node list, in which we can trigger the assert
for current_vnode_info in get_vnode_info.

Fix this by checking for a NULL current_vnode_info first, for which we
have to move the implementation to group.c.  To me this makes sense
anyway as the node list is a group.c internal detail to start with.

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

diff --git a/sheep/group.c b/sheep/group.c
index b5146b8..2deb7b4 100644
--- a/sheep/group.c
+++ b/sheep/group.c
@@ -128,6 +128,16 @@ bool have_enough_zones(void)
 	return false;
 }
 
+static int get_node_idx(struct vnode_info *vnode_info, struct sd_node *ent)
+{
+	ent = bsearch(ent, vnode_info->nodes, vnode_info->nr_nodes,
+		      sizeof(*ent), node_cmp);
+	if (!ent)
+		return -1;
+
+	return ent - vnode_info->nodes;
+}
+
 /*
  * If we have less zones available than the desired redundancy we have to do
  * with nr_zones copies, sorry.
@@ -223,6 +233,30 @@ struct vnode_info *alloc_vnode_info(struct sd_node *nodes, size_t nr_nodes)
 	return vnode_info;
 }
 
+int local_get_node_list(const struct sd_req *req, struct sd_rsp *rsp,
+			       void *data)
+{
+	struct sd_node_rsp *node_rsp = (struct sd_node_rsp *)rsp;
+	int nr_nodes;
+
+	if (current_vnode_info) {
+		nr_nodes = current_vnode_info->nr_nodes;
+		memcpy(data, current_vnode_info->nodes,
+			sizeof(struct sd_node) * nr_nodes);
+		node_rsp->data_length = nr_nodes * sizeof(struct sd_node);
+		node_rsp->nr_nodes = nr_nodes;
+		node_rsp->local_idx = get_node_idx(current_vnode_info,
+						   &sys->this_node);
+	} else {
+		node_rsp->data_length = 0;
+		node_rsp->nr_nodes = 0;
+		node_rsp->local_idx = 0;
+	}
+
+	node_rsp->master_idx = -1;
+	return SD_RES_SUCCESS;
+}
+
 /*
  * If we have less zones available than the desired redundancy we have to do
  * with nr_zones copies, sorry.
diff --git a/sheep/ops.c b/sheep/ops.c
index 84ebcc8..a6f0670 100644
--- a/sheep/ops.c
+++ b/sheep/ops.c
@@ -313,36 +313,6 @@ static int local_read_vdis(const struct sd_req *req, struct sd_rsp *rsp,
 	return read_vdis(data, req->data_length, &rsp->data_length);
 }
 
-static int get_node_idx(struct sd_node *ent,
-			struct sd_node *entries, int nr_nodes)
-{
-	ent = bsearch(ent, entries, nr_nodes, sizeof(*ent), node_cmp);
-	if (!ent)
-		return -1;
-
-	return ent - entries;
-}
-
-static int local_get_node_list(const struct sd_req *req, struct sd_rsp *rsp,
-			       void *data)
-{
-	struct sd_node_rsp *node_rsp = (struct sd_node_rsp *)rsp;
-	struct vnode_info *vnode_info;
-	int nr_nodes;
-
-	vnode_info = get_vnode_info();
-	nr_nodes = vnode_info->nr_nodes;
-
-	memcpy(data, vnode_info->nodes, sizeof(struct sd_node) * nr_nodes);
-	node_rsp->data_length = nr_nodes * sizeof(struct sd_node);
-	node_rsp->nr_nodes = nr_nodes;
-	node_rsp->local_idx = get_node_idx(&sys->this_node, data, nr_nodes);
-	node_rsp->master_idx = -1;
-
-	put_vnode_info(vnode_info);
-	return SD_RES_SUCCESS;
-}
-
 static int local_stat_sheep(struct request *req)
 {
 	struct sd_node_rsp *node_rsp = (struct sd_node_rsp *)&req->rp;
diff --git a/sheep/sheep_priv.h b/sheep/sheep_priv.h
index 38f3d18..f4934fe 100644
--- a/sheep/sheep_priv.h
+++ b/sheep/sheep_priv.h
@@ -231,6 +231,9 @@ int get_vdi_attr(struct vnode_info *vnode_info, uint32_t epoch,
 		uint32_t *attrid, int copies, uint64_t ctime, int write,
 		int excl, int delete);
 
+int local_get_node_list(const struct sd_req *req, struct sd_rsp *rsp,
+		void *data);
+
 bool have_enough_zones(void);
 struct vnode_info *alloc_vnode_info(struct sd_node *nodes, size_t nr_nodes);
 struct vnode_info *grab_vnode_info(struct vnode_info *vnode_info);



More information about the sheepdog mailing list