Whamcloud - gitweb
LU-8900 snapshot: rename filesysetem fsname 68/24268/16
authorFan Yong <fan.yong@intel.com>
Fri, 4 Nov 2016 12:28:31 +0000 (20:28 +0800)
committerOleg Drokin <oleg.drokin@intel.com>
Thu, 23 Mar 2017 01:40:15 +0000 (01:40 +0000)
Introuduce new tunefs options "--rename" for renaming the existing
Lustre filesystem fsname with configuration/parameters preserved.
Usage: tunefs.lustre --fsname $NEW_FSNAME --rename $OLD_FSNAME ...

NEW_FSNAME is the new fsname, must be specified.
OLD_FSNAME is the old fsname, it is optional if the MGS and the MDT
are combined together.

It shares the functionality of fork/erase Lustre configuration logs
in kernel.

Signed-off-by: Fan Yong <fan.yong@intel.com>
Change-Id: Ic9aaf6ed6209c7580bfabd4b660a6a7667576484
Reviewed-on: https://review.whamcloud.com/24268
Reviewed-by: Niu Yawei <yawei.niu@intel.com>
Reviewed-by: Lai Siyao <lai.siyao@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
Tested-by: Oleg Drokin <oleg.drokin@intel.com>
13 files changed:
lustre/include/dt_object.h
lustre/include/lustre_disk.h
lustre/mgs/mgs_handler.c
lustre/mgs/mgs_internal.h
lustre/mgs/mgs_llog.c
lustre/obdclass/local_storage.c
lustre/tests/conf-sanity.sh
lustre/tests/test-framework.sh
lustre/utils/mkfs_lustre.c
lustre/utils/mount_utils.c
lustre/utils/mount_utils.h
lustre/utils/mount_utils_ldiskfs.c
lustre/utils/mount_utils_zfs.c

index 537ee16..5c568ee 100644 (file)
@@ -1975,6 +1975,10 @@ int local_object_create(const struct lu_env *env,
                        struct dt_object *o,
                        struct lu_attr *attr, struct dt_object_format *dof,
                        struct thandle *th);
