[Sheepdog] [PATCH 2/5] collie: add vdi creation support

MORITA Kazutaka morita.kazutaka at lab.ntt.co.jp
Mon Aug 8 18:44:16 CEST 2011


$ collie vdi create -h
vdi create - create a image

Usage:
  collie vdi create <vdiname> <size> [-P] [-a address] [-p port] [-h]

Command parameters:
  -P, --prealloc          preallocate all the data objects
  -a, --address           specify the daemon address (default: localhost)
  -p, --port              specify the daemon port
  -h, --help              display this help and exit

Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
---
 collie/collie.c          |  155 ++++++++++++++++++++++++++++++++++++++++++++++
 include/sheepdog_proto.h |    1 +
 2 files changed, 156 insertions(+), 0 deletions(-)

diff --git a/collie/collie.c b/collie/collie.c
index c669891..b89e533 100644
--- a/collie/collie.c
+++ b/collie/collie.c
@@ -58,6 +58,7 @@ static const struct sd_option collie_options[] = {
 	{'h', "help", 0, "display this help and exit"},
 
 	/* vdi options */
+	{'P', "prealloc", 0, "preallocate all the data objects"},
 	{'i', "index", 1, "specify the index of data objects"},
 	{'s', "snapshot", 1, "specify a snapshot id or tag name"},
 	{'x', "exclusive", 0, "write in an exclusive mode"},
@@ -109,6 +110,36 @@ static char *size_to_str(uint64_t _size, char *str, int str_size)
 	return str;
 }
 
