Currently, Sheepdog doesn't clean up vdi attributes when we delete the vdi. So if we create a new vdi whose name was used before, we could read the old attribute. This patch adds a vdi creation time to the attribute header and checks whether the attribute belongs to the current vdi. Note that this is a transitional approach. In future, we should remove vdi attributes when we remove the vdi. Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp> --- collie/vdi.c | 17 +++++++---------- include/sheepdog_proto.h | 13 +++++++++++-- sheep/group.c | 7 ++++--- sheep/sheep_priv.h | 7 ++++--- sheep/vdi.c | 39 ++++++++++++++++++++++----------------- 5 files changed, 48 insertions(+), 35 deletions(-) diff --git a/collie/vdi.c b/collie/vdi.c index 27b0595..18c0171 100644 --- a/collie/vdi.c +++ b/collie/vdi.c @@ -791,16 +791,13 @@ static int find_vdi_attr_oid(char *vdiname, char *tag, uint32_t snapid, struct sd_vdi_rsp *rsp = (struct sd_vdi_rsp *)&hdr; int fd, ret; unsigned int wlen, rlen; - char buf[SD_ATTR_HEADER_SIZE]; + struct sheepdog_vdi_attr vattr; - memset(buf, 0, sizeof(buf)); - strncpy(buf, vdiname, SD_MAX_VDI_LEN); - strncpy(buf + SD_MAX_VDI_LEN, vdi_cmd_data.snapshot_tag, - SD_MAX_VDI_TAG_LEN); - memcpy(buf + SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN, - &vdi_cmd_data.snapshot_id, sizeof(uint32_t)); - strncpy(buf + SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN + sizeof(uint32_t), - key, SD_MAX_VDI_ATTR_KEY_LEN); + memset(&vattr, 0, sizeof(vattr)); + strncpy(vattr.name, vdiname, SD_MAX_VDI_LEN); + strncpy(vattr.tag, vdi_cmd_data.snapshot_tag, SD_MAX_VDI_TAG_LEN); + vattr.snap_id = vdi_cmd_data.snapshot_id; + strncpy(vattr.key, key, SD_MAX_VDI_ATTR_KEY_LEN); fd = connect_to(sdhost, sdport); if (fd < 0) { @@ -821,7 +818,7 @@ static int find_vdi_attr_oid(char *vdiname, char *tag, uint32_t snapid, if (excl) hdr.flags |= SD_FLAG_CMD_EXCL; - ret = exec_req(fd, (struct sd_req *)&hdr, buf, &wlen, &rlen); + ret = exec_req(fd, (struct sd_req *)&hdr, &vattr, &wlen, &rlen); if (ret) { ret = SD_RES_EIO; goto out; diff --git a/include/sheepdog_proto.h b/include/sheepdog_proto.h index 2b042f4..75e27e5 100644 --- a/include/sheepdog_proto.h +++ b/include/sheepdog_proto.h @@ -87,8 +87,7 @@ #define SD_INODE_SIZE (sizeof(struct sheepdog_inode)) #define SD_INODE_HEADER_SIZE (sizeof(struct sheepdog_inode) - \ sizeof(uint32_t) * MAX_DATA_OBJS) -#define SD_ATTR_HEADER_SIZE (SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN + \ - sizeof(uint32_t) + SD_MAX_VDI_ATTR_KEY_LEN) +#define SD_ATTR_HEADER_SIZE (sizeof(struct sheepdog_vdi_attr)) #define CURRENT_VDI_ID 0 struct sd_req { @@ -185,6 +184,16 @@ struct sheepdog_inode { uint32_t data_vdi_id[MAX_DATA_OBJS]; }; +struct sheepdog_vdi_attr { + char name[SD_MAX_VDI_LEN]; + char tag[SD_MAX_VDI_TAG_LEN]; + uint64_t ctime; + uint32_t snap_id; + uint32_t value_len; + char key[SD_MAX_VDI_ATTR_KEY_LEN]; + char value[0]; +}; + /* * 64 bit FNV-1a non-zero initial basis */ diff --git a/sheep/group.c b/sheep/group.c index f6743f5..0a6d0b0 100644 --- a/sheep/group.c +++ b/sheep/group.c @@ -853,6 +853,7 @@ static void vdi_op(struct vdi_op_message *msg) void *data = msg->data; int ret = SD_RES_SUCCESS; uint32_t vid = 0, attrid = 0, nr_copies = sys->nr_sobjs; + uint64_t ctime = 0; switch (hdr->opcode) { case SD_OP_NEW_VDI: @@ -871,14 +872,14 @@ static void vdi_op(struct vdi_op_message *msg) break; } ret = lookup_vdi(hdr->epoch, data, hdr->data_length, &vid, - hdr->snapid, &nr_copies); + hdr->snapid, &nr_copies, NULL); if (ret != SD_RES_SUCCESS) break; break; case SD_OP_GET_VDI_ATTR: ret = lookup_vdi(hdr->epoch, data, min(SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN, hdr->data_length), - &vid, hdr->snapid, &nr_copies); + &vid, hdr->snapid, &nr_copies, &ctime); if (ret != SD_RES_SUCCESS) break; /* the curernt vdi id can change if we take the snapshot, @@ -886,7 +887,7 @@ static void vdi_op(struct vdi_op_message *msg) vid = fnv_64a_buf(data, strlen(data), FNV1A_64_INIT); vid &= SD_NR_VDIS - 1; ret = get_vdi_attr(hdr->epoch, data, hdr->data_length, vid, - &attrid, nr_copies, + &attrid, nr_copies, ctime, hdr->flags & SD_FLAG_CMD_CREAT, hdr->flags & SD_FLAG_CMD_EXCL); break; diff --git a/sheep/sheep_priv.h b/sheep/sheep_priv.h index e2fcb40..b292548 100644 --- a/sheep/sheep_priv.h +++ b/sheep/sheep_priv.h @@ -175,12 +175,13 @@ int del_vdi(uint32_t epoch, char *data, int data_len, uint32_t *vid, uint32_t snapid, unsigned int *nr_copies); int lookup_vdi(uint32_t epoch, char *data, int data_len, uint32_t *vid, - uint32_t snapid, unsigned int *nr_copies); + uint32_t snapid, unsigned int *nr_copies, uint64_t *ctime); int read_vdis(char *data, int len, unsigned int *rsp_len); -int get_vdi_attr(uint32_t epoch, char *data, int data_len, uint32_t vid, - uint32_t *attrid, int copies, int creat, int excl); +int get_vdi_attr(uint32_t epoch, struct sheepdog_vdi_attr *vattr, int data_len, + uint32_t vid, uint32_t *attrid, int copies, uint64_t ctime, + int creat, int excl); int get_ordered_sd_node_list(struct sheepdog_node_list_entry *entries); void setup_ordered_sd_vnode_list(struct request *req); diff --git a/sheep/vdi.c b/sheep/vdi.c index 392d429..1526afe 100644 --- a/sheep/vdi.c +++ b/sheep/vdi.c @@ -159,7 +159,7 @@ out: static int find_first_vdi(uint32_t epoch, unsigned long start, unsigned long end, char *name, char *tag, uint32_t snapid, uint32_t *vid, unsigned long *deleted_nr, uint32_t *next_snap, - unsigned int *nr_copies) + unsigned int *nr_copies, uint64_t *ctime) { struct sheepdog_vnode_list_entry *entries; struct sheepdog_inode *inode = NULL; @@ -206,6 +206,8 @@ static int find_first_vdi(uint32_t epoch, unsigned long start, unsigned long end *next_snap = inode->snap_id + 1; *vid = inode->vdi_id; *nr_copies = inode->nr_copies; + if (ctime) + *ctime = inode->ctime; ret = SD_RES_SUCCESS; goto out; } @@ -226,7 +228,7 @@ out: static int do_lookup_vdi(uint32_t epoch, char *name, int namelen, uint32_t *vid, char *tag, uint32_t snapid, uint32_t *next_snapid, unsigned long *right_nr, unsigned long *deleted_nr, - unsigned int *nr_copies) + unsigned int *nr_copies, uint64_t *ctime) { int ret; unsigned long nr, start_nr; @@ -244,7 +246,7 @@ static int do_lookup_vdi(uint32_t epoch, char *name, int namelen, uint32_t *vid, right_side: /* look up on the right side of the hash point */ ret = find_first_vdi(epoch, nr - 1, start_nr, name, tag, snapid, vid, - deleted_nr, next_snapid, nr_copies); + deleted_nr, next_snapid, nr_copies, ctime); return ret; } else { /* round up... bitmap search from the head of the bitmap */ @@ -255,7 +257,7 @@ static int do_lookup_vdi(uint32_t epoch, char *name, int namelen, uint32_t *vid, else if (nr) { /* look up on the left side of the hash point */ ret = find_first_vdi(epoch, nr - 1, 0, name, tag, snapid, vid, - deleted_nr, next_snapid, nr_copies); + deleted_nr, next_snapid, nr_copies, ctime); if (ret == SD_RES_NO_VDI) ; /* we need to go to the right side */ else @@ -268,7 +270,7 @@ static int do_lookup_vdi(uint32_t epoch, char *name, int namelen, uint32_t *vid, } int lookup_vdi(uint32_t epoch, char *data, int data_len, uint32_t *vid, - uint32_t snapid, unsigned int *nr_copies) + uint32_t snapid, unsigned int *nr_copies, uint64_t *ctime) { char *name = data, *tag; uint32_t dummy0; @@ -282,7 +284,7 @@ int lookup_vdi(uint32_t epoch, char *data, int data_len, uint32_t *vid, return SD_RES_INVALID_PARMS; return do_lookup_vdi(epoch, name, strlen(name), vid, tag, snapid, - &dummy0, &dummy1, &dummy2, nr_copies); + &dummy0, &dummy1, &dummy2, nr_copies, ctime); } int add_vdi(uint32_t epoch, char *data, int data_len, uint64_t size, @@ -301,7 +303,7 @@ int add_vdi(uint32_t epoch, char *data, int data_len, uint64_t size, name = data; ret = do_lookup_vdi(epoch, name, strlen(name), &cur_vid, NULL, 0, &next_snapid, - &right_nr, &deleted_nr, nr_copies); + &right_nr, &deleted_nr, nr_copies, NULL); if (is_snapshot) { if (ret != SD_RES_SUCCESS) { @@ -375,7 +377,7 @@ int del_vdi(uint32_t epoch, char *data, int data_len, uint32_t *vid, } ret = do_lookup_vdi(epoch, name, strlen(name), vid, tag, snapid, - &dummy0, &dummy1, &dummy2, nr_copies); + &dummy0, &dummy1, &dummy2, nr_copies, NULL); if (ret != SD_RES_SUCCESS) goto out; @@ -658,11 +660,12 @@ err: return ret; } -int get_vdi_attr(uint32_t epoch, char *data, int data_len, uint32_t vid, - uint32_t *attrid, int copies, int creat, int excl) +int get_vdi_attr(uint32_t epoch, struct sheepdog_vdi_attr *vattr, int data_len, + uint32_t vid, uint32_t *attrid, int copies, uint64_t ctime, + int creat, int excl) { struct sheepdog_vnode_list_entry *entries; - char attr_buf[SD_ATTR_HEADER_SIZE]; + struct sheepdog_vdi_attr tmp_attr; uint64_t oid; uint32_t end; int ret, nr_zones, nr_vnodes; @@ -679,20 +682,22 @@ int get_vdi_attr(uint32_t epoch, char *data, int data_len, uint32_t vid, goto out; } + vattr->ctime = ctime; + get_ordered_sd_vnode_list(entries, &nr_vnodes, &nr_zones); - *attrid = fnv_64a_buf(data, data_len, FNV1A_64_INIT); + *attrid = fnv_64a_buf(vattr, data_len, FNV1A_64_INIT); *attrid &= (UINT64_C(1) << VDI_SPACE_SHIFT) - 1; end = *attrid - 1; while (*attrid != end) { oid = vid_to_attr_oid(vid, *attrid); - ret = read_object(entries, nr_vnodes, nr_zones, epoch, oid, attr_buf, - sizeof(attr_buf), 0, copies); + ret = read_object(entries, nr_vnodes, nr_zones, epoch, oid, (char *)&tmp_attr, + sizeof(tmp_attr), 0, copies); if (ret == -SD_RES_NO_OBJ && creat) { - ret = write_object(entries, nr_vnodes, nr_zones, epoch, oid, data, - data_len, 0, copies, 1); + ret = write_object(entries, nr_vnodes, nr_zones, epoch, oid, + (char *)vattr, data_len, 0, copies, 1); if (ret) ret = SD_RES_EIO; else @@ -703,7 +708,7 @@ int get_vdi_attr(uint32_t epoch, char *data, int data_len, uint32_t vid, if (ret < 0) return -ret; - if (memcmp(attr_buf, data, sizeof(attr_buf)) == 0) { + if (memcmp(&tmp_attr, vattr, sizeof(tmp_attr)) == 0) { if (excl) ret = SD_RES_VDI_EXIST; else -- 1.7.2.5 |