From 96f6c5159da92500e8ddb21a487d2848a2b1f7db Mon Sep 17 00:00:00 2001 From: Vijaikumar M Date: Thu, 13 Feb 2014 16:32:12 +0530 Subject: glusterd/snapshot: Use snap uuid to create lvm snapshot Using snap uuid to create lvm snapshot will solve the problem of having '-' in the snap name or snap name is too long. Change-Id: If204f02a8f5de599fb409d06c7893ef3542a6300 BUG: 1045333 Signed-off-by: Vijaikumar M Reviewed-on: http://review.gluster.org/6709 Reviewed-by: Rajesh Joseph Tested-by: Rajesh Joseph --- xlators/mgmt/glusterd/src/glusterd-handler.c | 1 - xlators/mgmt/glusterd/src/glusterd-handshake.c | 102 ++++++++++++---- xlators/mgmt/glusterd/src/glusterd-snapshot.c | 154 +++++++++++++++---------- xlators/mgmt/glusterd/src/glusterd-store.c | 10 +- xlators/mgmt/glusterd/src/glusterd.h | 14 +++ 5 files changed, 188 insertions(+), 93 deletions(-) (limited to 'xlators/mgmt') diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index d109e11bd..ec13c8528 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -338,7 +338,6 @@ glusterd_add_volume_detail_to_dict (glusterd_volinfo_t *volinfo, char *volume_id_str = NULL; struct args_pack pack = {0,}; xlator_t *this = NULL; - int caps = 0; GF_ASSERT (volinfo); GF_ASSERT (volumes); diff --git a/xlators/mgmt/glusterd/src/glusterd-handshake.c b/xlators/mgmt/glusterd/src/glusterd-handshake.c index dbf342cbc..a1368e211 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handshake.c +++ b/xlators/mgmt/glusterd/src/glusterd-handshake.c @@ -42,19 +42,21 @@ static size_t build_volfile_path (const char *volname, char *path, size_t path_len, char *trusted_str) { - struct stat stbuf = {0,}; - int32_t ret = -1; - glusterd_conf_t *priv = NULL; - char *vol = NULL; - char *dup_volname = NULL; - char *free_ptr = NULL; - char *tmp = NULL; - glusterd_volinfo_t *volinfo = NULL; - char *server = NULL; - gf_boolean_t snap_volume = _gf_false; - char *str = NULL; - char *tmp_volname = NULL; - char *input_vol = NULL; + struct stat stbuf = {0,}; + int32_t ret = -1; + glusterd_conf_t *priv = NULL; + char *vol = NULL; + char *dup_volname = NULL; + char *free_ptr = NULL; + char *tmp = NULL; + glusterd_volinfo_t *volinfo = NULL; + glusterd_volinfo_t *parent_volinfo = NULL; + glusterd_snap_t *snap = NULL; + char *server = NULL; + gf_boolean_t snap_volume = _gf_false; + char *str = NULL; + char *parent_volname = NULL; + char *input_vol = NULL; priv = THIS->private; @@ -64,17 +66,53 @@ build_volfile_path (const char *volname, char *path, path, path_len); ret = 1; goto out; - } else if (strstr (volname, "/snaps/")) { - input_vol = gf_strdup (volname); + } else if ((tmp = strstr (volname, "/snaps/"))) { + /* Input volname will have below formats: + /snaps// + or + /snaps/snapname + + We need to extract snap uuid from the input volname */ + snap_volume = _gf_true; + input_vol = gf_strdup (volname); + if (!input_vol) + goto out; + parent_volname = strtok_r (input_vol, "/", &str); + if (!parent_volname) + goto out; + str = strrchr (volname, '/'); if (str) str++; - dup_volname = gf_strdup (str); + + tmp = strstr (tmp+1, "/"); + while(*tmp && *tmp == '/') + tmp++; + + /* User has provided snapname from the mountpoint. + Map the snapname to uuid to find the volfile */ + if (tmp == str) { + ret = glusterd_volinfo_find (parent_volname, + &parent_volinfo); + if (ret) { + gf_log(THIS->name, GF_LOG_ERROR, "Failed to " + "find parent volinfo for snap %s", str); + goto out; + } + snap = glusterd_find_snap_by_name (parent_volinfo, str); + if (!snap) { + gf_log(THIS->name, GF_LOG_ERROR, "Failed to " + "fetch snap %s", str); + ret = -1; + goto out; + } + dup_volname = gf_strdup (snap->snap_volume->volname); + } else { + dup_volname = gf_strdup (str); + } str = NULL; - tmp_volname = strtok_r (input_vol, "/", &str); - if (!tmp_volname) - goto out; + } else if (volname[0] != '/') { /* Normal behavior */ dup_volname = gf_strdup (volname); @@ -85,9 +123,23 @@ build_volfile_path (const char *volname, char *path, dup_volname = gf_strdup (&volname[1]); } + if (!dup_volname) { + gf_log(THIS->name, GF_LOG_ERROR, "strdup failed"); + ret = -1; + goto out; + } free_ptr = dup_volname; - ret = glusterd_volinfo_find (dup_volname, &volinfo); + if (!snap_volume) { + ret = glusterd_volinfo_find (dup_volname, &volinfo); + } else { + ret = 0; + if (snap) + volinfo = snap->snap_volume; + else + ret = glusterd_snap_volinfo_find (dup_volname,&volinfo); + } + if (ret) { /* Split the volume name */ vol = strtok_r (dup_volname, ".", &tmp); @@ -125,9 +177,9 @@ build_volfile_path (const char *volname, char *path, dup_volname); else snprintf (path, path_len, - "%s/vols/%s/snaps/%s/%s%s-fuse.vol", - priv->workdir, tmp_volname, volinfo->volname, - (trusted_str ? trusted_str:""), dup_volname); + "%s/vols/%s/snaps/%s/%s%s-fuse.vol", + priv->workdir, parent_volname, volinfo->volname, + (trusted_str ? trusted_str:""), dup_volname); ret = stat (path, &stbuf); } @@ -139,8 +191,8 @@ build_volfile_path (const char *volname, char *path, else snprintf (path, path_len, "%s/vols/%s/snaps/%s/%s-tcp.vol", - priv->workdir, tmp_volname, volinfo->volname, - volname); + priv->workdir, parent_volname, + volinfo->volname, volname); } ret = 1; diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c index b33be0982..e886f4b55 100644 --- a/xlators/mgmt/glusterd/src/glusterd-snapshot.c +++ b/xlators/mgmt/glusterd/src/glusterd-snapshot.c @@ -585,6 +585,7 @@ glusterd_snapshot_create_prevalidate (dict_t *dict, char **op_errstr, char snapmntname[PATH_MAX] = ""; char snapbrckcnt[PATH_MAX] = ""; char snapbrckord[PATH_MAX] = ""; + char snap_volname[64] = ""; int ret = -1; int64_t i = 0; int64_t volume_count = 0; @@ -594,6 +595,7 @@ glusterd_snapshot_create_prevalidate (dict_t *dict, char **op_errstr, glusterd_volinfo_t *volinfo = NULL; gf_boolean_t is_cg = _gf_false; xlator_t *this = NULL; + uuid_t *snap_volid = NULL; this = THIS; @@ -653,10 +655,24 @@ glusterd_snapshot_create_prevalidate (dict_t *dict, char **op_errstr, goto out; } + snprintf (key, sizeof(key) - 1, "vol%ld_volid", i+1); + ret = dict_get_bin (dict, key, (void **)&snap_volid); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Unable to fetch snap_volid"); + goto out; + } + + /* snap uuid is used as lvm snapshot name. + This will avoid restrictions on snapshot names + provided by user */ + GLUSTERD_GET_UUID_NOHYPHEN (snap_volname, *snap_volid); + if (is_cg) { memset(snapname, '\0', sizeof (snapname)); snprintf (tmp, sizeof (tmp), "%s_snap", volinfo->volname); snprintf (snapname, sizeof (snapname), "%s_%s", name, tmp); + strcpy(snap_volname, snapname); } //Also check whether geo replication is running @@ -683,7 +699,8 @@ glusterd_snapshot_create_prevalidate (dict_t *dict, char **op_errstr, goto out; } - device = glusterd_build_snap_device_path (device, snapname); + device = glusterd_build_snap_device_path (device, + snap_volname); if (!device) { gf_log (this->name, GF_LOG_WARNING, "cannot copy the " "snapshot device name (volname: %s, " @@ -699,7 +716,7 @@ glusterd_snapshot_create_prevalidate (dict_t *dict, char **op_errstr, ret = snprintf (snap_mount, sizeof(snap_mount) - 1, "%s/%s%s-brick", GLUSTERD_DEFAULT_SNAPS_BRICK_DIR, - snapname, device); + snap_volname, device); snap_mount[ret] = '\0'; ret = glusterd_get_brick_root (brickinfo->path, &mnt_pt); @@ -2642,7 +2659,7 @@ out: */ int32_t glusterd_snap_create (glusterd_volinfo_t *volinfo, - glusterd_volinfo_t *snap_volinfo, + glusterd_volinfo_t *snap_volinfo, char *snapname, char *description, uuid_t *cg_id, glusterd_snap_cg_t *cg, char *cg_name) { @@ -2655,6 +2672,7 @@ glusterd_snap_create (glusterd_volinfo_t *volinfo, priv = this->private; GF_ASSERT (snap_volinfo); + GF_ASSERT (snapname); if (cg_id) GF_ASSERT (cg_name); @@ -2667,7 +2685,7 @@ glusterd_snap_create (glusterd_volinfo_t *volinfo, if (!snap) { gf_log (this->name, GF_LOG_ERROR, "could not create " "the snap object fot the volume %s (snap: %s)", - volinfo->volname, snap_volinfo->volname); + volinfo->volname, snapname); goto out; } @@ -2701,8 +2719,7 @@ glusterd_snap_create (glusterd_volinfo_t *volinfo, sizeof (snap->cg_name) - 1); } snap->snap_volume = snap_volinfo; - strcpy (snap->snap_name, snap_volinfo->volname); - //TODO: replace strcpy with strncpy + strcpy (snap->snap_name, snapname); ret = glusterd_add_snap (volinfo, snap); if (ret) { @@ -2729,22 +2746,21 @@ out: } /* This function is called to get the device path of the snap lvm. Usually - if /dev//- is the device for the lvm, - then the snap device will be /dev//-. + if /dev/mapper/- is the device for the lvm, + then the snap device will be /dev//. This function takes care of building the path for the snap device. */ char * glusterd_build_snap_device_path (char *device, char *snapname) { - char *tmp = NULL; - char snap[PATH_MAX] = {0, }; - char msg[1024] = {0, }; - char *str = NULL; - int device_len = 0; - int tmp_len = 0; - int var = 0; - char *snap_device = NULL; - xlator_t *this = NULL; + char snap[PATH_MAX] = ""; + char msg[1024] = ""; + char volgroup[PATH_MAX] = ""; + char *snap_device = NULL; + xlator_t *this = NULL; + runner_t runner = {0,}; + char *ptr = NULL; + int ret = -1; this = THIS; GF_ASSERT (this); @@ -2752,42 +2768,47 @@ glusterd_build_snap_device_path (char *device, char *snapname) gf_log (this->name, GF_LOG_ERROR, "device is NULL"); goto out; } + if (!snapname) { + gf_log (this->name, GF_LOG_ERROR, "snapname is NULL"); + goto out; + } - device_len = strlen (device); - - tmp = strrchr (device, '/'); - if (tmp) - tmp++; - str = gf_strdup (tmp); - if (!str) { + runinit (&runner); + runner_add_args (&runner, "/sbin/lvs", "--noheadings", "-o", "vg_name", + device, NULL); + runner_redir (&runner, STDOUT_FILENO, RUN_PIPE); + snprintf (msg, sizeof (msg), "Get volume group for device %s", device); + runner_log (&runner, this->name, GF_LOG_DEBUG, msg); + ret = runner_start (&runner); + if (ret == -1) { + gf_log (this->name, GF_LOG_ERROR, "Failed to get volume group " + "for device %s", device); + runner_end (&runner); + goto out; + } + ptr = fgets(volgroup, sizeof(volgroup), + runner_chio (&runner, STDOUT_FILENO)); + if (!ptr || !strlen(volgroup)) { + gf_log (this->name, GF_LOG_ERROR, "Failed to get volume group " + "for snap %s", snapname); + runner_end (&runner); + ret = -1; goto out; } + runner_end (&runner); + + strcpy(snap, "/dev/"); + strcat(snap, gf_trim(volgroup)); + strcat(snap, "/"); + strcat(snap, snapname); - tmp_len = strlen (str); - var = device_len - tmp_len; - device[var] = '\0'; - tmp = strchr (str, '-'); - if (tmp) - tmp++; - device_len = tmp_len; - tmp_len = strlen (tmp); - var = device_len - tmp_len; - str[var] = '\0'; - msg[0] = '\0'; - strcpy (msg, str); - strcat (msg, snapname); - strcpy (snap, device); - strcat (snap, msg); snap_device = gf_strdup (snap); if (!snap_device) { - gf_log (this->name, GF_LOG_WARNING, "cannot copy the " - "snapshot device name " - "snapname: %s)", snapname); - goto out; + gf_log (this->name, GF_LOG_WARNING, "Cannot copy the " + "snapshot device name for snapname: %s)", snapname); } out: - GF_FREE (str); return snap_device; } @@ -2898,20 +2919,19 @@ int32_t glusterd_snap_brick_create (char *device, glusterd_volinfo_t *snap_volinfo, glusterd_brickinfo_t *original_brickinfo) { - int32_t ret = -1; - xlator_t *this = NULL; - glusterd_conf_t *priv = NULL; - char snap_brick_mount_path[PATH_MAX] = {0, }; - char *tmp = NULL; - char *mnt_pt = NULL; - struct mntent *entry = NULL; - FILE *mtab = NULL; - char *snap_brick_dir = NULL; - char snap_brick_path[PATH_MAX] = {0, }; - struct stat statbuf = {0, }; - runner_t runner = {0, }; - char msg[1024] = {0, }; - + int32_t ret = -1; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + char *snap_brick_dir = NULL; + char snap_brick_mount_path[PATH_MAX] = ""; + char *tmp = NULL; + char snap_brick_path[PATH_MAX] = ""; + char msg[1024] = ""; + char *mnt_pt = NULL; + struct mntent *entry = NULL; + FILE *mtab = NULL; + struct stat statbuf = {0, }; + runner_t runner = {0, }; this = THIS; priv = this->private; @@ -3077,8 +3097,16 @@ glusterd_do_snap (glusterd_volinfo_t *volinfo, char *snapname, dict_t *dict, GF_ASSERT (cg_name); ret = glusterd_volinfo_dup (volinfo, &snap_volume); - strncpy (snap_volume->volname, snapname, - sizeof(snap_volume->volname) - 1); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to duplicate volinfo " + "for the snapshot %s", snapname); + goto out; + } + + /* snap uuid is used as lvm snapshot name. + This will avoid restrictions on snapshot names provided by user */ + GLUSTERD_GET_UUID_NOHYPHEN (snap_volume->volname, snap_volid); + snap_volume->is_snap_volume = _gf_true; strncpy (snap_volume->parent_volname, volinfo->volname, sizeof(snap_volume->parent_volname) - 1); @@ -3158,7 +3186,7 @@ glusterd_do_snap (glusterd_volinfo_t *volinfo, char *snapname, dict_t *dict, ret = glusterd_take_snapshot (brickinfo, volinfo->volname, - snapname, &device); + snap_volume->volname, &device); /* Fail the snapshot even though snapshot on one of the bricks fails. At the end when we check whether the snapshot volume meets quorum or not, then the @@ -3190,8 +3218,8 @@ glusterd_do_snap (glusterd_volinfo_t *volinfo, char *snapname, dict_t *dict, ret = dict_get_str (dict, "snap-description", &description); // for now continue the snap, if getting description fails. - ret = glusterd_snap_create (volinfo, snap_volume, description, cg_id, - cg, cg_name); + ret = glusterd_snap_create (volinfo, snap_volume, snapname, + description, cg_id, cg, cg_name); if (ret) { gf_log (this->name, GF_LOG_ERROR, "creating the" "snap object failed for the volume %s", diff --git a/xlators/mgmt/glusterd/src/glusterd-store.c b/xlators/mgmt/glusterd/src/glusterd-store.c index 56a64145c..c02c2c690 100644 --- a/xlators/mgmt/glusterd/src/glusterd-store.c +++ b/xlators/mgmt/glusterd/src/glusterd-store.c @@ -1444,7 +1444,7 @@ glusterd_store_snap_volume (glusterd_volinfo_t *volinfo, glusterd_snap_t *snap) goto unlock; ret = glusterd_store_create_snap_vol_dir (volinfo, - snap->snap_name); + snap_volinfo->volname); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "Failed create snapshot dir (%s) for volume " @@ -2843,7 +2843,7 @@ glusterd_store_update_volinfo (glusterd_volinfo_t *volinfo, goto out; } - GLUSTERD_GET_SNAP_DIR (volpath, parent_vol, snap->snap_name, + GLUSTERD_GET_SNAP_DIR (volpath, parent_vol, volinfo->volname, conf); } else { GLUSTERD_GET_VOLUME_DIR(volpath, volinfo, conf); @@ -3075,8 +3075,10 @@ glusterd_store_retrieve_volume (char *volname, glusterd_snap_t *snap) ret = glusterd_volinfo_find (volname, &parent_vol); if (ret) goto out; - strncpy (volinfo->volname, snap->snap_name, GLUSTERD_MAX_VOLUME_NAME); - GLUSTERD_GET_SNAP_DIR (volpath, parent_vol, snap->snap_name, priv); + GLUSTERD_GET_UUID_NOHYPHEN(volinfo->volname, + snap->snap_id); + GLUSTERD_GET_SNAP_DIR (volpath, parent_vol, volinfo->volname, + priv); strncpy (volinfo->parent_volname, volname, GLUSTERD_MAX_VOLUME_NAME); } else { strncpy (volinfo->volname, volname, GLUSTERD_MAX_VOLUME_NAME); diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index 8997e7555..27ebbbb6c 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -528,6 +528,20 @@ typedef ssize_t (*gd_serialize_t) (struct iovec outmsg, void *args); uuid_utoa(MY_UUID)); \ } while (0) +#define GLUSTERD_GET_UUID_NOHYPHEN(ret_string, uuid) do { \ + char *snap_volname_ptr = ret_string; \ + char *snap_volid_ptr = uuid_utoa(uuid); \ + while (*snap_volid_ptr) { \ + if (*snap_volid_ptr == '-') { \ + snap_volid_ptr++; \ + } else { \ + (*snap_volname_ptr++) = \ + (*snap_volid_ptr++); \ + } \ + } \ + *snap_volname_ptr = '\0'; \ + } while (0) + int glusterd_uuid_init(); int glusterd_uuid_generate_save (); -- cgit