+static int parse_option_size(const char *value, uint64_t *ret)
+{
+	char *postfix;
+	double sizef;
+
+	sizef = strtod(value, &postfix);
+	switch (*postfix) {
+	case 'T':
+		sizef *= 1024;
+	case 'G':
+		sizef *= 1024;
+	case 'M':
+		sizef *= 1024;
+	case 'K':
+	case 'k':
+		sizef *= 1024;
+	case 'b':
+	case '\0':
+		*ret = (uint64_t) sizef;
+		break;
+	default:
+		fprintf(stderr, "invalid parameter, %s\n", value);
+		fprintf(stderr, "You may use k, M, G or T suffixes for "
+			"kilobytes, megabytes, gigabytes and terabytes.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
 static int update_node_list(int max_nodes, int epoch)
 {
 	int fd, ret;
@@ -268,6 +299,7 @@ struct vdi_cmd_data {
 	char snapshot_tag[SD_MAX_VDI_TAG_LEN];
 	int exclusive;
 	int delete;
+	int prealloc;
 } vdi_cmd_data = { ~0, };
 
 static int cluster_format(int argc, char **argv)
@@ -821,6 +853,124 @@ static int vdi_graph(int argc, char **argv)
 	return EXIT_SUCCESS;
 }
 
+static int do_vdi_create(char *vdiname, int64_t vdi_size, uint32_t base_vid,
+			 uint32_t *vdi_id, int snapshot)
+{
+	struct sd_vdi_req hdr;
+	struct sd_vdi_rsp *rsp = (struct sd_vdi_rsp *)&hdr;
+	int fd, ret;
+	unsigned int wlen, rlen = 0;
+	char buf[SD_MAX_VDI_LEN];
+
+	fd = connect_to(sdhost, sdport);
+	if (fd < 0) {
+		fprintf(stderr, "failed to connect\n");
+		return EXIT_SYSFAIL;
+	}
+
+	memset(buf, 0, sizeof(buf));
+	strncpy(buf, vdiname, SD_MAX_VDI_LEN);
+
+	memset(&hdr, 0, sizeof(hdr));
+	hdr.opcode = SD_OP_NEW_VDI;
+	hdr.base_vdi_id = base_vid;
+
+	wlen = SD_MAX_VDI_LEN;
+
+	hdr.flags = SD_FLAG_CMD_WRITE;
+	hdr.snapid = snapshot;
+
+	hdr.data_length = wlen;
+	hdr.vdi_size = vdi_size;
+
+	ret = exec_req(fd, (struct sd_req *)&hdr, buf, &wlen, &rlen);
+
+	close(fd);
+
+	if (ret) {
+		fprintf(stderr, "failed to send a request\n");
+		return EXIT_SYSFAIL;
+	}
+
+	if (rsp->result != SD_RES_SUCCESS) {
+		fprintf(stderr, "%s, %s\n", sd_strerror(rsp->result), vdiname);
+		return EXIT_FAILURE;
+	}
+
+	if (vdi_id)
+		*vdi_id = rsp->vdi_id;
+
+	return EXIT_SUCCESS;
+}
+
+static int vdi_create(int argc, char **argv)
+{
+	char *vdiname = argv[optind++];
+	uint64_t size;
+	uint32_t vid;
+	uint64_t oid;
+	int idx, max_idx, ret;
+	struct sheepdog_inode *inode = NULL;
+	char *buf = NULL;
+
+	if (!argv[optind]) {
+		fprintf(stderr, "please specify the size of vdi\n");
+		return EXIT_USAGE;
+	}
+	ret = parse_option_size(argv[optind], &size);
+	if (ret < 0)
+		return EXIT_USAGE;
+	if (size > SD_MAX_VDI_SIZE) {
+		fprintf(stderr, "too big image size, %s\n", argv[optind]);
+		return EXIT_USAGE;
+	}
+
+	ret = do_vdi_create(vdiname, size, 0, &vid, 0);
+	if (ret != EXIT_SUCCESS || !vdi_cmd_data.prealloc)
+		goto out;
+
+	inode = malloc(sizeof(*inode));
+	buf = zalloc(SD_DATA_OBJ_SIZE);
+	if (!inode || !buf) {
+		fprintf(stderr, "oom\n");
+		ret = EXIT_SYSFAIL;
+		goto out;
+	}
+
+	ret = sd_read_object(vid_to_vdi_oid(vid), inode, sizeof(*inode), 0);
+	if (ret != SD_RES_SUCCESS) {
+		fprintf(stderr, "failed to read a newly created vdi object\n");
+		ret = EXIT_FAILURE;
+		goto out;
+	}
+	max_idx = DIV_ROUND_UP(size, SD_DATA_OBJ_SIZE);
+
+	for (idx = 0; idx < max_idx; idx++) {
+		oid = vid_to_data_oid(vid, idx);
+
+		ret = sd_write_object(oid, buf, SD_DATA_OBJ_SIZE, 0, 0,
+				      inode->nr_copies, 1);
+		if (ret != SD_RES_SUCCESS) {
+			ret = EXIT_FAILURE;
+			goto out;
+		}
+
+		inode->data_vdi_id[idx] = vid;
+		ret = sd_write_object(vid_to_vdi_oid(vid), &vid, sizeof(vid),
+				      SD_INODE_HEADER_SIZE + sizeof(vid) * idx, 0,
+				      inode->nr_copies, 0);
+		if (ret) {
+			ret = EXIT_FAILURE;
+			goto out;
+		}
+	}
+	ret = EXIT_SUCCESS;
+out:
+	free(inode);
+	free(buf);
+	return ret;
+}
+
 static int vdi_delete(int argc, char **argv)
 {
 	char *data = argv[optind];
@@ -1108,6 +1258,8 @@ static int vdi_getattr(int argc, char **argv)
 }
 
 static struct subcommand vdi_cmd[] = {
+	{"create", "<vdiname> <size>", "Paph", "create a image",
+	 SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_create},
 	{"delete", "<vdiname>", "saph", "delete a image",
 	 SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG, vdi_delete},
 	{"list", "[vdiname]", "aprh", "list images",
@@ -1128,6 +1280,9 @@ static struct subcommand vdi_cmd[] = {
 static int vdi_parser(int ch, char *opt)
 {
 	switch (ch) {
+	case 'P':
+		vdi_cmd_data.prealloc = 1;
+		break;
 	case 'i':
 		vdi_cmd_data.index = atoi(opt);
 		break;
diff --git a/include/sheepdog_proto.h b/include/sheepdog_proto.h
index 5c50aa7..2b042f4 100644
--- a/include/sheepdog_proto.h
+++ b/include/sheepdog_proto.h
@@ -81,6 +81,7 @@
 #define SD_MAX_VDI_ATTR_VALUE_LEN (UINT64_C(1) << 22)
 #define SD_NR_VDIS   (1U << 24)
 #define SD_DATA_OBJ_SIZE (UINT64_C(1) << 22)
+#define SD_MAX_VDI_SIZE (SD_DATA_OBJ_SIZE * MAX_DATA_OBJS)
 #define SECTOR_SIZE (1U << 9)
 
 #define SD_INODE_SIZE (sizeof(struct sheepdog_inode))
-- 
1.7.2.5




More information about the sheepdog mailing list