[sheepdog] [PATCH 2/3] md: fix a fatal bug in check_and_move()

Liu Yuan namei.unix at gmail.com
Wed Apr 17 11:24:03 CEST 2013


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

We can't rename(2) objects accross devices and this will cause recovery to fail.

Signed-off-by: Liu Yuan <tailai.ly at taobao.com>
---
 sheep/md.c |   39 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 37 insertions(+), 2 deletions(-)

diff --git a/sheep/md.c b/sheep/md.c
index 1bc6705..5d148cd 100644
--- a/sheep/md.c
+++ b/sheep/md.c
@@ -22,9 +22,11 @@
 #include <dirent.h>
 #include <pthread.h>
 #include <string.h>
+#include <fcntl.h>
 
 #include "sheep_priv.h"
 #include "util.h"
+#include "strbuf.h"
 
 #define MD_DEFAULT_VDISKS 128
 #define MD_MAX_VDISK (MD_MAX_DISK * MD_DEFAULT_VDISKS)
@@ -474,6 +476,38 @@ static int get_old_new_path(uint64_t oid, uint32_t epoch, char *path,
 	return 0;
 }
 
+static int move_object(char *old, char *new)
+{
+	struct strbuf buf = STRBUF_INIT;
+	int fd, ret = -1;
+
+	fd = open(old, O_RDONLY);
+	if (fd < 0) {
+		sd_eprintf("failed to open %s", old);
+		goto out;
+	}
+
+	ret = strbuf_read(&buf, fd, SD_INODE_SIZE);
+	if (ret != SD_INODE_SIZE || ret != SD_DATA_OBJ_SIZE) {
+		sd_eprintf("failed to read %s", old);
+		ret = -1;
+		goto out_close;
+	}
+
+	if (atomic_create_and_write(new, buf.buf, buf.len) < 0) {
+		sd_eprintf("failed to create %s", new);
+		ret = -1;
+		goto out_close;
+	}
+	unlink(old);
+	ret = 0;
+out_close:
+	close(fd);
+out:
+	strbuf_release(&buf);
+	return ret;
+}
+
 static int check_and_move(uint64_t oid, uint32_t epoch, char *path)
 {
 	char old[PATH_MAX], new[PATH_MAX];
@@ -481,8 +515,9 @@ static int check_and_move(uint64_t oid, uint32_t epoch, char *path)
 	if (get_old_new_path(oid, epoch, path, old, new) < 0)
 		return SD_RES_EIO;
 
-	if (rename(old, new) < 0) {
-		sd_eprintf("old %s, new %s: %m", old, new);
+	/* We can't use rename(2) accross device */
+	if (move_object(old, new) < 0) {
+		sd_eprintf("move old %s to new %s failed", old, new);
 		return SD_RES_EIO;
 	}
 
-- 
1.7.9.5




More information about the sheepdog mailing list