+struct dt_object *local_file_find(const struct lu_env *env,
+                                 struct local_oid_storage *los,
+                                 struct dt_object *parent,
+                                 const char *name);
 struct dt_object *local_file_find_or_create(const struct lu_env *env,
                                            struct local_oid_storage *los,
                                            struct dt_object *parent,
index 2841f6a..90e6629 100644 (file)
 
 #define LDD_F_MASK          0xFFFF
 
+#define XATTR_TARGET_RENAME "trusted.rename_tgt"
+
 enum ldd_mount_type {
        LDD_MT_EXT3 = 0,
        LDD_MT_LDISKFS,
@@ -184,12 +186,13 @@ struct lustre_disk_data {
 };
 
 
-#define IS_MDT(data)    ((data)->lsi_flags & LDD_F_SV_TYPE_MDT)
-#define IS_OST(data)    ((data)->lsi_flags & LDD_F_SV_TYPE_OST)
-#define IS_MGS(data)    ((data)->lsi_flags & LDD_F_SV_TYPE_MGS)
-#define IS_SERVER(data) ((data)->lsi_flags & (LDD_F_SV_TYPE_MGS | \
-                        LDD_F_SV_TYPE_MDT | LDD_F_SV_TYPE_OST))
-#define MT_STR(data)    mt_str((data)->ldd_mount_type)
+#define IS_MDT(data)           ((data)->lsi_flags & LDD_F_SV_TYPE_MDT)
+#define IS_OST(data)           ((data)->lsi_flags & LDD_F_SV_TYPE_OST)
+#define IS_MGS(data)           ((data)->lsi_flags & LDD_F_SV_TYPE_MGS)
+#define IS_SEPARATED_MGS(data) ((data)->ldd_flags == LDD_F_SV_TYPE_MGS)
+#define IS_SERVER(data)                ((data)->lsi_flags & (LDD_F_SV_TYPE_MGS | \
+                                LDD_F_SV_TYPE_MDT | LDD_F_SV_TYPE_OST))
+#define MT_STR(data)           mt_str((data)->ldd_mount_type)
 
 /* Make the mdt/ost server obd name based on the filesystem name */
 static inline bool server_make_name(__u32 flags, __u16 index, char *fs,
index 36ed177..a21acf3 100644 (file)
@@ -1294,6 +1294,10 @@ static int mgs_init0(const struct lu_env *env, struct mgs_device *mgs,
        mutex_init(&mgs->mgs_health_mutex);
        init_rwsem(&mgs->mgs_barrier_rwsem);
 
+       rc = mgs_lcfg_rename(env, mgs);
+       if (rc)
+               GOTO(err_llog, rc);
+
        rc = lproc_mgs_setup(mgs, lustre_cfg_string(lcfg, 3));
        if (rc != 0) {
                CERROR("%s: cannot initialize proc entry: rc = %d\n",
index 88cf7e8..634a9fe 100644 (file)
@@ -426,5 +426,6 @@ int mgs_lcfg_fork(const struct lu_env *env, struct mgs_device *mgs,
                  const char *oldname, const char *newname);
 int mgs_lcfg_erase(const struct lu_env *env, struct mgs_device *mgs,
                   const char *fsname);
+int mgs_lcfg_rename(const struct lu_env *env, struct mgs_device *mgs);
 
 #endif /* _MGS_INTERNAL_H */
index 15102e0..407667d 100644 (file)
@@ -4517,6 +4517,141 @@ int mgs_lcfg_erase(const struct lu_env *env, struct mgs_device *mgs,
        RETURN(rc);
 }
 
+static int mgs_xattr_del(const struct lu_env *env, struct dt_object *obj)
+{
+       struct dt_device *dev;
+       struct thandle *th = NULL;
+       int rc = 0;
+
+       ENTRY;
+
+       dev = container_of0(obj->do_lu.lo_dev, struct dt_device, dd_lu_dev);
+       th = dt_trans_create(env, dev);
+       if (IS_ERR(th))
+               RETURN(PTR_ERR(th));
+
+       rc = dt_declare_xattr_del(env, obj, XATTR_TARGET_RENAME, th);
+       if (rc)
+               GOTO(stop, rc);
+
+       rc = dt_trans_start_local(env, dev, th);
+       if (rc)
+               GOTO(stop, rc);
+
+       dt_write_lock(env, obj, 0);
+       rc = dt_xattr_del(env, obj, XATTR_TARGET_RENAME, th);
+
+       GOTO(unlock, rc);
+
+unlock:
+       dt_write_unlock(env, obj);
+
+stop:
+       dt_trans_stop(env, dev, th);
+
+       return rc;
+}
+
+int mgs_lcfg_rename(const struct lu_env *env, struct mgs_device *mgs)
+{
+       struct list_head log_list;
+       struct mgs_direntry *dirent, *n;
+       char fsname[16];
+       struct lu_buf buf = {
+               .lb_buf = fsname,
+               .lb_len = sizeof(fsname)
+       };
+       int rc = 0;
+
+       ENTRY;
+
+       rc = class_dentry_readdir(env, mgs, &log_list);
+       if (rc)
+               RETURN(rc);
+
+       if (list_empty(&log_list))
+               RETURN(0);
+
+       list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
+               struct dt_object *o = NULL;
+               char oldname[16];
+               char *ptr;
+               int len;
+
+               list_del_init(&dirent->mde_list);
+               ptr = strrchr(dirent->mde_name, '-');
+               if (!ptr)
+                       goto next;
+
+               len = ptr - dirent->mde_name;
+               if (unlikely(len >= sizeof(oldname))) {
+                       CDEBUG(D_MGS, "Skip invalid configuration file %s\n",
+                              dirent->mde_name);
+                       goto next;
+               }
+
+               o = local_file_find(env, mgs->mgs_los, mgs->mgs_configs_dir,
+                                   dirent->mde_name);
+               if (IS_ERR(o)) {
+                       rc = PTR_ERR(o);
+                       CDEBUG(D_MGS, "Fail to locate file %s: rc = %d\n",
+                              dirent->mde_name, rc);
+                       goto next;
+               }
+
+               rc = dt_xattr_get(env, o, &buf, XATTR_TARGET_RENAME);
+               if (rc < 0) {
+                       if (rc == -ENODATA)
+                               rc = 0;
+                       else
+                               CDEBUG(D_MGS,
+                                      "Fail to get EA for %s: rc = %d\n",
+                                      dirent->mde_name, rc);
+                       goto next;
+               }
+
+               if (unlikely(rc == len &&
+                            memcmp(fsname, dirent->mde_name, len) == 0)) {
+                       /* The new fsname is the same as the old one. */
+                       rc = mgs_xattr_del(env, o);
+                       goto next;
+               }
+
+               memcpy(oldname, dirent->mde_name, len);
+               oldname[len] = '\0';
+               fsname[rc] = '\0';
+               rc = mgs_lcfg_fork_one(env, mgs, dirent, oldname, fsname);
+               if (rc && rc != -EEXIST) {
+                       CDEBUG(D_MGS, "Fail to fork %s: rc = %d\n",
+                              dirent->mde_name, rc);
+                       goto next;
+               }
+
+               rc = mgs_erase_log(env, mgs, dirent->mde_name);
+               if (rc) {
+                       CDEBUG(D_MGS, "Fail to erase old %s: rc = %d\n",
+                              dirent->mde_name, rc);
+                       /* keep it there if failed to remove it. */
+                       rc = 0;
+               }
+
+next:
+               if (o && !IS_ERR(o))
+                       lu_object_put(env, &o->do_lu);
+
+               mgs_direntry_free(dirent);
+               if (rc)
+                       break;
+       }
+
+       list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
+               list_del_init(&dirent->mde_list);
+               mgs_direntry_free(dirent);
+       }
+
+       RETURN(rc);
+}
+
 /* from llog_swab */
 static void print_lustre_cfg(struct lustre_cfg *lcfg)
 {
index ffcf104..c15624e 100644 (file)
@@ -425,6 +425,28 @@ out:
        RETURN(dto);
 }
 
+struct dt_object *local_file_find(const struct lu_env *env,
+                                 struct local_oid_storage *los,
+                                 struct dt_object *parent,
+                                 const char *name)
+{
+       struct dt_thread_info   *dti = dt_info(env);
+       struct dt_object        *dto;
+       int                      rc;
+
+       LASSERT(parent);
+
+       rc = dt_lookup_dir(env, parent, name, &dti->dti_fid);
+       if (!rc)
+               dto = ls_locate(env, dt2ls_dev(los->los_dev),
+                               &dti->dti_fid, NULL);
+       else
+               dto = ERR_PTR(rc);
+
+       return dto;
+}
+EXPORT_SYMBOL(local_file_find);
+
 /*
  * Look up and create (if it does not exist) a local named file or directory in
  * parent directory.
@@ -438,30 +460,21 @@ struct dt_object *local_file_find_or_create(const struct lu_env *env,
        struct dt_object        *dto;
        int                      rc;
 
-       LASSERT(parent);
+       dto = local_file_find(env, los, parent, name);
+       if (!IS_ERR(dto) || PTR_ERR(dto) != -ENOENT)
+               return dto;
 
-       rc = dt_lookup_dir(env, parent, name, &dti->dti_fid);
-       if (rc == 0)
-               /* name is found, get the object */
-               dto = ls_locate(env, dt2ls_dev(los->los_dev),
-                               &dti->dti_fid, NULL);
-       else if (rc != -ENOENT)
-               dto = ERR_PTR(rc);
-       else {
-               rc = local_object_fid_generate(env, los, &dti->dti_fid);
-               if (rc < 0) {
-                       dto = ERR_PTR(rc);
-               } else {
-                       /* create the object */
-                       dti->dti_attr.la_valid  = LA_MODE;
-                       dti->dti_attr.la_mode   = mode;
-                       dti->dti_dof.dof_type   = dt_mode_to_dft(mode & S_IFMT);
-                       dto = __local_file_create(env, &dti->dti_fid, los,
-                                                 dt2ls_dev(los->los_dev),
-                                                 parent, name, &dti->dti_attr,
-                                                 &dti->dti_dof);
-               }
-       }
+       rc = local_object_fid_generate(env, los, &dti->dti_fid);
+       if (rc)
+               return ERR_PTR(rc);
+
+       /* create the object */
+       dti->dti_attr.la_valid = LA_MODE;
+       dti->dti_attr.la_mode = mode;
+       dti->dti_dof.dof_type = dt_mode_to_dft(mode & S_IFMT);
+       dto = __local_file_create(env, &dti->dti_fid, los,
+                                 dt2ls_dev(los->los_dev), parent, name,
+                                 &dti->dti_attr, &dti->dti_dof);
        return dto;
 }
 EXPORT_SYMBOL(local_file_find_or_create);
index 5ee57af..6d95b78 100755 (executable)
@@ -7076,6 +7076,131 @@ test_102() {
 }
 run_test 102 "obdclass module cleanup upon error"
 
+test_renamefs() {
+       local newname=$1
+
+       echo "rename $FSNAME to $newname"
+
+       if [ ! combined_mgs_mds ]; then
+               local facet=$(mgsdevname)
+
+               do_facet mgs \
+                       "$TUNEFS --fsname=$newname --rename=$FSNAME -v $facet"||
+                       error "(7) Fail to rename MGS"
+               if [ "$(facet_fstype $facet)" = "zfs" ]; then
+                       reimport_zpool mgs $newname-mgs
+               fi
+       fi
+
+       for num in $(seq $MDSCOUNT); do
+               local facet=$(mdsdevname $num)
+
+               do_facet mds${num} \
+                       "$TUNEFS --fsname=$newname --rename=$FSNAME -v $facet"||
+                       error "(8) Fail to rename MDT $num"
+               if [ "$(facet_fstype $facet)" = "zfs" ]; then
+                       reimport_zpool mds${num} $newname-mdt${num}
+               fi
+       done
+
+       for num in $(seq $OSTCOUNT); do
+               local facet=$(ostdevname $num)
+
+               do_facet ost${num} \
+                       "$TUNEFS --fsname=$newname --rename=$FSNAME -v $facet"||
+                       error "(9) Fail to rename OST $num"
+               if [ "$(facet_fstype $facet)" = "zfs" ]; then
+                       reimport_zpool ost${num} $newname-ost${num}
+               fi
+       done
+}
+
+test_103_set_pool() {
+       local pname=$1
+       local ost_x=$2
+
+       do_facet mgs $LCTL pool_add $FSNAME.$pname ${FSNAME}-$ost_x ||
+               error "Fail to add $ost_x to $FSNAME.$pname"
+       wait_update $HOSTNAME \
+               "lctl get_param -n lov.$FSNAME-clilov-*.pools.$pname |
+                grep $ost_x" "$FSNAME-${ost_x}_UUID" ||
+               error "$ost_x is NOT in pool $FSNAME.$pname"
+}
+
+test_103_check_pool() {
+       local save_fsname=$1
+       local errno=$2
+
+       stat $DIR/$tdir/test-framework.sh ||
+               error "($errno) Fail to stat"
+       do_facet mgs $LCTL pool_list $FSNAME.pool1 ||
+               error "($errno) Fail to list $FSNAME.pool1"
+       do_facet mgs $LCTL pool_list $FSNAME.$save_fsname ||
+               error "($errno) Fail to list $FSNAME.$save_fsname"
+       do_facet mgs $LCTL pool_list $FSNAME.$save_fsname |
+               grep ${FSNAME}-OST0000 ||
+               error "($errno) List $FSNAME.$save_fsname is invalid"
+
+       local pname=$($LFS getstripe --pool $DIR/$tdir/d0)
+       [ "$pname" = "$save_fsname" ] ||
+               error "($errno) Unexpected pool name $pname"
+}
+
+test_103() {
+       check_mount_and_prep
+       rm -rf $DIR/$tdir
+       mkdir $DIR/$tdir || error "(1) Fail to mkdir $DIR/$tdir"
+       cp $LUSTRE/tests/test-framework.sh $DIR/$tdir ||
+               error "(2) Fail to copy test-framework.sh"
+
+       do_facet mgs $LCTL pool_new $FSNAME.pool1 ||
+               error "(3) Fail to create $FSNAME.pool1"
+       # name the pool name as the fsname
+       do_facet mgs $LCTL pool_new $FSNAME.$FSNAME ||
+               error "(4) Fail to create $FSNAME.$FSNAME"
+
+       test_103_set_pool $FSNAME OST0000
+
+       $SETSTRIPE -p $FSNAME $DIR/$tdir/d0 ||
+               error "(6) Fail to setstripe on $DIR/$tdir/d0"
+
+       KEEP_ZPOOL=true
+       stopall
+
+       test_renamefs mylustre
+
+       local save_fsname=$FSNAME
+       FSNAME="mylustre"
+       setupall
+
+       test_103_check_pool $save_fsname 7
+
+       if [ $OSTCOUNT -ge 2 ]; then
+               test_103_set_pool $save_fsname OST0001
+       fi
+
+       $SETSTRIPE -p $save_fsname $DIR/$tdir/f0 ||
+               error "(16) Fail to setstripe on $DIR/$tdir/f0"
+
+       stopall
+
+       test_renamefs tfs
+
+       FSNAME="tfs"
+       setupall
+
+       test_103_check_pool $save_fsname 17
+
+       stopall
+
+       test_renamefs $save_fsname
+
+       FSNAME=$save_fsname
+       setupall
+       KEEP_ZPOOL=false
+}
+run_test 103 "rename filesystem name"
+
 if ! combined_mgs_mds ; then
        stop mgs
 fi
index 623caca..1a1ad31 100755 (executable)
@@ -139,6 +139,7 @@ init_test_env() {
        export FAIL_ON_SKIP_ENV=${FAIL_ON_SKIP_ENV:-false}
        export RPC_MODE=${RPC_MODE:-false}
        export DO_CLEANUP=${DO_CLEANUP:-true}
+       export KEEP_ZPOOL=${KEEP_ZPOOL:-false}
 
     export MKE2FS=$MKE2FS
     if [ -z "$MKE2FS" ]; then
@@ -1110,6 +1111,20 @@ import_zpool() {
 }
 
 #
+# Reimport ZFS storage pool with new name
+#
+reimport_zpool() {
+       local facet=$1
+       local newpool=$2
+       local opts="-o cachefile=none"
+       local poolname=$(zpool_name $facet)
+
+       opts+=" -d $(dirname $(facet_vdevice $facet))"
+       do_facet $facet "$ZPOOL export $poolname;
+                        $ZPOOL import $opts $poolname $newpool"
+}
+
+#
 # Set the "cachefile=none" property on ZFS storage pool so that the pool
 # is not automatically imported on system startup.
 #
@@ -1398,7 +1413,7 @@ stop() {
 
        if [[ $(facet_fstype $facet) == zfs ]]; then
                # export ZFS storage pool
-               export_zpool $facet
+               [ "$KEEP_ZPOOL" = "true" ] || export_zpool $facet
        fi
 }
 
index e426f64..ab813fa 100644 (file)
@@ -119,9 +119,10 @@ void usage(FILE *out)
                        "cache, log)\n"
 #endif
                "\n"
-#ifndef TUNEFS
                "\ttarget types:\n"
                "\t\t--mgs: configuration management service\n"
+               "\t\t--nomgs: turn off MGS service on this MDT\n"
+#ifndef TUNEFS
                "\t\t--mdt: metadata storage, mutually exclusive with ost\n"
                "\t\t--ost: object storage, mutually exclusive with mdt, mgs\n"
 #endif
@@ -154,9 +155,9 @@ void usage(FILE *out)
                "\t\t--stripe-count-hint=#N: for optimizing MDT inode size\n"
 #else
                "\t\t--erase-params: erase all old parameter settings\n"
-               "\t\t--nomgs: turn off MGS service on this MDT\n"
                "\t\t--writeconf: erase all config logs for this fs.\n"
                "\t\t--quota: enable space accounting on old 2.x device.\n"
+               "\t\t--rename: rename the filesystem name\n"
 #endif
                "\t\t--comment=<user comment>: arbitrary string (%d bytes)\n"
                "\t\t--dryrun: report what we would do; don't write to disk\n"
@@ -274,18 +275,20 @@ static char *convert_hostnames(char *s1)
 }
 
 int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop,
-              char **mountopts)
+              char **mountopts, char *old_fsname)
 {
        static struct option long_opt[] = {
                { "backfs-mount-opts",  required_argument,      NULL, 'B' },
                { "failnode",           required_argument,      NULL, 'f' },
                { "failover",           required_argument,      NULL, 'f' },
+               { "mgs",                no_argument,            NULL, 'G' },
                { "help",               no_argument,            NULL, 'h' },
                { "index",              required_argument,      NULL, 'i' },
                { "fsname",             required_argument,      NULL, 'L' },
                { "mgsnode",            required_argument,      NULL, 'm' },
                { "mgsnid",             required_argument,      NULL, 'm' },
                { "dryrun",             no_argument,            NULL, 'n' },
+               { "nomgs",              no_argument,            NULL, 'N' },
                { "mountfsoptions",     required_argument,      NULL, 'o' },
                { "param",              required_argument,      NULL, 'p' },
                { "quiet",              no_argument,            NULL, 'q' },
@@ -299,25 +302,24 @@ int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop,
                { "backfstype",         required_argument,      NULL, 'b' },
                { "stripe-count-hint",  required_argument,      NULL, 'c' },
                { "device-size",        required_argument,      NULL, 'd' },
-               { "mgs",                no_argument,            NULL, 'G' },
                { "mkfsoptions",        required_argument,      NULL, 'k' },
                { "mdt",                no_argument,            NULL, 'M' },
-               { "nomgs",              no_argument,            NULL, 'N' },
                { "ost",                no_argument,            NULL, 'O' },
                { "reformat",           no_argument,            NULL, 'r' },
                { "replace",            no_argument,            NULL, 'R' },
 #else
                { "erase-params",       no_argument,            NULL, 'e' },
                { "quota",              no_argument,            NULL, 'Q' },
+               { "rename",             optional_argument,      NULL, 'R' },
                { "writeconf",          no_argument,            NULL, 'w' },
 #endif
                { 0,                    0,                      NULL,  0  }
        };
-       char *optstring = "B:f:hi:L:m:no:p:qs:t:u:vV"
+       char *optstring = "B:f:Ghi:L:m:nNo:p:qs:t:u:vV"
 #ifndef TUNEFS
-                         "b:c:d:Gk:MNOrR";
+                         "b:c:d:k:MOrR";
 #else
-                         "eQw";
+                         "eQR::w";
 #endif
        struct lustre_disk_data *ldd = &mop->mo_ldd;
        char new_fsname[16] = { 0 };
@@ -368,6 +370,9 @@ int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop,
                        mop->mo_flags |= MO_FAILOVER;
                        break;
                }
