From 983d290f7b36fea580ed9337bdc15e8f0f6f5bb3 Mon Sep 17 00:00:00 2001 From: "M. Mohan Kumar" Date: Thu, 29 Nov 2012 21:46:07 +0530 Subject: BD Backend: CLI to create a full/linked clone of a image A new CLI command added to support cloning/snapshotting of a LV device Syntax is: $ gluster bd clone :/ $ gluster bd snapshot :/ BUG: 805138 Change-Id: Idc2ac14525a3998329c742bf85a06326cac8cd54 Signed-off-by: M. Mohan Kumar Reviewed-on: http://review.gluster.org/3719 Tested-by: Gluster Build System Reviewed-by: Vijay Bellur --- xlators/mgmt/glusterd/src/glusterd-volume-ops.c | 19 ++++- xlators/storage/bd_map/src/bd_map.c | 106 ++++++++++++++++++++++-- 2 files changed, 115 insertions(+), 10 deletions(-) (limited to 'xlators') diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c index b74bbec7..db143d5f 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c +++ b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c @@ -1295,6 +1295,24 @@ glusterd_op_stage_bd (dict_t *dict, char **op_errstr) ret = -1; goto out; } + } else if (bd_op == GF_BD_OP_SNAPSHOT_BD) { + ret = dict_get_str (dict, "size", &size); + if (ret) { + snprintf (msg, sizeof(msg), "Failed to get size"); + gf_log ("", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + goto out; + } + + if (gf_string2bytesize (size, &bytes) < 0) { + ret = -1; + snprintf (msg, sizeof(msg), + "Invalid size %s, suffix with KB, MB etc", + size); + gf_log ("", GF_LOG_ERROR, "%s", msg); + *op_errstr = gf_strdup (msg); + goto out; + } } ret = glusterd_volinfo_find (volname, &volinfo); @@ -1324,7 +1342,6 @@ out: gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); return ret; } - #endif int diff --git a/xlators/storage/bd_map/src/bd_map.c b/xlators/storage/bd_map/src/bd_map.c index a84ee29f..9c8f69c6 100644 --- a/xlators/storage/bd_map/src/bd_map.c +++ b/xlators/storage/bd_map/src/bd_map.c @@ -371,10 +371,6 @@ int bd_clone_lv (bd_priv_t *priv, bd_entry_t *p_entry, dict_t *output, ret = 0; gf_log (THIS->name, GF_LOG_INFO, "Clone completed"); out: - for (i = 0; i < IOV_NR; i++) { - if (vec[i].iov_base) - GF_FREE (vec[i].iov_base); - } if (vg) lvm_vg_close (vg); if (fd1 != -1) @@ -387,7 +383,7 @@ out: } int bd_snapshot_lv (bd_priv_t *priv, bd_entry_t *p_entry, dict_t *output, - const char *lv_name, const char *dest_lv, uint64_t size, + const char *lv_name, const char *dest_lv, char *size, struct iatt *stbuf) { int32_t ret = -1; @@ -408,7 +404,7 @@ int bd_snapshot_lv (bd_priv_t *priv, bd_entry_t *p_entry, dict_t *output, runner_argprintf (&runner, "/dev/%s/%s", p_entry->name, lv_name); runner_add_args (&runner, "--name", NULL); runner_argprintf (&runner, "%s", dest_lv); - runner_argprintf (&runner, "-L%ld", size); + runner_argprintf (&runner, "-L%s", size); runner_start (&runner); runner_end (&runner); @@ -534,7 +530,7 @@ bd_symlink (call_frame_t *frame, xlator_t *this, memcpy (&preparent, lventry->parent->attr, sizeof(preparent)); if (bd_snapshot_lv (priv, lventry->parent, NULL, lventry->name, - name, 1, &stbuf) < 0) { + name, "1", &stbuf) < 0) { op_errno = EAGAIN; goto out; } @@ -2232,6 +2228,94 @@ out: return ret; } +int bd_xl_op_clone(bd_priv_t *priv, int subop, dict_t *input, dict_t *output) +{ + bd_entry_t *p_entry = NULL; + bd_entry_t *lventry = NULL; + int ret = -1; + char *error = NULL; + int retval = -1; + char *vg = NULL; + char *lv = NULL; + char *dest_lv = NULL; + char *size = NULL; + char *buff = NULL; + char *buffp = NULL; + char *path = NULL; + char *save = NULL; + char *npath = NULL; + + ret = dict_get_str (input, "path", &path); + ret = dict_get_str (input, "dest_lv", &dest_lv); + ret = dict_get_str (input, "size", &size); + + if (!path || !dest_lv) { + gf_asprintf (&error, "invalid arguments"); + ret = -1; + goto out; + } + + buff = buffp = gf_strdup (path); + + vg = strtok_r (buff, "/", &save); + lv = strtok_r (NULL, "/", &save); + if (!lv) { + gf_asprintf (&error, "lv not given %s", path); + ret = -1; + goto out; + } + + BD_ENTRY (priv, p_entry, vg); + if (!p_entry) { + gf_asprintf (&error, "%s does not exist", vg); + retval = dict_set_str (output, "error", error); + goto out; + } + + BD_ENTRY (priv, lventry, path); + if (!lventry) { + gf_asprintf (&error, "%s does not exist", path); + ret = -1; + goto out; + } + BD_PUT_ENTRY (priv, lventry); + lventry = NULL; + gf_asprintf (&npath, "/%s/%s", vg, dest_lv); + BD_ENTRY (priv, lventry, npath); + if (lventry) { + gf_asprintf (&error, "%s already exists", dest_lv); + BD_PUT_ENTRY (priv, lventry); + ret = -1; + goto out; + } + + if (subop == GF_BD_OP_SNAPSHOT_BD) { + if (!size) { + gf_asprintf (&error, "size not given"); + ret = -1; + goto out; + } + ret = bd_snapshot_lv (priv, p_entry, output, lv, dest_lv, + size, NULL); + } else + ret = bd_clone_lv (priv, p_entry, output, vg, lv, dest_lv, + NULL); + + if (ret) + goto out; + ret = 0; +out: + if (error) + retval = dict_set_dynstr (output, "error", error); + if (p_entry) + BD_PUT_ENTRY (priv, p_entry); + if (npath) + GF_FREE (npath); + if (buffp) + GF_FREE (buffp); + return ret; +} + int32_t bd_notify (xlator_t *this, dict_t *input, dict_t *output) { @@ -2246,7 +2330,7 @@ bd_notify (xlator_t *this, dict_t *input, dict_t *output) ret = dict_get_int32 (input, "bd-op", (int32_t *)&bdop); if (ret) { - asprintf (&error, "no sub-op specified"); + gf_asprintf (&error, "no sub-op specified"); goto out; } @@ -2258,6 +2342,10 @@ bd_notify (xlator_t *this, dict_t *input, dict_t *output) case GF_BD_OP_DELETE_BD: ret = bd_xl_op_delete (priv, input, output); break; + case GF_BD_OP_CLONE_BD: + case GF_BD_OP_SNAPSHOT_BD: + ret = bd_xl_op_clone (priv, bdop, input, output); + break; default: gf_asprintf (&error, "invalid bd-op %d specified", bdop); retval = dict_set_dynstr (output, "error", error); @@ -2278,7 +2366,7 @@ notify (xlator_t *this, ...) { va_list ap; - int ret = -1; + int ret = 0; void *data2 = NULL; dict_t *input = NULL; dict_t *output = NULL; -- cgit