[Sheepdog] [PATCH 02/10] collie: add snapshot id support

FUJITA Tomonori fujita.tomonori at lab.ntt.co.jp
Tue Jan 26 05:34:48 CET 2010


qemu (qcow2) supports the id of snapshots, which can be used to
specify a snapshot. the ids are automatically generated when creating
a snapshot.

This patch adds the above support to sheepdog.

Signed-off-by: FUJITA Tomonori <fujita.tomonori at lab.ntt.co.jp>
---
 collie/store.c |  120 +++++++++++++++++++++++++++++---------------------------
 1 files changed, 62 insertions(+), 58 deletions(-)

diff --git a/collie/store.c b/collie/store.c
index 5d1cb43..0244789 100644
--- a/collie/store.c
+++ b/collie/store.c
@@ -23,7 +23,6 @@
 
 #define ANAME_LAST_OID "user.sheepdog.last_oid"
 #define ANAME_COPIES "user.sheepdog.copies"
-#define ANAME_CURRENT "user.sheepdog.current"
 
 static char *vdi_path;
 static char *obj_path;
@@ -581,8 +580,6 @@ static int so_read_vdis(struct request *req)
 	DIR *dir, *vdir;
 	struct dirent *dent, *vdent;
 	char *p;
-	int fd, ret;
-	uint64_t coid;
 	char vpath[1024];
 	struct sheepdog_dir_entry *sde = req->data;
 
@@ -597,25 +594,6 @@ static int so_read_vdis(struct request *req)
 
 		snprintf(vpath, sizeof(vpath), "%s%s", vdi_path, dent->d_name);
 
-		fd = open(vpath, O_RDONLY);
-		if (fd < 0) {
-			eprintf("%m\n");
-			closedir(dir);
-			return SD_RES_EIO;
-		}
-
-		ret = fgetxattr(fd, ANAME_CURRENT, &coid,
-				sizeof(coid));
-		if (ret != sizeof(coid)) {
-			closedir(dir);
-			close(fd);
-			return SD_RES_EIO;
-		}
-
-		dprintf("%lx\n", coid);
-
-		close(fd);
-
 		vdir = opendir(vpath);
 		if (!vdir) {
 			closedir(dir);
@@ -628,20 +606,19 @@ static int so_read_vdis(struct request *req)
 				continue;
 
 			p = strchr(vdent->d_name, '-');
-			if (!p) {
-				eprintf("bug %s\n", vdent->d_name);
-				continue;
-			}
 
 			dprintf("%s\n", vdent->d_name);
 
-			*p = '\0';
+			if (p)
+				*p = '\0';
 
 			sde->oid = strtoull(vdent->d_name, NULL, 16);
-			sde->tag = strtoull(p + 1, NULL, 16);
-
-			if (sde->oid == coid)
+			if (p)
+				sde->tag = strtoull(p + 1, NULL, 16);
+			else {
+				sde->tag = 0;
 				sde->flags = FLAG_CURRENT;
+			}
 
 			sde->name_len = strlen(dent->d_name);
 			strcpy(sde->name, dent->d_name);
@@ -667,7 +644,7 @@ static int so_lookup_vdi(struct request *req)
 	struct dirent *dent;
 	char *p;
 	int fd, ret;
-	uint64_t coid, oid;
+	uint64_t oid;
 	char path[1024];
 
 	memset(path, 0, sizeof(path));
@@ -686,24 +663,8 @@ static int so_lookup_vdi(struct request *req)
 		}
 	}
 
-	ret = fgetxattr(fd, ANAME_CURRENT, &coid,
-			sizeof(coid));
-	if (ret != sizeof(coid)) {
-		close(fd);
-		eprintf("%m\n");
-		return SD_RES_EIO;
-	}
-
-	dprintf("%lx, %x\n", coid, hdr->tag);
-
 	close(fd);
 
-	if (hdr->tag == 0xffffffff) {
-		rsp->oid = coid;
-		rsp->flags = SD_VDI_RSP_FLAG_CURRENT;
-		return SD_RES_SUCCESS;
-	}
-
 	dir = opendir(path);
 	if (!dir)
 		return SD_RES_EIO;