+               case 'G':
+                       ldd->ldd_flags |= LDD_F_SV_TYPE_MGS;
+                       break;
                case 'h':
                        usage(stdout);
                        return 1;
@@ -434,6 +439,9 @@ int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop,
                case 'n':
                        print_only++;
                        break;
+               case 'N':
+                       ldd->ldd_flags &= ~LDD_F_SV_TYPE_MGS;
+                       break;
                case 'o':
                        *mountopts = optarg;
                        break;
@@ -515,9 +523,6 @@ int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop,
                case 'd':
                        mop->mo_device_kb = atol(optarg);
                        break;
-               case 'G':
-                       ldd->ldd_flags |= LDD_F_SV_TYPE_MGS;
-                       break;
                case 'k':
                        strscpy(mop->mo_mkfsopts, optarg,
                                sizeof(mop->mo_mkfsopts));
@@ -525,9 +530,6 @@ int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop,
                case 'M':
                        ldd->ldd_flags |= LDD_F_SV_TYPE_MDT;
                        break;
-               case 'N':
-                       ldd->ldd_flags &= ~LDD_F_SV_TYPE_MGS;
-                       break;
                case 'O':
                        ldd->ldd_flags |= LDD_F_SV_TYPE_OST;
                        break;
@@ -546,6 +548,45 @@ int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop,
                case 'Q':
                        mop->mo_flags |= MO_QUOTA;
                        break;
