[Sheepdog] [PATCH v6 08/17] farm: remove stale object in backend store

Liu Yuan namei.unix at gmail.com
Thu Jan 12 14:37:19 CET 2012


From: Liu Yuan <tailai.ly at taobao.com>

For storing one object into backend store, either

a) no content change, then point to the same old sha1_file (no stale object)
or
b) content updated, then will point to a new object with a new sha1.

So we need to remove stale object in case b), only in the assumption it is the
object generated by recovery code. [*]

When we try store new snapshot object into the backend store, it is safe and
good timing for us to remove the old object with the same object ID.

[*] Here I assume we don't need to restore to 'sys epoch' state.

Signed-off-by: Liu Yuan <tailai.ly at taobao.com>
---
 sheep/farm/farm.h  |    2 +
 sheep/farm/trunk.c |  149 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 149 insertions(+), 2 deletions(-)

diff --git a/sheep/farm/farm.h b/sheep/farm/farm.h
index 5734903..bf8654c 100644
--- a/sheep/farm/farm.h
+++ b/sheep/farm/farm.h
@@ -62,5 +62,7 @@ extern int trunk_file_write(unsigned char *outsha1, int user);
 extern void *trunk_file_read(unsigned char *sha1, struct sha1_file_hdr *);
 extern int trunk_update_entry(uint64_t oid);
 extern void trunk_reset(void);
+extern void trunk_put_entry(uint64_t oid);
+extern void trunk_get_entry(uint64_t oid);
 
 #endif
diff --git a/sheep/farm/trunk.c b/sheep/farm/trunk.c
index 0506f3f..d10da85 100644
--- a/sheep/farm/trunk.c
+++ b/sheep/farm/trunk.c
@@ -18,6 +18,8 @@
  */
 #include <pthread.h>
 #include <dirent.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 #include "farm.h"
 #include "strbuf.h"
@@ -36,6 +38,11 @@ static struct hlist_head trunk_hashtable[HASH_SIZE];
 static pthread_mutex_t hashtable_lock[HASH_SIZE] = { [0 ... HASH_SIZE - 1] = PTHREAD_MUTEX_INITIALIZER };
 static unsigned int trunk_entry_active_nr;
 
+struct omap_entry {
+	uint64_t oid;
+	unsigned char sha1[SHA1_LEN];
+};
+
 static inline int trunk_entry_is_dirty(struct trunk_entry_incore *entry)
 {
 	return entry->flags & TRUNK_ENTRY_DIRTY;
@@ -91,6 +98,27 @@ out:
 	return entry;
 }
 
+static int create_files(void)
+{
+	int fd, ret = 0;
+	struct strbuf buf = STRBUF_INIT;
+
+	strbuf_addstr(&buf, farm_dir);
+	strbuf_addf(&buf, "/%s", "sys_omap");
+
+	fd = open(buf.buf, O_CREAT | O_EXCL, 0666);
+	if (fd < 0) {
+		if (errno != EEXIST) {
+			ret = -1;
+			goto out;
+		}
+	}
+	close(fd);
+out:
+	strbuf_release(&buf);
+	return ret;
+}
+
 int trunk_init(void)
 {
 	DIR *dir;
@@ -109,6 +137,10 @@ int trunk_init(void)
 			continue;
 		lookup_trunk_entry(oid, 1);
 	}
+
+	if (create_files() < 0)
+		return -1;
+
 	closedir(dir);
 	return 0;
 }
@@ -142,7 +174,8 @@ static int fill_entry_new_sha1(struct trunk_entry_incore *entry)
 		close(fd);
 		goto out;
 	}
-	dprintf("oid: %"PRIx64"\n", entry->raw.oid);
+	dprintf("data sha1:%s, %"PRIx64"\n", sha1_to_hex(entry->raw.sha1),
+		entry->raw.oid);
 out:
 	strbuf_release(&buf);
 	return ret;
@@ -163,9 +196,91 @@ static void inline put_entry(struct trunk_entry_incore *entry)
 	free(entry);
 }
 
