summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorM. Mohan Kumar <mohan@in.ibm.com>2012-11-29 21:46:07 +0530
committerVijay Bellur <vbellur@redhat.com>2012-11-29 09:40:14 -0800
commit983d290f7b36fea580ed9337bdc15e8f0f6f5bb3 (patch)
tree7437660f9427ca9fb1bbf5432b38dc35f7351389
parent3c72850e8d00f0cf35ae054136be076a394e08e9 (diff)
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 <volname>:<vg>/<lv> <newlv> $ gluster bd snapshot <volname>:<vg>/<lv> <snap_lv> <size> BUG: 805138 Change-Id: Idc2ac14525a3998329c742bf85a06326cac8cd54 Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com> Reviewed-on: http://review.gluster.org/3719 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Vijay Bellur <vbellur@redhat.com>
-rw-r--r--cli/src/cli-cmd-parser.c2
-rw-r--r--cli/src/cli-cmd-volume-bdevice.c47
-rw-r--r--cli/src/cli-rpc-ops.c6
-rw-r--r--rpc/rpc-lib/src/protocol-common.h2
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volume-ops.c19
-rw-r--r--xlators/storage/bd_map/src/bd_map.c106
6 files changed, 170 insertions, 12 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c
index f7ee29a1..ae754b97 100644
--- a/cli/src/cli-cmd-parser.c
+++ b/cli/src/cli-cmd-parser.c
@@ -369,7 +369,7 @@ cli_cmd_volume_create_parse (const char **words, int wordcount, dict_t **options
cli_err ("Block Device backend volume does not support multiple"
" bricks");
gf_log ("", GF_LOG_ERROR,
- "Block Device backend volumer does not support multiple"
+ "Block Device backend volume does not support multiple"
" bricks");
ret = -1;
goto out;
diff --git a/cli/src/cli-cmd-volume-bdevice.c b/cli/src/cli-cmd-volume-bdevice.c
index ea7edab6..19325754 100644
--- a/cli/src/cli-cmd-volume-bdevice.c
+++ b/cli/src/cli-cmd-volume-bdevice.c
@@ -41,6 +41,8 @@ cli_cmd_bd_parse (dict_t *dict, const char **words)
char *size = NULL;
char *eptr = NULL;
gf_xl_bd_op_t bd_op = GF_BD_OP_INVALID;
+ char *dest_lv = NULL;
+
/* volname:/path */
if (!strchr (words[2], ':') || !strchr (words[2], '/')) {
@@ -64,6 +66,10 @@ cli_cmd_bd_parse (dict_t *dict, const char **words)
bd_op = GF_BD_OP_NEW_BD;
else if (!strcasecmp (words[1], "delete"))
bd_op = GF_BD_OP_DELETE_BD;
+ else if (!strcasecmp (words[1], "clone"))
+ bd_op = GF_BD_OP_CLONE_BD;
+ else if (!strcasecmp (words[1], "snapshot"))
+ bd_op = GF_BD_OP_SNAPSHOT_BD;
else
return -1;
@@ -83,6 +89,30 @@ cli_cmd_bd_parse (dict_t *dict, const char **words)
ret = dict_set_dynstr (dict, "size", size);
if (ret)
goto out;
+ } else if (bd_op == GF_BD_OP_SNAPSHOT_BD ||
+ bd_op == GF_BD_OP_CLONE_BD) {
+ /*
+ * dest_lv should be just dest_lv, we don't support
+ * cloning/snapshotting to a different volume or vg
+ */
+ if (strchr (words[3], ':') || strchr (words[3], '/')) {
+ cli_err ("invalid parameter %s, volname/vg not needed",
+ words[3]);
+ ret = -1;
+ goto out;
+ }
+ dest_lv = gf_strdup (words[3]);
+ ret = dict_set_dynstr (dict, "dest_lv", dest_lv);
+ if (ret)
+ goto out;
+
+ /* clone needs size as parameter */
+ if (bd_op == GF_BD_OP_SNAPSHOT_BD) {
+ ret = dict_set_dynstr (dict, "size",
+ gf_strdup (words[4]));
+ if (ret)
+ goto out;
+ }
}
ret = 0;
@@ -94,13 +124,15 @@ out:
/*
* bd create <volname>:/path <size>
* bd delete <volname>:/path
+ * bd clone <volname>:/path <newbd>
+ * bd snapshot <volname>:/<path> <newbd> <size>
*/
int32_t
cli_cmd_bd_validate (const char **words, int wordcount, dict_t **options)
{
dict_t *dict = NULL;
int ret = -1;
- char *op[] = { "create", "delete", NULL };
+ char *op[] = { "create", "delete", "clone", "snapshot", NULL };
int index = 0;
for (index = 0; op[index]; index++)
@@ -120,6 +152,12 @@ cli_cmd_bd_validate (const char **words, int wordcount, dict_t **options)
} else if (!strcasecmp (words[1], "delete")) {
if (wordcount != 3)
goto out;
+ } else if (!strcasecmp (words[1], "clone")) {
+ if (wordcount != 4)
+ goto out;
+ } else if (!strcasecmp (words[1], "snapshot")) {
+ if (wordcount != 5)
+ goto out;
} else {
ret = -1;
goto out;
@@ -193,6 +231,13 @@ struct cli_cmd cli_bd_cmds[] = {
{ "bd delete <volname>:<bd>",
cli_cmd_bd_cbk,
"Delete a block device"},
+ { "bd clone <volname>:<bd> <newbd>",
+ cli_cmd_bd_cbk,
+ "clone device"},
+ { "bd snapshot <volname>:<bd> <newbd> <size>",
+ cli_cmd_bd_cbk,
+ "\n\tsnapshot device where size can be "
+ "suffixed with KB, MB etc. Default size is in MB"},
{ NULL, NULL, NULL }
};
diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c
index 9e4e03d0..da239b51 100644
--- a/cli/src/cli-rpc-ops.c
+++ b/cli/src/cli-rpc-ops.c
@@ -2647,6 +2647,12 @@ gf_cli_bd_op_cbk (struct rpc_req *req, struct iovec *iov,
case GF_BD_OP_DELETE_BD:
operation = gf_strdup ("delete");
break;
+ case GF_BD_OP_CLONE_BD:
+ operation = gf_strdup ("clone");
+ break;
+ case GF_BD_OP_SNAPSHOT_BD:
+ operation = gf_strdup ("snapshot");
+ break;
default:
break;
}
diff --git a/rpc/rpc-lib/src/protocol-common.h b/rpc/rpc-lib/src/protocol-common.h
index 38528bd5..97017e5f 100644
--- a/rpc/rpc-lib/src/protocol-common.h
+++ b/rpc/rpc-lib/src/protocol-common.h
@@ -211,6 +211,8 @@ typedef enum {
GF_BD_OP_INVALID,
GF_BD_OP_NEW_BD,
GF_BD_OP_DELETE_BD,
+ GF_BD_OP_CLONE_BD,
+ GF_BD_OP_SNAPSHOT_BD,
} gf_xl_bd_op_t ;
#define GLUSTER_HNDSK_PROGRAM 14398633 /* Completely random */
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;