+               case 'R': {
+                       char *tmp;
+
+                       mop->mo_flags |= MO_RENAME;
+                       if (!optarg) {
+                               if (IS_SEPARATED_MGS(ldd)) {
+                                       fprintf(stderr, "%s: must specify the "
+                                               "old fsname to be renamed for "
+                                               "separated MGS\n", progname);
+                                       return 1;
+                               }
+                               break;
+                       }
+
+                       if ((strlen(optarg) < 1) || (strlen(optarg) > 8)) {
+                               fprintf(stderr, "%s: filesystem name must be "
+                                       "1-8 chars\n", progname);
+                               return 1;
+                       }
+
+                       tmp = strpbrk(optarg, "/:");
+                       if (tmp) {
+                               fprintf(stderr, "%s: char '%c' not allowed in "
+                                       "filesystem name\n", progname, *tmp);
+                               return 1;
+                       }
+
+                       if (IS_SEPARATED_MGS(ldd)) {
+                               strscpy(old_fsname, optarg,
+                                       sizeof(ldd->ldd_fsname));
+                       } else if (strlen(old_fsname) != strlen(optarg) ||
+                                  strcmp(old_fsname, optarg) != 0) {
+                               fprintf(stderr, "%s: the given fsname '%s' "
+                                       "to be renamed does not exist\n",
+                                       progname, optarg);
+                               return 1;
+                       }
+                       break;
+               }
                case 'w':
                        ldd->ldd_flags |= LDD_F_WRITECONF;
                        break;
