[Sheepdog] [RFC PATCH] sheep: introduce sd_op_template

Liu Yuan namei.unix at gmail.com
Fri Oct 21 14:13:46 CEST 2011


On 10/21/2011 04:28 PM, MORITA Kazutaka wrote:

> When we want to add a new operation (SD_OP_xxxxx), it is not clear
> which codes we should modify.  And in some cases, we need to modify
> codes everywhere to implement one operation.  This is not a good
> design.
> 
> This patch abstracts out Sheepdog operations into sd_op_template, and
> moves all the request processing codes to sheep/ops.c.
> 
> The definition of sd_op_template is as follows:
> 
> struct sd_op_template {
>         enum sd_op_type type;
> 
>         int available_always;
> 
>         int (*process)(const struct sd_req *req, struct sd_rsp *rsp,
>                        void *data);
>         int (*post_process)(const struct sd_req *req, struct sd_rsp *rsp,
>                             void *data);
> };
> 
> 'type' is the type of the operation; SD_OP_TYPE_CLUSTER,
> SD_OP_TYPE_STORE, or SD_OP_TYPE_IO.
> 
> 'available_always' is set to non-zero if the operations should be
> processed even when the cluster is not working.
> 
> 'process()' and 'post_process()' are the main functions of this
> operation.  process() will be called in the worker thread, and
> post_process() will be called in the main thread.
> 
> If type is SD_OP_TYPE_CLUSTER, it is guaranteed that only one node
> processes a cluster operation at the same time.  We can use this for
> something like distributed locking.  process() will be called on the
> local node, and post_process() will be called on every nodes.
> 
> If type is SD_OP_TYPE_STORE, both process() and post_process() will be
> called on the local node.
> 
> If type is SD_OP_TYPE_IO, neither process() nor post_process() is used
> because this type of operation is heavily intertwined with Sheepdog
> core codes.  We will be unlikely to add new operations of this type.
> 
> Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
> ---
>  sheep/Makefile.am  |    2 +-
>  sheep/group.c      |  286 +++--------------------------------
>  sheep/ops.c        |  427 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  sheep/sdnet.c      |  111 ++------------
>  sheep/sheep_priv.h |   48 ++++++-
>  sheep/store.c      |   19 +--
>  6 files changed, 522 insertions(+), 371 deletions(-)
>  create mode 100644 sheep/ops.c
> 
> diff --git a/sheep/Makefile.am b/sheep/Makefile.am
> index 2b9d58f..3db914d 100644
> --- a/sheep/Makefile.am
> +++ b/sheep/Makefile.am
> @@ -23,7 +23,7 @@ INCLUDES		= -I$(top_builddir)/include -I$(top_srcdir)/include $(libcpg_CFLAGS) $
>  
>  sbin_PROGRAMS		= sheep
>  
> -sheep_SOURCES		= sheep.c group.c sdnet.c store.c vdi.c work.c journal.c \
> +sheep_SOURCES		= sheep.c group.c sdnet.c store.c vdi.c work.c journal.c ops.c \
>  			  cluster/corosync.c
>  sheep_LDADD	  	= $(libcpg_LIBS) $(libcfg_LIBS) ../lib/libsheepdog.a -lpthread
>  sheep_DEPENDENCIES	= ../lib/libsheepdog.a
> diff --git a/sheep/group.c b/sheep/group.c
> index e22dabc..8664b6f 100644
> --- a/sheep/group.c
> +++ b/sheep/group.c
> @@ -101,17 +101,7 @@ static size_t get_join_message_size(struct join_message *jm)
>  	return sizeof(*jm) + jm->nr_nodes * sizeof(jm->nodes[0]);
>  }
>  
> -static int get_node_idx(struct sheepdog_node_list_entry *ent,
> -			struct sheepdog_node_list_entry *entries, int nr_nodes)
> -{
> -	ent = bsearch(ent, entries, nr_nodes, sizeof(*ent), node_cmp);
> -	if (!ent)
> -		return -1;
> -
> -	return ent - entries;
> -}
> -
> -static int get_zones_nr_from(struct sheepdog_node_list_entry *nodes, int nr_nodes)
> +int get_zones_nr_from(struct sheepdog_node_list_entry *nodes, int nr_nodes)
>  {
>  	int nr_zones = 0, i, j;
>  	uint32_t zones[SD_MAX_REDUNDANCY];
> @@ -146,116 +136,28 @@ void setup_ordered_sd_vnode_list(struct request *req)
>  	get_ordered_sd_vnode_list(req->entry, &req->nr_vnodes, &req->nr_zones);
>  }
>  
> -static void get_node_list(struct sd_node_req *req,
> -			  struct sd_node_rsp *rsp, void *data)
> +static void do_cluster_op(void *arg)
>  {
> -	int nr_nodes;
> -
> -	nr_nodes = sys->nr_nodes;
> -	memcpy(data, sys->nodes, sizeof(*sys->nodes) * nr_nodes);
> -	rsp->data_length = nr_nodes * sizeof(struct sheepdog_node_list_entry);
> -	rsp->nr_nodes = nr_nodes;
> -	rsp->local_idx = get_node_idx(&sys->this_node, data, nr_nodes);
> -	rsp->master_idx = -1;
> -}
> +	struct vdi_op_message *msg = arg;
> +	int ret;
> +	struct request *req;
>  
> -static int get_epoch(struct sd_obj_req *req,
> -		      struct sd_obj_rsp *rsp, void *data)
> -{
> -	int epoch = req->tgt_epoch;
> -	int len, ret;
> -	dprintf("%d\n", epoch);
> -	len = epoch_log_read(epoch, (char *)data, req->data_length);
> -	if (len == -1) {
> -		ret = SD_RES_NO_TAG;
> -		rsp->data_length = 0;
> -	} else {
> -		ret = SD_RES_SUCCESS;
> -		rsp->data_length = len;
> -	}
> -	return ret;
> -}
> +	req = list_first_entry(&sys->pending_list, struct request, pending_list);
> +	ret = req->op->process((const struct sd_req *)&msg->req,
> +			       (struct sd_rsp *)&msg->rsp, req->data);
>  
> -static void vdi_op(void *arg);
> +	msg->rsp.result = ret;
> +}
>  
>  void cluster_queue_request(struct work *work, int idx)
>  {
>  	struct request *req = container_of(work, struct request, work);
>  	struct sd_req *hdr = (struct sd_req *)&req->rq;
> -	struct sd_rsp *rsp = (struct sd_rsp *)&req->rp;
>  	struct vdi_op_message *msg;
> -	struct epoch_log *log;
> -	int ret = SD_RES_SUCCESS, i, max_logs, epoch;
> -	uint32_t sys_stat = sys_stat_get();
>  	size_t size;
>  
>  	eprintf("%p %x\n", req, hdr->opcode);
>  
> -	switch (hdr->opcode) {
> -	case SD_OP_GET_EPOCH:
> -		ret = get_epoch((struct sd_obj_req *)hdr,
> -			  (struct sd_obj_rsp *)rsp, req->data);
> -		break;
> -	case SD_OP_GET_NODE_LIST:
> -		get_node_list((struct sd_node_req *)hdr,
> -			      (struct sd_node_rsp *)rsp, req->data);
> -		break;
> -	case SD_OP_STAT_CLUSTER:
> -		max_logs = rsp->data_length / sizeof(*log);
> -		epoch = get_latest_epoch();
> -		rsp->data_length = 0;
> -		for (i = 0; i < max_logs; i++) {
> -			if (epoch <= 0)
> -				break;
> -
> -			log = (struct epoch_log *)req->data + i;
> -			log->epoch = epoch;
> -			log->ctime = get_cluster_ctime();
> -			log->nr_nodes = epoch_log_read(epoch, (char *)log->nodes,
> -						       sizeof(log->nodes));
> -			if (log->nr_nodes == -1)
> -				log->nr_nodes = epoch_log_read_remote(epoch,
> -								      (char *)log->nodes,
> -								      sizeof(log->nodes));
> -
> -			rsp->data_length += sizeof(*log);
> -			log->nr_nodes /= sizeof(log->nodes[0]);
> -			epoch--;
> -		}
> -
> -		switch (sys_stat) {
> -		case SD_STATUS_OK:
> -			ret = SD_RES_SUCCESS;
> -			break;
> -		case SD_STATUS_WAIT_FOR_FORMAT:
> -			ret = SD_RES_WAIT_FOR_FORMAT;
> -			break;
> -		case SD_STATUS_WAIT_FOR_JOIN:
> -			ret = SD_RES_WAIT_FOR_JOIN;
> -			break;
> -		case SD_STATUS_SHUTDOWN:
> -			ret = SD_RES_SHUTDOWN;
> -			break;
> -		case SD_STATUS_JOIN_FAILED:
> -			ret = SD_RES_JOIN_FAILED;
> -			break;
> -		case SD_STATUS_HALT:
> -			ret = SD_RES_HALT;
> -			break;
> -		default:
> -			ret = SD_RES_SYSTEM_ERROR;
> -			break;
> -		}
> -		break;
> -	default:
> -		/* forward request to group */
> -		goto forward;
> -	}
> -
> -	rsp->result = ret;
> -	return;
> -
> -forward:
>  	if (hdr->flags & SD_FLAG_CMD_WRITE)
>  		size = sizeof(*msg);
>  	else
> @@ -272,7 +174,12 @@ forward:
>  
>  	list_add(&req->pending_list, &sys->pending_list);
>  
> -	sys->cdrv->notify(msg, size, vdi_op);
> +	if (req->op->process)
> +		sys->cdrv->notify(msg, size, do_cluster_op);
> +	else {
> +		msg->rsp.result = SD_RES_SUCCESS;
> +		sys->cdrv->notify(msg, size, NULL);
> +	}
>  
>  	free(msg);
>  }
> @@ -628,85 +535,6 @@ join_finished:
>  	return;
>  }
>  
> -static void vdi_op(void *arg)
> -{
> -	struct vdi_op_message *msg = arg;
> -	const struct sd_vdi_req *hdr = &msg->req;
> -	struct sd_vdi_rsp *rsp = &msg->rsp;
> -	void *data, *tag;
> -	int ret = SD_RES_SUCCESS;
> -	struct sheepdog_vdi_attr *vattr;
> -	uint32_t vid = 0, attrid = 0, nr_copies = sys->nr_sobjs;
> -	uint64_t ctime = 0;
> -	struct request *req;
> -
> -	req = list_first_entry(&sys->pending_list, struct request, pending_list);
> -	data = req->data;
> -
> -	switch (hdr->opcode) {
> -	case SD_OP_NEW_VDI:
> -		ret = add_vdi(hdr->epoch, data, hdr->data_length, hdr->vdi_size, &vid,
> -			      hdr->base_vdi_id, hdr->copies,
> -			      hdr->snapid, &nr_copies);
> -		break;
> -	case SD_OP_DEL_VDI:
> -		ret = del_vdi(hdr->epoch, data, hdr->data_length, &vid,
> -			      hdr->snapid, &nr_copies);
> -		break;
> -	case SD_OP_LOCK_VDI:
> -	case SD_OP_GET_VDI_INFO:
> -		if (hdr->proto_ver != SD_PROTO_VER) {
> -			ret = SD_RES_VER_MISMATCH;
> -			break;
> -		}
> -		if (hdr->data_length == SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN)
> -			tag = (char *)data + SD_MAX_VDI_LEN;
> -		else if (hdr->data_length == SD_MAX_VDI_LEN)
> -			tag = NULL;
> -		else {
> -			ret = SD_RES_INVALID_PARMS;
> -			break;
> -		}
> -		ret = lookup_vdi(hdr->epoch, data, tag, &vid, hdr->snapid,
> -				 &nr_copies, NULL);
> -		if (ret != SD_RES_SUCCESS)
> -			break;
> -		break;
> -	case SD_OP_GET_VDI_ATTR:
> -		vattr = data;
> -		ret = lookup_vdi(hdr->epoch, vattr->name, vattr->tag,
> -				 &vid, hdr->snapid, &nr_copies, &ctime);
> -		if (ret != SD_RES_SUCCESS)
> -			break;
> -		/* the curernt vdi id can change if we take the snapshot,
> -		   so we use the hash value of the vdi name as the vdi id */
> -		vid = fnv_64a_buf(vattr->name, strlen(vattr->name), FNV1A_64_INIT);
> -		vid &= SD_NR_VDIS - 1;
> -		ret = get_vdi_attr(hdr->epoch, data, hdr->data_length, vid,
> -				   &attrid, nr_copies, ctime,
> -				   hdr->flags & SD_FLAG_CMD_CREAT,
> -				   hdr->flags & SD_FLAG_CMD_EXCL,
> -				   hdr->flags & SD_FLAG_CMD_DEL);
> -		break;
> -	case SD_OP_RELEASE_VDI:
> -		break;
> -	case SD_OP_MAKE_FS:
> -		ret = SD_RES_SUCCESS;
> -		break;
> -	case SD_OP_SHUTDOWN:
> -		break;
> -	default:
> -		ret = SD_RES_SYSTEM_ERROR;
> -		eprintf("opcode %d is not implemented\n", hdr->opcode);
> -		break;
> -	}
> -
> -	rsp->vdi_id = vid;
> -	rsp->attr_id = attrid;
> -	rsp->copies = nr_copies;
> -	rsp->result = ret;
> -}
> -
>  static void __sd_notify(struct cpg_event *cevent)
>  {
>  }
> @@ -715,86 +543,22 @@ static void __sd_notify_done(struct cpg_event *cevent)
>  {
>  	struct work_notify *w = container_of(cevent, struct work_notify, cev);
>  	struct vdi_op_message *msg = (struct vdi_op_message *)w->msg;
> -	const struct sd_vdi_req *hdr = &msg->req;
> -	struct sd_vdi_rsp *rsp = &msg->rsp;
> -	void *data = msg->data;
>  	struct request *req;
>  	int ret = msg->rsp.result;
> -	int i, latest_epoch;
> -	uint64_t ctime;
> -
> -	if (ret != SD_RES_SUCCESS)
> -		goto out;
> -
> -	switch (hdr->opcode) {
> -	case SD_OP_NEW_VDI:
> -	{
> -		unsigned long nr = rsp->vdi_id;
> -		vprintf(SDOG_INFO, "done %d %ld\n", ret, nr);
> -		set_bit(nr, sys->vdi_inuse);
> -		break;
> -	}
> -	case SD_OP_DEL_VDI:
> -		break;
> -	case SD_OP_LOCK_VDI:
> -	case SD_OP_RELEASE_VDI:
> -	case SD_OP_GET_VDI_INFO:
> -	case SD_OP_GET_VDI_ATTR:
> -		break;
> -	case SD_OP_MAKE_FS:
> -		sys->nr_sobjs = ((struct sd_so_req *)hdr)->copies;
> -		sys->flags = ((struct sd_so_req *)hdr)->flags;
> -		if (!sys->nr_sobjs)
> -			sys->nr_sobjs = SD_DEFAULT_REDUNDANCY;
> -
> -		ctime = ((struct sd_so_req *)hdr)->ctime;
> -		set_cluster_ctime(ctime);
> -
> -		latest_epoch = get_latest_epoch();
> -		for (i = 1; i <= latest_epoch; i++)
> -			remove_epoch(i);
> -		memset(sys->vdi_inuse, 0, sizeof(sys->vdi_inuse));
> -
> -		sys->epoch = 1;
> -		sys->recovered_epoch = 1;
> -
> -		dprintf("write epoch log, %d, %d\n", sys->epoch, sys->nr_nodes);
> -		ret = epoch_log_write(sys->epoch, (char *)sys->nodes,
> -				      sys->nr_nodes * sizeof(struct sheepdog_node_list_entry));
> -		if (ret < 0)
> -			eprintf("can't write epoch %u\n", sys->epoch);
> -		update_epoch_store(sys->epoch);
> +	struct sd_op_template *op = get_sd_op(msg->req.opcode);
>  
> -		set_cluster_copies(sys->nr_sobjs);
> -		set_cluster_flags(sys->flags);
> +	if (ret == SD_RES_SUCCESS && op->post_process)
> +		ret = op->post_process((const struct sd_req *)&msg->req,
> +				       (struct sd_rsp *)&msg->rsp, msg->data);
>  
> -		if (sys_flag_nohalt())
> -			sys_stat_set(SD_STATUS_OK);
> -		else {
> -			int nr_zones = get_zones_nr_from(sys->nodes, sys->nr_nodes);
> -
> -			if (nr_zones >= sys->nr_sobjs)
> -				sys_stat_set(SD_STATUS_OK);
> -			else
> -				sys_stat_set(SD_STATUS_HALT);
> -		}
> -		break;
> -	case SD_OP_SHUTDOWN:
> -		sys_stat_set(SD_STATUS_SHUTDOWN);
> -		break;
> -	default:
> -		eprintf("unknown operation %d\n", hdr->opcode);
> -		ret = SD_RES_UNKNOWN;
> -	}
> -out:
>  	if (!is_myself(w->sender.addr, w->sender.port))
>  		return;
>  
>  	req = list_first_entry(&sys->pending_list, struct request, pending_list);
>  
> -	rsp->result = ret;
> -	memcpy(req->data, data, rsp->data_length);
> -	memcpy(&req->rp, rsp, sizeof(req->rp));
> +	msg->rsp.result = ret;
> +	memcpy(req->data, msg->data, msg->rsp.data_length);
> +	memcpy(&req->rp, &msg->rsp, sizeof(req->rp));
>  	list_del(&req->pending_list);
>  	req->done(req);
>  }
> @@ -1226,7 +990,7 @@ do_retry:
>  
>  		list_del(&cevent->cpg_event_list);
>  
> -		if (is_io_request(req->rq.opcode)) {
> +		if (is_io_op(req->op)) {
>  			int copies = sys->nr_sobjs;
>  
>  			if (copies > req->nr_zones)
> @@ -1282,7 +1046,7 @@ do_retry:
>  			}
>  		}
>  
> -		if (is_cluster_request(req->rq.opcode))
> +		if (is_cluster_op(req->op))
>  			queue_work(sys->cpg_wqueue, &req->work);
>  		else if (req->rq.flags & SD_FLAG_CMD_IO_LOCAL)
>  			queue_work(sys->io_wqueue, &req->work);
> diff --git a/sheep/ops.c b/sheep/ops.c
> new file mode 100644
> index 0000000..0d38e7b
> --- /dev/null
> +++ b/sheep/ops.c
> @@ -0,0 +1,427 @@
> +/*
> + * Copyright (C) 2011 Nippon Telegraph and Telephone Corporation.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License version
> + * 2 as published by the Free Software Foundation.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +#include <stdio.h>
> +#include <stdlib.h>
> +
> +#include "sheep_priv.h"
> +
> +static int process_new_vdi(const struct sd_req *req, struct sd_rsp *rsp,
> +			   void *data)
> +{
> +	const struct sd_vdi_req *hdr = (const struct sd_vdi_req *)req;
> +	struct sd_vdi_rsp *vdi_rsp = (struct sd_vdi_rsp *)rsp;
> +	uint32_t vid = 0, nr_copies = sys->nr_sobjs;
> +	int ret;
> +
> +	ret = add_vdi(hdr->epoch, data, hdr->data_length, hdr->vdi_size, &vid,
> +		      hdr->base_vdi_id, hdr->copies,
> +		      hdr->snapid, &nr_copies);
> +
> +	vdi_rsp->vdi_id = vid;
> +	vdi_rsp->copies = nr_copies;
> +
> +	return ret;
> +}
> +
> +static int post_process_new_vdi(const struct sd_req *req, struct sd_rsp *rsp,
> +				void *data)
> +{
> +	struct sd_vdi_rsp *vdi_rsp = (struct sd_vdi_rsp *)rsp;
> +	unsigned long nr = vdi_rsp->vdi_id;
> +	int ret = vdi_rsp->result;
> +
> +	vprintf(SDOG_INFO, "done %d %ld\n", ret, nr);
> +	set_bit(nr, sys->vdi_inuse);
> +
> +	return SD_RES_SUCCESS;
> +}
> +
> +static int process_del_vdi(const struct sd_req *req, struct sd_rsp *rsp,
> +			   void *data)
> +{
> +	const struct sd_vdi_req *hdr = (const struct sd_vdi_req *)req;
> +	struct sd_vdi_rsp *vdi_rsp = (struct sd_vdi_rsp *)rsp;
> +	uint32_t vid = 0, nr_copies = sys->nr_sobjs;
> +	int ret;
> +
> +	ret = del_vdi(hdr->epoch, data, hdr->data_length, &vid,
> +		      hdr->snapid, &nr_copies);
> +
> +	vdi_rsp->vdi_id = vid;
> +	vdi_rsp->copies = nr_copies;
> +
> +	return ret;
> +}
> +
> +static int process_get_vdi_info(const struct sd_req *req, struct sd_rsp *rsp,
> +				void *data)
> +{
> +	const struct sd_vdi_req *hdr = (const struct sd_vdi_req *)req;
> +	struct sd_vdi_rsp *vdi_rsp = (struct sd_vdi_rsp *)rsp;
> +	uint32_t vid = 0, nr_copies = sys->nr_sobjs;
> +	void *tag;
> +	int ret;
> +
> +	if (hdr->proto_ver != SD_PROTO_VER)
> +		return SD_RES_VER_MISMATCH;
> +
> +	if (hdr->data_length == SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN)
> +		tag = (char *)data + SD_MAX_VDI_LEN;
> +	else if (hdr->data_length == SD_MAX_VDI_LEN)
> +		tag = NULL;
> +	else
> +		return SD_RES_INVALID_PARMS;
> +
> +	ret = lookup_vdi(hdr->epoch, data, tag, &vid, hdr->snapid,
> +			 &nr_copies, NULL);
> +	if (ret != SD_RES_SUCCESS)
> +		return ret;
> +
> +	vdi_rsp->vdi_id = vid;
> +	vdi_rsp->copies = nr_copies;
> +
> +	return ret;
> +}
> +
> +static int post_process_make_fs(const struct sd_req *req, struct sd_rsp *rsp,
> +				void *data)
> +{
> +	const struct sd_so_req *hdr = (const struct sd_so_req *)req;
> +	int i, latest_epoch, ret;
> +	uint64_t ctime;
> +
> +	sys->nr_sobjs = hdr->copies;
> +	sys->flags = hdr->flags;
> +	if (!sys->nr_sobjs)
> +		sys->nr_sobjs = SD_DEFAULT_REDUNDANCY;
> +
> +	ctime = hdr->ctime;
> +	set_cluster_ctime(ctime);
> +
> +	latest_epoch = get_latest_epoch();
> +	for (i = 1; i <= latest_epoch; i++)
> +		remove_epoch(i);
> +	memset(sys->vdi_inuse, 0, sizeof(sys->vdi_inuse));
> +
> +	sys->epoch = 1;
> +	sys->recovered_epoch = 1;
> +
> +	dprintf("write epoch log, %d, %d\n", sys->epoch, sys->nr_nodes);
> +	ret = epoch_log_write(sys->epoch, (char *)sys->nodes,
> +			      sys->nr_nodes * sizeof(struct sheepdog_node_list_entry));
> +	if (ret < 0) {
> +		eprintf("can't write epoch %u\n", sys->epoch);
> +		return SD_RES_EIO;
> +	}
> +	update_epoch_store(sys->epoch);
> +
> +	set_cluster_copies(sys->nr_sobjs);
> +	set_cluster_flags(sys->flags);
> +
> +	if (sys_flag_nohalt())
> +		sys_stat_set(SD_STATUS_OK);
> +	else {
> +		int nr_zones = get_zones_nr_from(sys->nodes, sys->nr_nodes);
> +
> +		if (nr_zones >= sys->nr_sobjs)
> +			sys_stat_set(SD_STATUS_OK);
> +		else
> +			sys_stat_set(SD_STATUS_HALT);
> +	}
> +
> +	return SD_RES_SUCCESS;
> +}
> +
> +static int post_process_shutdown(const struct sd_req *req, struct sd_rsp *rsp,
> +				 void *data)
> +{
> +	sys_stat_set(SD_STATUS_SHUTDOWN);
> +
> +	return SD_RES_SUCCESS;
> +}
> +
> +static int process_get_vdi_attr(const struct sd_req *req, struct sd_rsp *rsp,
> +				void *data)
> +{
> +	const struct sd_vdi_req *hdr = (const struct sd_vdi_req *)req;
> +	struct sd_vdi_rsp *vdi_rsp = (struct sd_vdi_rsp *)rsp;
> +	uint32_t vid = 0, attrid = 0, nr_copies = sys->nr_sobjs;
> +	uint64_t ctime = 0;
> +	int ret;
> +	struct sheepdog_vdi_attr *vattr;
> +
> +	vattr = data;
> +	ret = lookup_vdi(hdr->epoch, vattr->name, vattr->tag,
> +			 &vid, hdr->snapid, &nr_copies, &ctime);
> +	if (ret != SD_RES_SUCCESS)
> +		return ret;
> +
> +	/* the curernt vdi id can change if we take the snapshot,
> +	   so we use the hash value of the vdi name as the vdi id */
> +	vid = fnv_64a_buf(vattr->name, strlen(vattr->name), FNV1A_64_INIT);
> +	vid &= SD_NR_VDIS - 1;
> +	ret = get_vdi_attr(hdr->epoch, data, hdr->data_length, vid,
> +			   &attrid, nr_copies, ctime,
> +			   hdr->flags & SD_FLAG_CMD_CREAT,
> +			   hdr->flags & SD_FLAG_CMD_EXCL,
> +			   hdr->flags & SD_FLAG_CMD_DEL);
> +
> +	vdi_rsp->vdi_id = vid;
> +	vdi_rsp->attr_id = attrid;
> +	vdi_rsp->copies = nr_copies;
> +
> +	return ret;
> +}
> +
> +static int post_process_read_vdis(const struct sd_req *req, struct sd_rsp *rsp,
> +				  void *data)
> +{
> +	return read_vdis(data, req->data_length, &rsp->data_length);
> +}
> +
> +static int get_node_idx(struct sheepdog_node_list_entry *ent,
> +			struct sheepdog_node_list_entry *entries, int nr_nodes)
> +{
> +	ent = bsearch(ent, entries, nr_nodes, sizeof(*ent), node_cmp);
> +	if (!ent)
> +		return -1;
> +
> +	return ent - entries;
> +}
> +
> +static int post_process_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;
> +
> +	nr_nodes = sys->nr_nodes;
> +	memcpy(data, sys->nodes, sizeof(*sys->nodes) * nr_nodes);
> +	node_rsp->data_length = nr_nodes * sizeof(struct sheepdog_node_list_entry);
> +	node_rsp->nr_nodes = nr_nodes;
> +	node_rsp->local_idx = get_node_idx(&sys->this_node, data, nr_nodes);
> +	node_rsp->master_idx = -1;
> +
> +	return SD_RES_SUCCESS;
> +}
> +
> +static int process_stat_sheep(const struct sd_req *req, struct sd_rsp *rsp,
> +			      void *data)
> +{
> +	struct sd_node_rsp *node_rsp = (struct sd_node_rsp *)rsp;
> +	uint32_t epoch = req->epoch;
> +
> +	return stat_sheep(&node_rsp->store_size, &node_rsp->store_free, epoch);
> +}
> +
> +static int process_stat_cluster(const struct sd_req *req, struct sd_rsp *rsp,
> +				void *data)
> +{
> +	struct epoch_log *log;
> +	int i, max_logs, epoch;
> +	uint32_t sys_stat = sys_stat_get();
> +
> +	max_logs = rsp->data_length / sizeof(*log);
> +	epoch = get_latest_epoch();
> +	rsp->data_length = 0;
> +	for (i = 0; i < max_logs; i++) {
> +		if (epoch <= 0)
> +			break;
> +
> +		log = (struct epoch_log *)data + i;
> +		log->epoch = epoch;
> +		log->ctime = get_cluster_ctime();
> +		log->nr_nodes = epoch_log_read(epoch, (char *)log->nodes,
> +					       sizeof(log->nodes));
> +		if (log->nr_nodes == -1)
> +			log->nr_nodes = epoch_log_read_remote(epoch,
> +							      (char *)log->nodes,
> +							      sizeof(log->nodes));
> +
> +		rsp->data_length += sizeof(*log);
> +		log->nr_nodes /= sizeof(log->nodes[0]);
> +		epoch--;
> +	}
> +
> +	switch (sys_stat) {
> +	case SD_STATUS_OK:
> +		return SD_RES_SUCCESS;
> +	case SD_STATUS_WAIT_FOR_FORMAT:
> +		return SD_RES_WAIT_FOR_FORMAT;
> +	case SD_STATUS_WAIT_FOR_JOIN:
> +		return SD_RES_WAIT_FOR_JOIN;
> +	case SD_STATUS_SHUTDOWN:
> +		return SD_RES_SHUTDOWN;
> +	case SD_STATUS_JOIN_FAILED:
> +		return SD_RES_JOIN_FAILED;
> +	case SD_STATUS_HALT:
> +		return SD_RES_HALT;
> +	default:
> +		return SD_RES_SYSTEM_ERROR;
> +	}
> +}
> +
> +static int process_kill_node(const struct sd_req *req, struct sd_rsp *rsp,
> +			     void *data)
> +{
> +	exit(1);
> +}
> +
> +static int process_get_obj_list(const struct sd_req *req, struct sd_rsp *rsp,
> +				void *data)
> +{
> +	return get_obj_list((const struct sd_list_req *)req,
> +			    (struct sd_list_rsp *)rsp, data);
> +}
> +
> +static int process_get_epoch(const struct sd_req *req, struct sd_rsp *rsp,
> +			     void *data)
> +{
> +	const struct sd_obj_req *obj_req = (const struct sd_obj_req *)req;
> +	struct sd_obj_rsp *obj_rsp = (struct sd_obj_rsp *)rsp;
> +	int epoch = obj_req->tgt_epoch;
> +	int len, ret;
> +	dprintf("%d\n", epoch);
> +	len = epoch_log_read(epoch, (char *)data, obj_req->data_length);
> +	if (len == -1) {
> +		ret = SD_RES_NO_TAG;
> +		obj_rsp->data_length = 0;
> +	} else {
> +		ret = SD_RES_SUCCESS;
> +		obj_rsp->data_length = len;
> +	}
> +	return ret;
> +}
> +
> +static struct sd_op_template sd_ops[] = {
> +
> +	/* cluster operations */
> +	[SD_OP_NEW_VDI] = {
> +		.type = SD_OP_TYPE_CLUSTER,
> +		.process = process_new_vdi,
> +		.post_process = post_process_new_vdi,
> +	},
> +
> +	[SD_OP_DEL_VDI] = {
> +		.type = SD_OP_TYPE_CLUSTER,
> +		.process = process_del_vdi,
> +	},
> +
> +	[SD_OP_GET_VDI_INFO] = {
> +		.type = SD_OP_TYPE_CLUSTER,
> +		.process = process_get_vdi_info,
> +	},
> +
> +	[SD_OP_LOCK_VDI] = {
> +		.type = SD_OP_TYPE_CLUSTER,
> +		.process = process_get_vdi_info,
> +	},
> +
> +	[SD_OP_MAKE_FS] = {
> +		.type = SD_OP_TYPE_CLUSTER,
> +		.available_always = 1,
> +		.post_process = post_process_make_fs,
> +	},
> +
> +	[SD_OP_SHUTDOWN] = {
> +		.type = SD_OP_TYPE_CLUSTER,
> +		.post_process = post_process_shutdown,
> +	},
> +
> +	[SD_OP_GET_VDI_ATTR] = {
> +		.type = SD_OP_TYPE_CLUSTER,
> +		.process = process_get_vdi_attr,
> +	},
> +
> +	[SD_OP_RELEASE_VDI] = {
> +		.type = SD_OP_TYPE_CLUSTER,
> +	},
> +


How about replace process/post_process prefix with 'cluster/local/io' to
differentiate those static functions internally? since we don't
reference them outside ops.c

Thanks,
YUan



More information about the sheepdog mailing list