From dedef037d64fef59d74b9861562aa7f93857a53e Mon Sep 17 00:00:00 2001 From: Rajesh Joseph Date: Tue, 1 Jul 2014 20:25:04 +0530 Subject: glusterd/snapshot: Change file-system uuid to file-system label Problem: In XFS changing file-system UUID with xfs_admin is causing too much delay with large file-system. The time taken by xfs_admin tool to change UUID is directly proportional to the size of the file system. Cause: In XFS file-system UUID is stored in file-system superblock. Therefore for chaning UUID all the superblock needs to be changed. Fix: Instead of using file-system UUID use file-system label. Change-Id: Ifb4c668fb29cfc1c89d9b221abc8d09dc09589ec BUG: 1115107 Signed-off-by: Rajesh Joseph Reviewed-on: http://review.gluster.org/8215 Reviewed-by: Atin Mukherjee Reviewed-by: Avra Sengupta Reviewed-by: Vijay Bellur Tested-by: Vijay Bellur --- xlators/mgmt/glusterd/src/glusterd-handshake.c | 12 +-- xlators/mgmt/glusterd/src/glusterd-snapshot.c | 140 ++++++++++--------------- xlators/mgmt/glusterd/src/glusterd-store.c | 23 +++- xlators/mgmt/glusterd/src/glusterd-store.h | 1 + xlators/mgmt/glusterd/src/glusterd-utils.c | 44 +++++++- xlators/mgmt/glusterd/src/glusterd-utils.h | 5 +- 6 files changed, 129 insertions(+), 96 deletions(-) (limited to 'xlators/mgmt/glusterd/src') diff --git a/xlators/mgmt/glusterd/src/glusterd-handshake.c b/xlators/mgmt/glusterd/src/glusterd-handshake.c index 0fd60806da2..7d582d443f4 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handshake.c +++ b/xlators/mgmt/glusterd/src/glusterd-handshake.c @@ -454,16 +454,16 @@ glusterd_create_missed_snap (glusterd_missed_snap_info *missed_snapinfo, } /* After the snapshot both the origin brick (LVM brick) and - * the snapshot brick will have the same file-system UUID. This + * the snapshot brick will have the same file-system label. This * will cause lot of problems at mount time. Therefore we must - * generate a new UUID for the snapshot brick + * generate a new label for the snapshot brick */ - ret = glusterd_update_fs_uuid (brickinfo); + ret = glusterd_update_fs_label (brickinfo); if (ret) { gf_log (this->name, GF_LOG_ERROR, "Failed to update " - "file-system uuid for %s brick", brickinfo->path); - /* Failing to update UUID should not cause snapshot failure. - * Currently UUID is updated only for XFS and ext2/ext3/ext4 + "file-system label for %s brick", brickinfo->path); + /* Failing to update label should not cause snapshot failure. + * Currently label is updated only for XFS and ext2/ext3/ext4 * file-system. */ } diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c index c1ddc0849cc..7678d77b3d5 100644 --- a/xlators/mgmt/glusterd/src/glusterd-snapshot.c +++ b/xlators/mgmt/glusterd/src/glusterd-snapshot.c @@ -971,6 +971,17 @@ glusterd_snapshot_restore_prevalidate (dict_t *dict, char **op_errstr, "Failed to set %s", key); goto out; } + + snprintf (key, sizeof (key), + "snap%d.brick%d.fs_type", + volcount, brick_count); + ret = dict_set_str (rsp_dict, key, + brickinfo->fstype); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to set %s", key); + goto out; + } } snprintf (key, sizeof (key), "snap%d.brick_count", volcount); @@ -1466,6 +1477,21 @@ glusterd_snap_restore_use_rsp_dict (dict_t *dst, dict_t *src) "Failed to set %s", key); goto out; } + + snprintf (key, sizeof (key), + "snap%d.brick%d.fs_type", i, j); + ret = dict_get_str (src, key, &strvalue); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to get %s", key); + goto out; + } + ret = dict_set_dynstr_with_alloc (dst, key, strvalue); + if (ret) { + gf_log (this->name, GF_LOG_DEBUG, + "Failed to set %s", key); + goto out; + } } } @@ -3725,7 +3751,8 @@ glusterd_snap_brick_create (glusterd_volinfo_t *snap_volinfo, But for now, mounting using runner apis. */ ret = glusterd_mount_lvm_snapshot (brickinfo->device_path, - snap_brick_mount_path); + snap_brick_mount_path, + brickinfo->fstype); if (ret) { gf_log (this->name, GF_LOG_ERROR, "Failed to mount lvm snapshot."); @@ -3978,7 +4005,7 @@ out: return ret; } -/* This function will update the file-system UUID of the +/* This function will update the file-system label of the * backend snapshot brick. * * @param brickinfo brickinfo of the snap volume @@ -3986,14 +4013,11 @@ out: * @return 0 on success and -1 on failure */ int -glusterd_update_fs_uuid (glusterd_brickinfo_t *brickinfo) +glusterd_update_fs_label (glusterd_brickinfo_t *brickinfo) { int32_t ret = -1; char msg [PATH_MAX] = ""; - char uuid_str [NAME_MAX] = ""; - char template [] = "/tmp/xfsmountXXXXXX"; - char *mount_path = NULL; - char *cmd = NULL; + char label [NAME_MAX] = ""; uuid_t uuid = {0,}; runner_t runner = {0,}; xlator_t *this = NULL; @@ -4005,82 +4029,39 @@ glusterd_update_fs_uuid (glusterd_brickinfo_t *brickinfo) /* Generate a new UUID */ uuid_generate (uuid); - if (NULL == uuid_utoa_r (uuid, uuid_str)) { - gf_log (this->name, GF_LOG_ERROR, "Failed to convert " - "uuid to string for %s brick", brickinfo->path); - goto out; - } + GLUSTERD_GET_UUID_NOHYPHEN (label, uuid); runinit (&runner); - snprintf (msg, sizeof (msg), "Changing filesystem uuid of %s brick to " - "%s", brickinfo->path, uuid_str); /* Call the file-system specific tools to update the file-system - * UUID. Currently we are only supporting xfs and ext2/ext3/ext4 + * label. Currently we are only supporting xfs and ext2/ext3/ext4 * file-system. */ if (0 == strcmp (brickinfo->fstype, "xfs")) { - /* TODO: xfs_admin tool is used to replace the file-system - * UUID. As of now the tool is failing with error when trying - * to replace the UUID. Therefore as a workaround we mount - * the file-system to a temporary location and then unmount - * it. - * After this xfs_admin tool works fine. - */ - mount_path = mkdtemp (template); - if (NULL == mount_path) { - gf_log (this->name, GF_LOG_ERROR, "Failed to create " - "temporary folder. Error: %s", - strerror (errno)); - runner_end (&runner); - goto out; - } - - /* First we mount the brick to a temporary path. Please - * note that we are using "nouuid" option here because - * both the origin volume brick and this brick will have - * the same UUID. And XFS does not allow us to mount a - * file-system which is sharing the UUID with any other - * file-system on the system. - */ -#ifdef GF_LINUX_HOST_OS - ret = mount (brickinfo->device_path, mount_path, - brickinfo->fstype, 0, "nouuid"); -#else - ret = -1; -#endif - - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Failed to mount " - "%s at %s", brickinfo->device_path, - mount_path); - runner_end (&runner); - goto out; - } - - /* Now unmount the brick. */ - ret = glusterd_umount (mount_path); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Failed to unmount " - "%s from %s", brickinfo->device_path, - mount_path); - runner_end (&runner); - goto out; - } - - /* Now we are ready to run xfs_admin tool */ - runner_add_args (&runner, "xfs_admin", "-U", uuid_str, + /* XFS label is of size 12. Therefore we should truncate the + * label to 12 bytes*/ + label [12] = '\0'; + snprintf (msg, sizeof (msg), "Changing filesystem label of " + "%s brick to %s", brickinfo->path, label); + /* Run the run xfs_admin tool to change the label + * of the file-system */ + runner_add_args (&runner, "xfs_admin", "-L", label, brickinfo->device_path, NULL); } else if (0 == strcmp (brickinfo->fstype, "ext4") || 0 == strcmp (brickinfo->fstype, "ext3") || 0 == strcmp (brickinfo->fstype, "ext2")) { + /* Ext2/Ext3/Ext4 label is of size 16. Therefore we should + * truncate the label to 16 bytes*/ + label [16] = '\0'; + snprintf (msg, sizeof (msg), "Changing filesystem label of " + "%s brick to %s", brickinfo->path, label); /* For ext2/ext3/ext4 run tune2fs to change the - * file-system UUID */ - runner_add_args (&runner, "tune2fs", "-U", uuid_str, + * file-system label */ + runner_add_args (&runner, "tune2fs", "-L", label, brickinfo->device_path, NULL); } else { gf_log (this->name, GF_LOG_WARNING, "Changing file-system " - "UUID of %s file-system is not supported as of now", + "label of %s file-system is not supported as of now", brickinfo->fstype); runner_end (&runner); ret = -1; @@ -4091,20 +4072,13 @@ glusterd_update_fs_uuid (glusterd_brickinfo_t *brickinfo) ret = runner_run (&runner); if (ret) { gf_log (this->name, GF_LOG_ERROR, "Failed to change " - "filesystem uuid of %s brick to %s", - brickinfo->path, uuid_str); + "filesystem label of %s brick to %s", + brickinfo->path, label); goto out; } ret = 0; out: - if (NULL != mount_path) { - if (rmdir (mount_path)) { - gf_log (this->name, GF_LOG_ERROR, "Failed to remove " - "temporary folder %s. Error: %s", - mount_path, strerror (errno)); - } - } return ret; } @@ -4148,16 +4122,16 @@ glusterd_take_brick_snapshot (dict_t *dict, glusterd_volinfo_t *snap_vol, } /* After the snapshot both the origin brick (LVM brick) and - * the snapshot brick will have the same file-system UUID. This + * the snapshot brick will have the same file-system label. This * will cause lot of problems at mount time. Therefore we must - * generate a new UUID for the snapshot brick + * generate a new label for the snapshot brick */ - ret = glusterd_update_fs_uuid (brickinfo); + ret = glusterd_update_fs_label (brickinfo); if (ret) { gf_log (this->name, GF_LOG_ERROR, "Failed to update " - "file-system uuid for %s brick", brickinfo->path); - /* Failing to update UUID should not cause snapshot failure. - * Currently UUID is updated only for XFS and ext2/ext3/ext4 + "file-system label for %s brick", brickinfo->path); + /* Failing to update label should not cause snapshot failure. + * Currently label is updated only for XFS and ext2/ext3/ext4 * file-system. */ } diff --git a/xlators/mgmt/glusterd/src/glusterd-store.c b/xlators/mgmt/glusterd/src/glusterd-store.c index e03ec7af9f5..c31d8a8ad71 100644 --- a/xlators/mgmt/glusterd/src/glusterd-store.c +++ b/xlators/mgmt/glusterd/src/glusterd-store.c @@ -325,6 +325,17 @@ gd_store_brick_snap_details_write (int fd, glusterd_brickinfo_t *brickinfo) goto out; } + if (strlen (brickinfo->fstype) > 0) { + snprintf (value, sizeof (value), "%s", brickinfo->fstype); + ret = gf_store_save_value (fd, + GLUSTERD_STORE_KEY_BRICK_FSTYPE, value); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to save " + "brick fs type of brick %s", brickinfo->path); + goto out; + } + } + memset (value, 0, sizeof (value)); snprintf (value, sizeof(value), "%d", brickinfo->snap_status); ret = gf_store_save_value (fd, GLUSTERD_STORE_KEY_BRICK_SNAP_STATUS, @@ -2272,6 +2283,10 @@ glusterd_store_retrieve_bricks (glusterd_volinfo_t *volinfo) } else if (!strncmp (key, GLUSTERD_STORE_KEY_BRICK_SNAP_STATUS, strlen (GLUSTERD_STORE_KEY_BRICK_SNAP_STATUS))) { gf_string2int (value, &brickinfo->snap_status); + } else if (!strncmp (key, GLUSTERD_STORE_KEY_BRICK_FSTYPE, + strlen (GLUSTERD_STORE_KEY_BRICK_FSTYPE))) { + strncpy (brickinfo->fstype, value, + sizeof (brickinfo->fstype)); } else if (!strncmp (key, GLUSTERD_STORE_KEY_BRICK_VGNAME, strlen (GLUSTERD_STORE_KEY_BRICK_VGNAME))) { @@ -3086,7 +3101,8 @@ out: * at the brick_mount_path */ int32_t -glusterd_mount_brick_paths (char *brick_mount_path, char *device_path) +glusterd_mount_brick_paths (char *brick_mount_path, char *device_path, + const char *fstype) { int32_t ret = -1; runner_t runner = {0, }; @@ -3134,7 +3150,8 @@ glusterd_mount_brick_paths (char *brick_mount_path, char *device_path) "Activating %s successful", device_path); /* Mount the snapshot */ - ret = glusterd_mount_lvm_snapshot (device_path, brick_mount_path); + ret = glusterd_mount_lvm_snapshot (device_path, brick_mount_path, + fstype); if (ret) { gf_log (this->name, GF_LOG_ERROR, "Failed to mount lvm snapshot."); @@ -3208,7 +3225,7 @@ glusterd_recreate_vol_brick_mounts (xlator_t *this, /* Check if brick_mount_path is already mounted. * If not, mount the device_path at the brick_mount_path */ ret = glusterd_mount_brick_paths (brick_mount_path, - brickinfo->device_path); + brickinfo->device_path, brickinfo->fstype); if (ret) { gf_log (this->name, GF_LOG_ERROR, "Failed to mount brick_mount_path"); diff --git a/xlators/mgmt/glusterd/src/glusterd-store.h b/xlators/mgmt/glusterd/src/glusterd-store.h index 4c0f0d42321..89cf24de789 100644 --- a/xlators/mgmt/glusterd/src/glusterd-store.h +++ b/xlators/mgmt/glusterd/src/glusterd-store.h @@ -82,6 +82,7 @@ typedef enum glusterd_store_ver_ac_{ #define GLUSTERD_STORE_KEY_BRICK_DEVICE_PATH "device_path" #define GLUSTERD_STORE_KEY_BRICK_MOUNT_DIR "mount_dir" #define GLUSTERD_STORE_KEY_BRICK_SNAP_STATUS "snap-status" +#define GLUSTERD_STORE_KEY_BRICK_FSTYPE "fs-type" #define GLUSTERD_STORE_KEY_BRICK_ID "brick-id" #define GLUSTERD_STORE_KEY_PEER_UUID "uuid" diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index 6b973a3638d..02b2ba923e5 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -612,6 +612,7 @@ glusterd_brickinfo_dup (glusterd_brickinfo_t *brickinfo, strcpy (dup_brickinfo->hostname, brickinfo->hostname); strcpy (dup_brickinfo->path, brickinfo->path); strcpy (dup_brickinfo->device_path, brickinfo->device_path); + strcpy (dup_brickinfo->fstype, brickinfo->fstype); ret = gf_canonicalize_path (dup_brickinfo->path); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "Failed to canonicalize " @@ -710,6 +711,13 @@ glusterd_snap_volinfo_restore (dict_t *dict, dict_t *rsp_dict, strncpy (new_brickinfo->device_path, value, sizeof(new_brickinfo->device_path)); + snprintf (key, sizeof (key), "snap%d.brick%d.fs_type", + volcount, brick_count); + ret = dict_get_str (dict, key, &value); + if (!ret) + strncpy (new_brickinfo->fstype, value, + sizeof(new_brickinfo->fstype)); + /* If the brick is not of this peer, or snapshot is missed * * for the brick do not replace the xattr for it */ if ((!uuid_compare (brickinfo->uuid, MY_UUID)) && @@ -2363,6 +2371,15 @@ gd_add_brick_snap_details_to_dict (dict_t *dict, char *prefix, goto out; } + snprintf (key, sizeof (key), "%s.fs_type", prefix); + ret = dict_set_str (dict, key, brickinfo->fstype); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to set fstype for %s:%s", + brickinfo->hostname, brickinfo->path); + goto out; + } + memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.mount_dir", prefix); ret = dict_set_str (dict, key, brickinfo->mount_dir); @@ -3695,6 +3712,7 @@ gd_import_new_brick_snap_details (dict_t *dict, char *prefix, glusterd_conf_t *conf = NULL; char key[512] = {0,}; char *snap_device = NULL; + char *fs_type = NULL; char *mount_dir = NULL; this = THIS; @@ -3727,6 +3745,14 @@ gd_import_new_brick_snap_details (dict_t *dict, char *prefix, } strcpy (brickinfo->device_path, snap_device); + snprintf (key, sizeof (key), "%s.fs_type", prefix); + ret = dict_get_str (dict, key, &fs_type); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "%s missing in payload", key); + goto out; + } + strcpy (brickinfo->fstype, fs_type); + memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.mount_dir", prefix); ret = dict_get_str (dict, key, &mount_dir); @@ -12206,7 +12232,8 @@ glusterd_compare_volume_name(struct list_head *list1, struct list_head *list2) } int32_t -glusterd_mount_lvm_snapshot (char *device_path, char *brick_mount_path) +glusterd_mount_lvm_snapshot (char *device_path, char *brick_mount_path, + const char *fstype) { char msg[NAME_MAX] = ""; int32_t ret = -1; @@ -12222,7 +12249,20 @@ glusterd_mount_lvm_snapshot (char *device_path, char *brick_mount_path) runinit (&runner); snprintf (msg, sizeof (msg), "mount %s %s", device_path, brick_mount_path); - runner_add_args (&runner, "mount", device_path, brick_mount_path, NULL); + + /* XFS file-system does not allow to mount file-system with duplicate + * UUID. File-system UUID of snapshot and its origin volume is same. + * Therefore to mount such a snapshot in XFS we need to pass nouuid + * option + */ + if (!strcmp (fstype, "xfs")) { + runner_add_args (&runner, "mount", "-o", "nouuid", + device_path, brick_mount_path, NULL); + } else { + runner_add_args (&runner, "mount", device_path, + brick_mount_path, NULL); + } + runner_log (&runner, this->name, GF_LOG_DEBUG, msg); ret = runner_run (&runner); if (ret) { diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h index 3edb0c55db4..8d3af0689fd 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.h +++ b/xlators/mgmt/glusterd/src/glusterd-utils.h @@ -757,7 +757,8 @@ gd_restore_snap_volume (dict_t *dict, dict_t *rsp_dict, int32_t volcount); int32_t -glusterd_mount_lvm_snapshot (char *device_path, char *brick_mount_path); +glusterd_mount_lvm_snapshot (char *device_path, char *brick_mount_path, + const char *fstype); int32_t glusterd_umount (const char *path); @@ -926,6 +927,6 @@ glusterd_update_fstype (char *orig_brick_path, char *fstype, size_t fslen); int -glusterd_update_fs_uuid (glusterd_brickinfo_t *brickinfo); +glusterd_update_fs_label (glusterd_brickinfo_t *brickinfo); #endif -- cgit