@@ -560,7 +601,7 @@ int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop,
        }
 
        if (strlen(new_fsname) > 0) {
-               if (!(mop->mo_flags & MO_FORCEFORMAT) &&
+               if (!(mop->mo_flags & (MO_FORCEFORMAT | MO_RENAME)) &&
                     (!(ldd->ldd_flags &
                        (LDD_F_UPGRADE14 | LDD_F_VIRGIN | LDD_F_WRITECONF)))) {
                        fprintf(stderr, "%s: cannot change the name "
@@ -579,6 +620,22 @@ int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop,
                return 1;
        }
 
+#ifdef TUNEFS
+       if (mop->mo_flags & MO_RENAME) {
+               if (new_fsname[0] == '\0') {
+                       fprintf(stderr, "%s: need to specify new fsname for "
+                               "renaming case\n", progname);
+                       return 1;
+               }
+
+               if (strcmp(old_fsname, new_fsname) == 0) {
+                       fprintf(stderr, "%s: cannot rename fsname '%s' to "
+                               "the same name\n", progname, old_fsname);
+                       return 1;
+               }
+       }
+#endif
+
        /* Need to clear this flag after parsing 'L' and 'i' options. */
        if (replace)
                ldd->ldd_flags &= ~LDD_F_VIRGIN;
@@ -607,6 +664,7 @@ int main(int argc, char *const argv[])
        struct lustre_disk_data *ldd = &mop.mo_ldd;
        char *mountopts = NULL;
        char wanted_mountopts[512] = "";
+       char old_fsname[16] = "";
        unsigned mount_type;
        int ret = 0;
        int ret2 = 0;
@@ -655,6 +713,7 @@ int main(int argc, char *const argv[])
                goto out;
        }
 
+       strscpy(old_fsname, ldd->ldd_fsname, sizeof(ldd->ldd_fsname));
        ldd->ldd_flags &= ~(LDD_F_WRITECONF | LDD_F_VIRGIN);
 
        /* svname of the form lustre:OST1234 means never registered */
@@ -674,7 +733,7 @@ int main(int argc, char *const argv[])
                print_ldd("Read previous values", ldd);
 #endif /* TUNEFS */
 
-       ret = parse_opts(argc, argv, &mop, &mountopts);
+       ret = parse_opts(argc, argv, &mop, &mountopts, old_fsname);
        if (ret != 0 || version)
                goto out;
 
@@ -839,7 +898,7 @@ int main(int argc, char *const argv[])
                fprintf(stderr, "mkfs failed %d\n", ret);
                goto out;
        }
-#else /* !TUNEFS */
+#else /* TUNEFS */
        /* update svname with '=' to refresh config */
        if (ldd->ldd_flags & LDD_F_WRITECONF) {
                struct mount_opts opts;
@@ -848,6 +907,13 @@ int main(int argc, char *const argv[])
                (void) osd_label_lustre(&opts);
        }
 
+       /* Rename filesystem fsname */
+       if (mop.mo_flags & MO_RENAME) {
+               ret = osd_rename_fsname(&mop, old_fsname);
+               if (ret)
+                       goto out;
+       }
+
        /* Enable quota accounting */
        if (mop.mo_flags & MO_QUOTA) {
                ret = osd_enable_quota(&mop);
index 2027b28..db05359 100644 (file)
 #include <sys/types.h>
 #include <dirent.h>
 #include <dlfcn.h>
+#include <lustre/lustre_idl.h>
+#include <lustre_cfg.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
 
 #ifdef HAVE_GSS
 #include <keyutils.h>
@@ -586,6 +591,7 @@ struct module_backfs_ops *load_backfs_module(enum ldd_mount_type mount_type)
        DLSYM(name, ops, prepare_lustre);
        DLSYM(name, ops, tune_lustre);
        DLSYM(name, ops, label_lustre);
+       DLSYM(name, ops, rename_fsname);
        DLSYM(name, ops, enable_quota);
 
        error = dlerror();
@@ -748,6 +754,21 @@ int osd_label_lustre(struct mount_opts *mop)
        return ret;
 }
 
+/* Rename filesystem fsname */
+int osd_rename_fsname(struct mkfs_opts *mop, const char *oldname)
+{
+       struct lustre_disk_data *ldd = &mop->mo_ldd;
+       int ret;
+
+       if (backfs_mount_type_okay(ldd->ldd_mount_type))
+               ret = backfs_ops[ldd->ldd_mount_type]->rename_fsname(mop,
+                                                                    oldname);
+       else
+               ret = EINVAL;
+
+       return ret;
+}
+
 /* Enable quota accounting */
 int osd_enable_quota(struct mkfs_opts *mop)
 {
@@ -875,6 +896,196 @@ int file_create(char *path, __u64 size)
        return 0;
 }
 
+
+struct lustre_cfg_entry {
+       struct list_head lce_list;
+       char             lce_name[0];
+};
+
+static struct lustre_cfg_entry *lustre_cfg_entry_init(const char *name)
+{
+       struct lustre_cfg_entry *lce;
+       int len = strlen(name) + 1;
+
+       lce = malloc(sizeof(*lce) + len);
+       if (lce) {
+               INIT_LIST_HEAD(&lce->lce_list);
+               memcpy(lce->lce_name, name, len);
+       }
+
+       return lce;
+}
+
+static void lustre_cfg_entry_fini(struct lustre_cfg_entry *lce)
+{
+       free(lce);
+}
+
+int lustre_rename_fsname(struct mkfs_opts *mop, const char *mntpt,
+                        const char *oldname)
+{
+       struct lustre_disk_data *ldd = &mop->mo_ldd;
+       struct lr_server_data lsd;
+       char filepnm[128];
+       char cfg_dir[128];
+       DIR *dir = NULL;
+       struct dirent64 *dirent;
+       struct lustre_cfg_entry *lce;
+       struct list_head cfg_list;
+       int old_namelen = strlen(oldname);
+       int new_namelen = strlen(ldd->ldd_fsname);
+       int ret;
+       int fd;
+
+       INIT_LIST_HEAD(&cfg_list);
+
+       snprintf(filepnm, sizeof(filepnm), "%s/%s", mntpt, LAST_RCVD);
+       fd = open(filepnm, O_RDWR);
+       if (fd < 0) {
+               if (errno == ENOENT)
+                       goto config;
+
+               if (errno != 0)
+                       ret = errno;
+               else
+                       ret = fd;
+               fprintf(stderr, "Unable to open %s: %s\n",
+                       filepnm, strerror(ret));
+               return ret;
+       }
+
+       ret = read(fd, &lsd, sizeof(lsd));
+       if (ret != sizeof(lsd)) {
+               if (errno != 0)
+                       ret = errno;
+               fprintf(stderr, "Unable to read %s: %s\n",
+                       filepnm, strerror(ret));
+               close(fd);
+               return ret;
+       }
+
+       ret = lseek(fd, 0, SEEK_SET);
+       if (ret) {
+               if (errno != 0)
+                       ret = errno;
+               fprintf(stderr, "Unable to lseek %s: %s\n",
+                       filepnm, strerror(ret));
+               close(fd);
+               return ret;
+       }
+
+       /* replace fsname in lr_server_data::lsd_uuid. */
+       if (old_namelen > new_namelen)
+               memmove(lsd.lsd_uuid + new_namelen,
+                       lsd.lsd_uuid + old_namelen,
+                       sizeof(lsd.lsd_uuid) - old_namelen);
+       else if (old_namelen < new_namelen)
+               memmove(lsd.lsd_uuid + new_namelen,
+                       lsd.lsd_uuid + old_namelen,
+                       sizeof(lsd.lsd_uuid) - new_namelen);
+       memcpy(lsd.lsd_uuid, ldd->ldd_fsname, new_namelen);
+       ret = write(fd, &lsd, sizeof(lsd));
+       if (ret != sizeof(lsd)) {
+               if (errno != 0)
+                       ret = errno;
+               fprintf(stderr, "Unable to write %s: %s\n",
+                       filepnm, strerror(ret));
+               close(fd);
+               return ret;
+       }
+
+       close(fd);
+
+config:
+       snprintf(cfg_dir, sizeof(cfg_dir), "%s/%s", mntpt, MOUNT_CONFIGS_DIR);
+       dir = opendir(cfg_dir);
+       if (!dir) {
+               if (errno != 0)
+                       ret = errno;
+               else
+                       ret = EINVAL;
+               fprintf(stderr, "Unable to opendir %s: %s\n",
+                       cfg_dir, strerror(ret));
+               return ret;
+       }
+
+       while ((dirent = readdir64(dir)) != NULL) {
+               char *ptr;
+
+               if (strlen(dirent->d_name) <= old_namelen)
+                       continue;
+
+               ptr = strrchr(dirent->d_name, '-');
+               if (!ptr || (ptr - dirent->d_name) != old_namelen)
+                       continue;
+
+               if (strncmp(dirent->d_name, oldname, old_namelen) != 0)
+                       continue;
+
+               lce = lustre_cfg_entry_init(dirent->d_name);
+               if (!lce) {
+                       if (errno != 0)
+                               ret = errno;
+                       else
+                               ret = EINVAL;
+
+                       fprintf(stderr, "Fail to init item for %s: %s\n",
+                               dirent->d_name, strerror(ret));
+                       goto out;
+               }
+
+               list_add(&lce->lce_list, &cfg_list);
+       }
+
+       closedir(dir);
+       dir = NULL;
+       ret = 0;
+
+       while (!list_empty(&cfg_list) && ret == 0) {
+               lce = list_entry(cfg_list.next, struct lustre_cfg_entry,
+                                lce_list);
+               list_del(&lce->lce_list);
+               snprintf(filepnm, sizeof(filepnm), "%s/%s", cfg_dir,
+                        lce->lce_name);
+               if (IS_MGS(ldd))
+                       /* Store the new fsname in the XATTR_TARGET_RENAME EA.
+                        * When the MGS start, it will scan config logs, and
+                        * for the ones which have the XATTR_TARGET_RENAME EA,
+                        * it will replace old fsname with the new fsname in
+                        * the config log by some shared kernel level config
+                        * logs {fork,erase} functionalities automatically. */
+                       ret = setxattr(filepnm, XATTR_TARGET_RENAME,
+                                      ldd->ldd_fsname,
+                                      strlen(ldd->ldd_fsname), 0);
+               else
+                       ret = unlink(filepnm);
+
+               if (ret) {
+                       if (errno != 0)
+                               ret = errno;
+
+                       fprintf(stderr, "Fail to %s %s: %s\n",
+                               IS_MGS(ldd) ? "setxattr" : "unlink",
+                               filepnm, strerror(ret));
+               }
+
+               lustre_cfg_entry_fini(lce);
+       }
+
+out:
+       if (dir)
+               closedir(dir);
+
+       while (!list_empty(&cfg_list)) {
+               lce = list_entry(cfg_list.next, struct lustre_cfg_entry,
+                                lce_list);
+               list_del(&lce->lce_list);
+               lustre_cfg_entry_fini(lce);
+       }
+
+       return ret;
+}
+
 #ifdef HAVE_GSS
 #ifdef HAVE_OPENSSL_SSK
 int load_shared_keys(struct mount_opts *mop)
index 16206a0..2b1ac8f 100644 (file)
@@ -72,6 +72,7 @@ extern int failover;
 #define MO_DRYRUN              0x08
 #define MO_QUOTA               0x10
 #define MO_NOHOSTID_CHECK      0x20
+#define MO_RENAME              0x40
 
 #define MAX_LOOP_DEVICES       16
 #define INDEX_UNASSIGNED       0xFFFF
@@ -141,6 +142,8 @@ int update_utab_entry(struct mount_opts *mop);
 int check_mountfsoptions(char *mountopts, char *wanted_mountopts);
 void trim_mountfsoptions(char *s);
 __u64 get_device_size(char* device);
+int lustre_rename_fsname(struct mkfs_opts *mop, const char *mntpt,
+                        const char *oldname);
 
 /* loopback helper functions */
 int file_create(char *path, __u64 size);
@@ -158,6 +161,7 @@ int osd_prepare_lustre(struct mkfs_opts *mop,
 int osd_fix_mountopts(struct mkfs_opts *mop, char *mountopts, size_t len);
 int osd_tune_lustre(char *dev, struct mount_opts *mop);
 int osd_label_lustre(struct mount_opts *mop);
+int osd_rename_fsname(struct mkfs_opts *mop, const char *oldname);
 int osd_enable_quota(struct mkfs_opts *mop);
 int osd_init(void);
 void osd_fini(void);
@@ -176,6 +180,7 @@ struct module_backfs_ops {
        int     (*tune_lustre)(char *dev, struct mount_opts *mop);
        int     (*label_lustre)(struct mount_opts *mop);
        int     (*enable_quota)(struct mkfs_opts *mop);
+       int     (*rename_fsname)(struct mkfs_opts *mop, const char *oldname);
        void   *dl_handle;
 };
 
index d93a483..b1edf54 100644 (file)
@@ -1314,6 +1314,69 @@ int ldiskfs_label_lustre(struct mount_opts *mop)
        return rc;
 }
 
+int ldiskfs_rename_fsname(struct mkfs_opts *mop, const char *oldname)
+{
+       struct mount_opts opts;
+       struct lustre_disk_data *ldd = &mop->mo_ldd;
+       char mntpt[] = "/tmp/mntXXXXXX";
+       char *dev;
+       int ret;
+
+       /* Change the filesystem label. */
+       opts.mo_ldd = *ldd;
+       opts.mo_source = mop->mo_device;
+       ret = ldiskfs_label_lustre(&opts);
+       if (ret) {
+               if (errno != 0)
+                       ret = errno;
+               fprintf(stderr, "Can't change filesystem label: %s\n",
+                       strerror(ret));
+               return ret;
+       }
+
+       /* Mount this device temporarily in order to write these files */
+       if (mkdtemp(mntpt) == NULL) {
+               if (errno != 0)
+                       ret = errno;
+               else
+                       ret = EINVAL;
+               fprintf(stderr, "Can't create temp mount point %s: %s\n",
+                       mntpt, strerror(ret));
+               return ret;
+       }
+
+#ifdef HAVE_SELINUX
+       /*
+        * Append file context to mount options if SE Linux is enabled
+        */
+       if (is_selinux_enabled() > 0)
+               append_context_for_mount(mntpt, mop);
+#endif
+
+       if (mop->mo_flags & MO_IS_LOOP)
+               dev = mop->mo_loopdev;
+       else
+               dev = mop->mo_device;
+       ret = mount(dev, mntpt, MT_STR(ldd), 0, ldd->ldd_mount_opts);
+       if (ret) {
+               if (errno != 0)
+                       ret = errno;
+               fprintf(stderr, "Unable to mount %s: %s\n",
+                       dev, strerror(ret));
+               if (ret == ENODEV)
+                       fprintf(stderr, "Is the %s module available?\n",
+                               MT_STR(ldd));
+               goto out_rmdir;
+       }
+
+       ret = lustre_rename_fsname(mop, mntpt, oldname);
+       umount(mntpt);
+
+out_rmdir:
+       rmdir(mntpt);
+       return ret;
+}
+
 /* Enable quota accounting */
 int ldiskfs_enable_quota(struct mkfs_opts *mop)
 {
index be29c3f..72dbb69 100644 (file)
@@ -680,6 +680,70 @@ int zfs_label_lustre(struct mount_opts *mop)
        return ret;
 }
 
+int zfs_rename_fsname(struct mkfs_opts *mop, const char *oldname)
+{
+       struct mount_opts opts;
+       char mntpt[] = "/tmp/mntXXXXXX";
+       char *cmd_buf;
+       int ret;
+
+       /* Change the filesystem label. */
+       opts.mo_ldd = mop->mo_ldd;
+       opts.mo_source = mop->mo_device;
+       ret = zfs_label_lustre(&opts);
+       if (ret) {
+               if (errno != 0)
+                       ret = errno;
+               fprintf(stderr, "Can't change filesystem label: %s\n",
+                       strerror(ret));
+               return ret;
+       }
+
+       /* Mount this device temporarily in order to write these files */
+       if (mkdtemp(mntpt) == NULL) {
+               if (errno != 0)
+                       ret = errno;
+               fprintf(stderr, "Can't create temp mount point %s: %s\n",
+                       mntpt, strerror(ret));
+               return ret;
+       }
+
+       cmd_buf = malloc(PATH_MAX);
+       if (!cmd_buf) {
+               ret = ENOMEM;
+               goto out_rmdir;
+       }
+
+       memset(cmd_buf, 0, PATH_MAX);
+       snprintf(cmd_buf, PATH_MAX - 1, "zfs set mountpoint=%s %s && "
+                "zfs set canmount=on %s && zfs mount %s",
+                mntpt, mop->mo_device, mop->mo_device, mop->mo_device);
+       ret = run_command(cmd_buf, PATH_MAX);
+       if (ret) {
+               if (errno != 0)
+                       ret = errno;
+               fprintf(stderr, "Unable to mount %s (%s)\n",
+                       mop->mo_device, strerror(ret));
+               if (ret == ENODEV)
+                       fprintf(stderr, "Is the %s module available?\n",
+                               MT_STR(&mop->mo_ldd));
+               goto out_free;
+       }
+
+       ret = lustre_rename_fsname(mop, mntpt, oldname);
+       memset(cmd_buf, 0, PATH_MAX);
+       snprintf(cmd_buf, PATH_MAX - 1, "zfs umount %s && "
+                "zfs set canmount=off %s && zfs set mountpoint=none %s",
+                mop->mo_device, mop->mo_device, mop->mo_device);
+       run_command(cmd_buf, PATH_MAX);
+
+out_free:
+       free(cmd_buf);
+out_rmdir:
+       rmdir(mntpt);
+       return ret;
+}
+
 int zfs_init(void)
 {
        int ret = 0;