diff options
| author | Rajesh Joseph <rjoseph@redhat.com> | 2014-07-01 20:25:04 +0530 | 
|---|---|---|
| committer | Vijay Bellur <vbellur@redhat.com> | 2014-07-03 06:53:12 -0700 | 
| commit | dedef037d64fef59d74b9861562aa7f93857a53e (patch) | |
| tree | e3ed0c288cfac75f0ece3f10a64bfa63bbb9a431 /xlators | |
| parent | 3df72ddcdb371c441b5535ad802fc59a794e3ac9 (diff) | |
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 <rjoseph@redhat.com>
Reviewed-on: http://review.gluster.org/8215
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
Reviewed-by: Avra Sengupta <asengupt@redhat.com>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
Tested-by: Vijay Bellur <vbellur@redhat.com>
Diffstat (limited to 'xlators')
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handshake.c | 12 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-snapshot.c | 140 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-store.c | 23 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-store.h | 1 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 44 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.h | 5 | 
6 files changed, 129 insertions, 96 deletions
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  | 
