[sheepdog] [PATCH v4 07/10] sheep: add operation to get object sha1 digest
MORITA Kazutaka
morita.kazutaka at gmail.com
Tue May 14 09:00:16 CEST 2013
From: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Currently, we compare entire object contents to check whether there is
no difference among them. However, this wastes a lot of network
bandwidth and some operations like vdi check or object recovery take
too long time to complete.
This adds an operation SD_OP_GET_HASH to get the sha1 digest of the
object, and enables us to do faster vdi check and recovery.
Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
---
include/internal_proto.h | 1 +
include/sha1.h | 1 +
include/sheepdog_proto.h | 5 +++++
lib/sha1.c | 15 +++++++++++++++
sheep/farm/farm.c | 1 +
sheep/farm/farm.h | 1 -
sheep/farm/sha1_file.c | 15 ---------------
sheep/ops.c | 18 ++++++++++++++++++
sheep/plain_store.c | 41 +++++++++++++++++++++++++++++++++++++++++
sheep/sheep_priv.h | 2 ++
10 files changed, 84 insertions(+), 16 deletions(-)
diff --git a/include/internal_proto.h b/include/internal_proto.h
index 995e213..a04af88 100644
--- a/include/internal_proto.h
+++ b/include/internal_proto.h
@@ -72,6 +72,7 @@
#define SD_OP_MD_INFO 0xB1
#define SD_OP_MD_PLUG 0xB2
#define SD_OP_MD_UNPLUG 0xB3
+#define SD_OP_GET_HASH 0xB4
/* internal flags for hdr.flags, must be above 0x80 */
#define SD_FLAG_CMD_RECOVERY 0x0080
diff --git a/include/sha1.h b/include/sha1.h
index 1043b30..332f5c1 100644
--- a/include/sha1.h
+++ b/include/sha1.h
@@ -23,5 +23,6 @@ struct sha1_ctx {
void sha1_init(void *ctx);
void sha1_update(void *ctx, const uint8_t *data, unsigned int len);
void sha1_final(void *ctx, uint8_t *out);
+const char *sha1_to_hex(const unsigned char *sha1);
#endif
diff --git a/include/sheepdog_proto.h b/include/sheepdog_proto.h
index 0916948..e211ce3 100644
--- a/include/sheepdog_proto.h
+++ b/include/sheepdog_proto.h
@@ -180,6 +180,11 @@ struct sd_rsp {
uint64_t store_size;
uint64_t store_free;
} node;
+ struct {
+ uint32_t __pad1;
+ uint32_t __pad2;
+ uint8_t digest[20];
+ } hash;
uint32_t __pad[8];
};
diff --git a/lib/sha1.c b/lib/sha1.c
index 8d3399a..c1ada09 100644
--- a/lib/sha1.c
+++ b/lib/sha1.c
@@ -197,3 +197,18 @@ void sha1_final(void *ctx, uint8_t *out)
/* Wipe context */
memset(sctx, 0, sizeof *sctx);
}
+
+const char *sha1_to_hex(const unsigned char *sha1)
+{
+ static __thread char buffer[50];
+ static const char hex[] = "0123456789abcdef";
+ char *buf = buffer;
+ int i;
+
+ for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
+ unsigned int val = *sha1++;
+ *buf++ = hex[val >> 4];
+ *buf++ = hex[val & 0xf];
+ }
+ return buffer;
+}
diff --git a/sheep/farm/farm.c b/sheep/farm/farm.c
index cca8bbd..c31c501 100644
--- a/sheep/farm/farm.c
+++ b/sheep/farm/farm.c
@@ -266,6 +266,7 @@ static struct store_driver farm = {
.format = default_format,
.purge_obj = default_purge_obj,
.remove_object = default_remove_object,
+ .get_hash = default_get_hash,
};
add_store_driver(farm);
diff --git a/sheep/farm/farm.h b/sheep/farm/farm.h
index 0fbdf12..41208e7 100644
--- a/sheep/farm/farm.h
+++ b/sheep/farm/farm.h
@@ -47,7 +47,6 @@ extern char farm_obj_dir[PATH_MAX];
char *sha1_to_path(const unsigned char *sha1);
int sha1_file_write(unsigned char *buf, unsigned len, unsigned char *);
void *sha1_file_read(const unsigned char *sha1, struct sha1_file_hdr *);
-char *sha1_to_hex(const unsigned char *sha1);
int get_sha1_hex(const char *hex, unsigned char *sha1);
int sha1_file_try_delete(const unsigned char *sha1);
diff --git a/sheep/farm/sha1_file.c b/sheep/farm/sha1_file.c
index 3883d95..dd29e23 100644
--- a/sheep/farm/sha1_file.c
+++ b/sheep/farm/sha1_file.c
@@ -256,18 +256,3 @@ int get_sha1_hex(const char *hex, unsigned char *sha1)
}
return 0;
}
-
-char *sha1_to_hex(const unsigned char *sha1)
-{
- static char buffer[50];
- static const char hex[] = "0123456789abcdef";
- char *buf = buffer;
- int i;
-
- for (i = 0; i < SHA1_LEN; i++) {
- unsigned int val = *sha1++;
- *buf++ = hex[val >> 4];
- *buf++ = hex[val & 0xf];
- }
- return buffer;
-}
diff --git a/sheep/ops.c b/sheep/ops.c
index e40fc65..8ab9ac3 100644
--- a/sheep/ops.c
+++ b/sheep/ops.c
@@ -761,6 +761,18 @@ static int local_md_unplug(const struct sd_req *req, struct sd_rsp *rsp,
return md_unplug_disks(disks);
}
+static int local_get_hash(struct request *request)
+{
+ struct sd_req *req = &request->rq;
+ struct sd_rsp *rsp = &request->rp;
+
+ if (!sd_store->get_hash)
+ return SD_RES_NO_SUPPORT;
+
+ return sd_store->get_hash(req->obj.oid, req->obj.tgt_epoch,
+ rsp->hash.digest);
+}
+
static int cluster_restore(const struct sd_req *req, struct sd_rsp *rsp,
void *data)
{
@@ -1247,6 +1259,12 @@ static struct sd_op_template sd_ops[] = {
.process_main = local_md_unplug,
},
+ [SD_OP_GET_HASH] = {
+ .name = "GET_HASH",
+ .type = SD_OP_TYPE_LOCAL,
+ .process_work = local_get_hash,
+ },
+
/* gateway I/O operations */
[SD_OP_CREATE_AND_WRITE_OBJ] = {
.name = "CREATE_AND_WRITE_OBJ",
diff --git a/sheep/plain_store.c b/sheep/plain_store.c
index c44a42f..3b71467 100644
--- a/sheep/plain_store.c
+++ b/sheep/plain_store.c
@@ -17,6 +17,7 @@
#include "sheep_priv.h"
#include "config.h"
+#include "sha1.h"
static int get_open_flags(uint64_t oid, bool create)
{
@@ -475,6 +476,45 @@ int default_remove_object(uint64_t oid)
return SD_RES_SUCCESS;
}
+int default_get_hash(uint64_t oid, uint32_t epoch, uint8_t *sha1)
+{
+ int ret;
+ void *buf;
+ struct siocb iocb = {};
+ struct sha1_ctx c;
+ uint64_t offset = 0;
+ uint32_t length;
+
+ length = get_objsize(oid);
+ buf = malloc(length);
+ if (buf == NULL)
+ return SD_RES_NO_MEM;
+
+ iocb.epoch = epoch;
+ iocb.buf = buf;
+ iocb.length = length;
+
+ ret = default_read(oid, &iocb);
+ if (ret != SD_RES_SUCCESS) {
+ free(buf);
+ return ret;
+ }
+
+ trim_zero_sectors(buf, &offset, &length);
+
+ sha1_init(&c);
+ sha1_update(&c, (uint8_t *)&offset, sizeof(offset));
+ sha1_update(&c, (uint8_t *)&length, sizeof(length));
+ sha1_update(&c, buf, length);
+ sha1_final(&c, sha1);
+ free(buf);
+
+ sd_dprintf("the message digest of %"PRIx64" at epoch %d is %s", oid,
+ epoch, sha1_to_hex(sha1));
+
+ return ret;
+}
+
int default_purge_obj(void)
{
uint32_t tgt_epoch = get_latest_epoch();
@@ -494,6 +534,7 @@ static struct store_driver plain_store = {
.cleanup = default_cleanup,
.format = default_format,
.remove_object = default_remove_object,
+ .get_hash = default_get_hash,
.purge_obj = default_purge_obj,
};
diff --git a/sheep/sheep_priv.h b/sheep/sheep_priv.h
index 27aec3f..56c512a 100644
--- a/sheep/sheep_priv.h
+++ b/sheep/sheep_priv.h
@@ -166,6 +166,7 @@ struct store_driver {
int (*read)(uint64_t oid, const struct siocb *);
int (*format)(void);
int (*remove_object)(uint64_t oid);
+ int (*get_hash)(uint64_t oid, uint32_t epoch, uint8_t *sha1);
/* Operations in recovery */
int (*link)(uint64_t oid, uint32_t tgt_epoch);
int (*update_epoch)(uint32_t epoch);
@@ -187,6 +188,7 @@ int default_update_epoch(uint32_t epoch);
int default_cleanup(void);
int default_format(void);
int default_remove_object(uint64_t oid);
+int default_get_hash(uint64_t oid, uint32_t epoch, uint8_t *sha1);
int default_purge_obj(void);
int for_each_object_in_wd(int (*func)(uint64_t, char *, void *), bool, void *);
int for_each_obj_path(int (*func)(char *path));
--
1.7.9.5
More information about the sheepdog
mailing list