This is a temporary hack to update the object list file atomically.
FNV hash value is added to the file as an extend attribute.

Signed-off-by: MORITA Kazutaka <[email protected]>
---
 collie/store.c |   49 ++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 44 insertions(+), 5 deletions(-)

diff --git a/collie/store.c b/collie/store.c
index 1f17df4..72c079c 100644
--- a/collie/store.c
+++ b/collie/store.c
@@ -24,6 +24,7 @@
 #define ANAME_CTIME "user.sheepdog.ctime"
 #define ANAME_COPIES "user.sheepdog.copies"
 #define ANAME_NODEID "user.sheepdog.nodeid"
+#define ANAME_CHECKSUM "user.sheepdog.checksum"
 
 static char *obj_path;
 static char *epoch_path;
@@ -105,6 +106,8 @@ static int get_obj_list(struct request *req, char *buf, int 
buf_len)
        int e_nr;
        int idx;
        int res = SD_RES_SUCCESS;
+       uint64_t checksum = 0;
+       int ret;
 
        if (epoch == 1)
                goto local;
@@ -114,10 +117,26 @@ static int get_obj_list(struct request *req, char *buf, 
int buf_len)
        fd = open(path, O_RDONLY);
        if (fd < 0) {
                eprintf("failed to open %s, %s\n", path, strerror(errno));
-               close(fd);
-               return SD_RES_EIO;
+               res = SD_RES_EIO;
+               goto out;
        }
        obj_nr = read(fd, buf, buf_len);
+
+       ret = fgetxattr(fd, ANAME_CHECKSUM, &checksum, sizeof(checksum));
+       if (ret != sizeof(checksum)) {
+               eprintf("failed to read checksum %s, %m\n", path);
+               close(fd);
+               res = SD_RES_EIO;
+               goto out;
+       }
+       if (checksum != fnv_64a_buf(buf, obj_nr, FNV1A_64_INIT)) {
+               eprintf("invalid checksum %s, %m\n", path);
+               close(fd);
+               res = SD_RES_EIO;
+               goto out;
+       }
+       dprintf("read objct list from %s, %d, %lx\n", path, obj_nr, checksum);
+
        obj_nr /= sizeof(uint64_t);
        objlist = (uint64_t *)buf;
        for (i = 0; i < obj_nr; i++) {
@@ -140,7 +159,8 @@ local:
        dir = opendir(path);
        if (!dir) {
                eprintf("%s\n", path);
-               return SD_RES_EIO;
+               res = SD_RES_EIO;
+               goto out;
        }
 
        while ((d = readdir(dir))) {
@@ -168,7 +188,6 @@ local:
        }
 
        eprintf("nr = %d\n", nr);
-       rsp->data_length = nr * sizeof(uint64_t);
 
        e_nr = epoch_log_read(epoch, buf, buf_len);
        e_nr /= sizeof(*e);
@@ -176,6 +195,7 @@ local:
 
        if (e_nr <= sys->nr_sobjs) {
                rsp->next = end_hash;
+               closedir(dir);
                goto out;
        }
 
@@ -200,9 +220,13 @@ local:
        } else
                res = SD_RES_SYSTEM_ERROR;
 
-out:
        closedir(dir);
 
+out:
+       rsp->data_length = nr * sizeof(uint64_t);
+       for (i = 0; i < nr; i++) {
+               eprintf("oid %lx, %lx\n", *(p + i), p[i]);
+       }
        return res;
 }
 
@@ -1209,6 +1233,8 @@ static void __start_recovery(struct work *work, int idx)
        int i, fd;
        uint64_t start_hash, end_hash;
        char path[PATH_MAX];
+       uint64_t checksum;
+       int ret;
 
        dprintf("%u\n", epoch);
 
@@ -1245,6 +1271,9 @@ static void __start_recovery(struct work *work, int idx)
                goto fail;
        }
 
+       if (rw->retry)
+               goto fail;
+
        snprintf(path, sizeof(path), "%s%08u/list", obj_path, epoch);
        dprintf("write object list file to %s\n", path);
 
@@ -1254,6 +1283,16 @@ static void __start_recovery(struct work *work, int idx)
                goto fail;
        }
        write(fd, rw->buf, sizeof(uint64_t) * rw->count);
+       fsync(fd);
+
+       checksum = fnv_64a_buf(rw->buf, sizeof(uint64_t) * rw->count, 
FNV1A_64_INIT);
+       ret = fsetxattr(fd, ANAME_CHECKSUM, &checksum, sizeof(checksum), 0);
+       if (ret) {
+               eprintf("couldn't set xattr to %s, %m\n", path);
+               close(fd);
+               goto fail;
+       }
+
        close(fd);
 
        return;
-- 
1.5.6.5

-- 
sheepdog mailing list
[email protected]
http://lists.wpkg.org/mailman/listinfo/sheepdog

Reply via email to