@@ -715,8 +676,14 @@ static int so_lookup_vdi(struct request *req)
 
 		p = strchr(dent->d_name, '-');
 		if (!p) {
-			eprintf("bug %s\n", dent->d_name);
-			continue;
+			if (!hdr->tag) {
+				rsp->oid = strtoull(dent->d_name, NULL, 16);
+				rsp->flags = SD_VDI_RSP_FLAG_CURRENT;
+
+				ret = SD_RES_SUCCESS;
+				break;
+			} else
+				continue;
 		}
 
 		if (strtoull(p + 1, NULL, 16) == hdr->tag) {
@@ -724,8 +691,6 @@ static int so_lookup_vdi(struct request *req)
 			oid = strtoull(dent->d_name, NULL, 16);
 			rsp->oid = oid;
 			dprintf("%lx, %x\n", oid, hdr->tag);
-			if (oid == coid)
-				rsp->flags = SD_VDI_RSP_FLAG_CURRENT;
 
 			ret = SD_RES_SUCCESS;
 			break;
@@ -746,6 +711,8 @@ void so_queue_request(struct work *work, int idx)
 	uint32_t opcode = hdr->opcode;
 	uint64_t last_oid = 0;
 	char path[1024];
+	char oldname[1024];
+	uint16_t id = 0;
 
 	if (list_empty(&cluster->node_list)) {
 		/* we haven't got SD_OP_GET_NODE_LIST response yet. */
@@ -804,9 +771,39 @@ void so_queue_request(struct work *work, int idx)
 		strncpy(path + strlen(path), "/", 1);
 		strncpy(path + strlen(path), (char *)req->data,	hdr->data_length);
 
-		if (hdr->flags & SD_FLAG_CMD_SNAPSHOT)
-			;
-		else {
+		if (hdr->flags & SD_FLAG_CMD_SNAPSHOT) {
+			DIR *dir;
+			struct dirent *dent;
+
+			dir = opendir(path);
+			if (!dir) {
+				ret = SD_RES_NO_VDI;
+				goto out;
+			}
+
+			while ((dent = readdir(dir))) {
+				uint16_t tmp;
+				char *p;
+
+				if (!strcmp(dent->d_name, ".") ||
+				    !strcmp(dent->d_name, ".."))
+					continue;
+				p = strchr(dent->d_name, '-');
+				if (!p) {
+					memset(oldname, 0, sizeof(oldname));
+					snprintf(oldname, sizeof(oldname), "%s/%s",
+						 path, dent->d_name);
+					continue;
+				}
+
+				tmp = strtoul(p + 1, NULL, 16);
+				if (tmp > id)
+					id = tmp;
+			}
+			/* TODO: wraparound */
+			id++;
+			closedir(dir);
+		} else {
 			ret = mkdir(path, def_dmode);
 			if (ret) {
 				if (errno == EEXIST)
@@ -828,8 +825,8 @@ void so_queue_request(struct work *work, int idx)
 
 		last_oid += MAX_DATA_OBJS;
 
-		snprintf(path+ strlen(path), sizeof(path) - strlen(path),
-			 "/%016lx-%08x", last_oid, hdr->tag);
+		snprintf(path+ strlen(path), sizeof(path) - strlen(path), "/%016lx", last_oid);
+
 		ret = creat(path, def_fmode);
 		if (ret < 0) {
 			eprintf("%m\n");
@@ -849,8 +846,15 @@ void so_queue_request(struct work *work, int idx)
 
 		close(fd);
 
-		ret = fsetxattr(nfd, ANAME_CURRENT, &last_oid,
-				sizeof(last_oid), 0);
+		if (hdr->flags & SD_FLAG_CMD_SNAPSHOT) {
+			snprintf(path, sizeof(path), "%s-%04x", oldname, id);
+			ret = rename(oldname, path);
+			if (ret) {
+				eprintf("%s, %s, %m\n", oldname, path);
+				result = SD_RES_EIO;
+				goto out;
+			}
+		}
 
 		close(nfd);
 
-- 
1.5.6.5




More information about the sheepdog mailing list