+static int omap_file_init(struct strbuf *outbuf)
+{
+	int fd;
+	int len = -1;
+	void *buffer = NULL;
+	struct strbuf buf = STRBUF_INIT;
+	struct stat st;
+
+	strbuf_addf(&buf, "%s/%s", farm_dir, "sys_omap");
+	fd = open(buf.buf, O_RDONLY);
+	if (fd < 0)
+		goto out;
+
+	if (fstat(fd, &st) < 0) {
+		dprintf("%m\n");
+		goto out_close;
+	}
+
+	len = st.st_size;
+	if (len == 0)
+		goto out_close;
+
+	buffer = xmalloc(len);
+	len = xread(fd, buffer, len);
+	if (len != st.st_size) {
+		len = -1;
+		goto out_close;
+	}
+	strbuf_add(outbuf, buffer, len);
+out_close:
+	close(fd);
+out:
+	strbuf_release(&buf);
+	free(buffer);
+	return len;
+}
+
+static int omap_file_final(struct strbuf *omap_buf)
+{
+	int fd, ret = -1;
+	struct strbuf buf = STRBUF_INIT;
+
+	if (omap_buf->len == 0)
+		return 0;
+
+	strbuf_addf(&buf, "%s/%s", farm_dir, "sys_omap");
+	fd = open(buf.buf, O_WRONLY | O_TRUNC);
+	if (fd < 0) {
+		dprintf("%m\n");
+		goto out;
+	}
+
+	ret = xwrite(fd, omap_buf->buf, omap_buf->len);
+	if (ret != omap_buf->len)
+		ret = -1;
+
+	close(fd);
+out:
+	strbuf_release(&buf);
+	return ret;
+}
+
+static struct omap_entry *omap_file_insert(struct strbuf *buf, struct omap_entry *new)
+{
+	unsigned i, nr = buf->len / sizeof(struct omap_entry);
+	struct omap_entry *omap_buf = (struct omap_entry *)buf->buf;
+	for (i = 0; i < nr; i++, omap_buf++)
+		if (omap_buf->oid == new->oid) {
+			if (memcmp(omap_buf->sha1, new->sha1, SHA1_LEN) == 0)
+				return NULL;
+			else {
+				struct omap_entry *old = xmalloc(sizeof(*old));
+				memcpy(old, omap_buf, sizeof(*old));
+				memcpy(omap_buf->sha1, new->sha1, SHA1_LEN);
+				return old;
+			}
+		}
+	dprintf("oid, %"PRIx64"\n", new->oid);
+	strbuf_add(buf, new, sizeof(*new));
+	return NULL;
+}
+
 int trunk_file_write(unsigned char *outsha1, int user)
 {
-	struct strbuf buf;
+	struct strbuf buf, omap_buf = STRBUF_INIT;
 	uint64_t data_size = sizeof(struct trunk_entry) * trunk_entry_active_nr;
 	struct sha1_file_hdr hdr = { .size = data_size,
 				     .priv = trunk_entry_active_nr };
@@ -174,6 +289,7 @@ int trunk_file_write(unsigned char *outsha1, int user)
 
 	memcpy(hdr.tag, TAG_TRUNK, TAG_LEN);
 	strbuf_init(&buf, sizeof(hdr) + data_size);
+	omap_file_init(&omap_buf);
 
 	strbuf_add(&buf, &hdr, sizeof(hdr));
 	list_for_each_entry_safe(entry, t, &trunk_active_list, active_list) {
@@ -184,8 +300,21 @@ int trunk_file_write(unsigned char *outsha1, int user)
 			}
 		}
 		strbuf_add(&buf, &entry->raw, sizeof(struct trunk_entry));
+		if (!user) {
+			struct omap_entry new = { .oid = entry->raw.oid }, *old;
+			memcpy(new.sha1, entry->raw.sha1, SHA1_LEN);
+			old = omap_file_insert(&omap_buf, &new);
+			if (old) {
+				dprintf("try delete stale snapshot object %"PRIx64"\n", old->oid);
+				sha1_file_try_delete(old->sha1);
+				free(old);
+			}
+		}
 		undirty_trunk_entry(entry);
 	}
+	if (omap_file_final(&omap_buf) < 0)
+		eprintf("omap_file_final failed\n");
+
 	if (sha1_file_write((void *)buf.buf, buf.len, outsha1) < 0) {
 		ret = -1;
 		goto out;
@@ -193,6 +322,7 @@ int trunk_file_write(unsigned char *outsha1, int user)
 	dprintf("trunk sha1: %s\n", sha1_to_hex(outsha1));
 out:
 	strbuf_release(&buf);
+	strbuf_release(&omap_buf);
 	return ret;
 }
 
@@ -223,6 +353,21 @@ int trunk_update_entry(uint64_t oid)
 	return 0;
 }
 
+void trunk_put_entry(uint64_t oid)
+{
+	struct trunk_entry_incore *entry;
+
+	entry = lookup_trunk_entry(oid, 0);
+	if (entry)
+	/* When it is supposed to be put, no IO requests for it */
+		put_entry(entry);
+}
+
+void trunk_get_entry(uint64_t oid)
+{
+	lookup_trunk_entry(oid, 1);
+}
+
 void trunk_reset(void)
 {
 	struct trunk_entry_incore *entry, *t;
-- 
1.7.8.2




More information about the sheepdog mailing list