From: Liu Yuan <tailai.ly at taobao.com> This is how we can deattach the volumes from sheep cluster storage. Usage: echo vdi_name > sheepfs_dir/vdi/unmount Signed-off-by: Liu Yuan <tailai.ly at taobao.com> --- include/sheep.h | 1 + sheep/ops.c | 20 ++++++++++++++++++++ sheepfs/core.c | 3 ++- sheepfs/sheepfs.h | 3 +++ sheepfs/vdi.c | 14 ++++++++++++++ sheepfs/volume.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 87 insertions(+), 2 deletions(-) diff --git a/include/sheep.h b/include/sheep.h index 36a4498..010e213 100644 --- a/include/sheep.h +++ b/include/sheep.h @@ -47,6 +47,7 @@ #define SD_OP_TRACE 0x95 #define SD_OP_TRACE_CAT 0x96 #define SD_OP_STAT_RECOVERY 0x97 +#define SD_OP_FLUSH_DEL_CACHE 0x98 #define SD_FLAG_CMD_IO_LOCAL 0x0010 #define SD_FLAG_CMD_RECOVERY 0x0020 diff --git a/sheep/ops.c b/sheep/ops.c index b4df70f..7ffa7db 100644 --- a/sheep/ops.c +++ b/sheep/ops.c @@ -605,6 +605,21 @@ static int local_flush_vdi(struct request *req) return SD_RES_SUCCESS; } +static int local_flush_and_del(const struct sd_req *req, struct sd_rsp *rsp, + void *data) +{ + struct sd_obj_req *hdr = (struct sd_obj_req *)req; + uint64_t oid = hdr->oid; + uint32_t vid = oid_to_vid(oid); + struct object_cache *cache = find_object_cache(vid, 0); + + if (cache) + if (object_cache_flush_and_delete(cache) < 0) + return SD_RES_EIO; + + return SD_RES_SUCCESS; +} + static int local_trace_ops(const struct sd_req *req, struct sd_rsp *rsp, void *data) { int enable = req->data_length, ret; @@ -971,6 +986,11 @@ static struct sd_op_template sd_ops[] = { .process_work = local_flush_vdi, }, + [SD_OP_FLUSH_DEL_CACHE] = { + .type = SD_OP_TYPE_LOCAL, + .process_work = local_flush_and_del, + }, + [SD_OP_TRACE] = { .type = SD_OP_TYPE_LOCAL, .force = 1, diff --git a/sheepfs/core.c b/sheepfs/core.c index 7da6674..9e24e20 100644 --- a/sheepfs/core.c +++ b/sheepfs/core.c @@ -51,7 +51,8 @@ static struct sheepfs_file_operation { [OP_NULL] = { NULL, NULL, NULL }, [OP_CLUSTER_INFO] = { cluster_info_read, NULL, cluster_info_get_size }, [OP_VDI_LIST] = { vdi_list_read, NULL, vdi_list_get_size }, - [OP_VDI_MOUNT] = { NULL, vdi_mount_write, NULL }, + [OP_VDI_MOUNT] = { NULL, vdi_mount_write }, + [OP_VDI_UNMOUNT] = { NULL, vdi_unmount_write }, [OP_VOLUME] = { volume_read, volume_write, volume_get_size, volume_sync, volume_open }, }; diff --git a/sheepfs/sheepfs.h b/sheepfs/sheepfs.h index e0be541..9e2d4bc 100644 --- a/sheepfs/sheepfs.h +++ b/sheepfs/sheepfs.h @@ -8,6 +8,7 @@ enum sheepfs_opcode { OP_CLUSTER_INFO, OP_VDI_LIST, OP_VDI_MOUNT, + OP_VDI_UNMOUNT, OP_VOLUME, }; @@ -34,6 +35,7 @@ extern int volume_read(const char *path, char *buf, size_t size, off_t offset); extern int volume_write(const char *, const char *buf, size_t size, off_t); extern size_t volume_get_size(const char *); extern int volume_create_entry(const char *entry); +extern int volume_remove_entry(const char *entry); extern int volume_sync(const char *path); extern int volume_open(const char *path, struct fuse_file_info *); @@ -48,5 +50,6 @@ extern int vdi_list_read(const char *path, char *buf, size_t size, off_t); extern size_t vdi_list_get_size(const char *path); extern int vdi_mount_write(const char *, const char *buf, size_t size, off_t); +extern int vdi_unmount_write(const char *, const char *buf, size_t, off_t); #endif diff --git a/sheepfs/vdi.c b/sheepfs/vdi.c index 9414d13..e7888da 100644 --- a/sheepfs/vdi.c +++ b/sheepfs/vdi.c @@ -27,6 +27,7 @@ #define PATH_VDI "/vdi" #define PATH_VDI_LIST "/vdi/list" #define PATH_VDI_MOUNT "/vdi/mount" +#define PATH_VDI_UNMOUNT "/vdi/unmount" int create_vdi_layout(void) { @@ -43,6 +44,11 @@ int create_vdi_layout(void) if (sheepfs_set_op(PATH_VDI_MOUNT, OP_VDI_MOUNT) < 0) return -1; + if (shadow_file_create(PATH_VDI_UNMOUNT) < 0) + return -1; + if (sheepfs_set_op(PATH_VDI_UNMOUNT, OP_VDI_UNMOUNT) < 0) + return -1; + return 0; } @@ -71,3 +77,11 @@ int vdi_mount_write(const char *path, const char *buf, size_t size, return -EINVAL; return size; } + +int vdi_unmount_write(const char *path, const char *buf, size_t size, + off_t ignore) +{ + if (volume_remove_entry(buf) < 0) + return -EINVAL; + return size; +} diff --git a/sheepfs/volume.c b/sheepfs/volume.c index 94f35b4..8905c63 100644 --- a/sheepfs/volume.c +++ b/sheepfs/volume.c @@ -21,6 +21,7 @@ #include <assert.h> #include <syslog.h> +#include "sheep.h" #include "strbuf.h" #include "sheepfs.h" #include "net.h" @@ -237,7 +238,7 @@ static int volume_do_sync(uint32_t vid) hdr.opcode = SD_OP_FLUSH_VDI; hdr.oid = vid_to_vdi_oid(vid); - ret = exec_req(sheep_fd, (struct sd_req *)&hdr, NULL, &wlen, &rlen); + ret = exec_req(0, (struct sd_req *)&hdr, NULL, &wlen, &rlen); if (ret || rsp->result != SD_RES_SUCCESS) { syslog(LOG_ERR, "[%s] failed to flush vdi %"PRIx32"\n", @@ -342,3 +343,48 @@ int volume_create_entry(const char *entry) return 0; } + +static int volume_sync_and_delete(uint32_t vid) +{ + struct sd_obj_req hdr = { 0 }; + struct sd_obj_rsp *rsp = (struct sd_obj_rsp *)&hdr; + int ret; + unsigned wlen = 0, rlen = 0; + + hdr.opcode = SD_OP_FLUSH_DEL_CACHE; + hdr.oid = vid_to_vdi_oid(vid); + + ret = exec_req(0, (struct sd_req *)&hdr, NULL, &wlen, &rlen); + + if (ret || rsp->result != SD_RES_SUCCESS) { + syslog(LOG_ERR, "[%s] failed to flush vdi %" PRIx32 "\n", + __func__, vid); + return -1; + } + + return 0; +} + +int volume_remove_entry(const char *entry) +{ + char path[PATH_MAX], *ch; + uint32_t vid; + + ch = strchr(entry, '\n'); + if (ch != NULL) + *ch = '\0'; + + sprintf(path, "%s/%s", PATH_VOLUME, entry); + if (!shadow_file_exsit(path)) + return -1; + + if (shadow_file_getxattr(path, SH_VID_NAME, &vid, SH_VID_SIZE) < 0) + return -1; + + if (volume_sync_and_delete(vid) < 0) + return -1; + + shadow_file_delete(path); + + return 0; +} -- 1.7.10.2 |