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,
#define LDD_F_MASK 0xFFFF
+#define XATTR_TARGET_RENAME "trusted.rename_tgt"
+
enum ldd_mount_type {
LDD_MT_EXT3 = 0,
LDD_MT_LDISKFS,
};
-#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,
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",
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 */
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)
{
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.
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);
}
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
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
}
#
+# 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.
#
if [[ $(facet_fstype $facet) == zfs ]]; then
# export ZFS storage pool
- export_zpool $facet
+ [ "$KEEP_ZPOOL" = "true" ] || export_zpool $facet
fi
}
"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
"\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"
}
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' },
{ "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 };
mop->mo_flags |= MO_FAILOVER;
break;
}
+ case 'G':
+ ldd->ldd_flags |= LDD_F_SV_TYPE_MGS;
+ break;
case 'h':
usage(stdout);
return 1;
case 'n':
print_only++;
break;
+ case 'N':
+ ldd->ldd_flags &= ~LDD_F_SV_TYPE_MGS;
+ break;
case 'o':
*mountopts = optarg;
break;
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));
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;
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;
}
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 "
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;
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;
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 */
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;
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;
(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);
#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>
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();
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)
{
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)
#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
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);
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);
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;
};
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)
{
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;