summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_changelist.c4
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c13
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h8
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c6
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c15
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h8
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dir.h2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_vfsops.h4
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c12
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c32
11 files changed, 91 insertions, 15 deletions
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_changelist.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_changelist.c
index 84b9300..8f222a9 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_changelist.c
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_changelist.c
@@ -122,6 +122,10 @@ changelist_prefix(prop_changelist_t *clp)
*/
switch (clp->cl_prop) {
case ZFS_PROP_MOUNTPOINT:
+ if (clp->cl_waslegacy &&
+ (clp->cl_gflags & CL_GATHER_KEEP_LEGACY)) {
+ break;
+ }
if (zfs_unmount(cn->cn_handle, NULL,
clp->cl_mflags) != 0) {
ret = -1;
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
index 381f5ed..bdd48b1 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
@@ -3489,6 +3489,7 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive)
zfs_handle_t *zhrp = NULL;
char *parentname = NULL;
char parent[ZFS_MAXNAMELEN];
+ char property[ZFS_MAXPROPLEN];
libzfs_handle_t *hdl = zhp->zfs_hdl;
char errbuf[1024];
@@ -3592,8 +3593,10 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive)
}
} else {
- if ((cl = changelist_gather(zhp, ZFS_PROP_NAME, 0, 0)) == NULL)
+ if ((cl = changelist_gather(zhp, ZFS_PROP_NAME,
+ CL_GATHER_KEEP_LEGACY, 0)) == NULL) {
return (-1);
+ }
if (changelist_haszonedchild(cl)) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
@@ -3615,7 +3618,13 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive)
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
(void) strlcpy(zc.zc_value, target, sizeof (zc.zc_value));
- zc.zc_cookie = recursive;
+ zc.zc_cookie = recursive ? 1 : 0;
+ if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, property, sizeof (property),
+ NULL, NULL, 0, B_FALSE) == 0 &&
+ (strcmp(property, "legacy") == 0 ||
+ strcmp(property, "none") == 0)) {
+ zc.zc_cookie |= 2;
+ }
if ((ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_RENAME, &zc)) != 0) {
/*
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h
index 9d1ecb7..db4aca7 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h
@@ -158,7 +158,13 @@ int zprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp,
* on each change node regardless of whether or not it is currently
* mounted.
*/
-#define CL_GATHER_MOUNT_ALWAYS 1
+#define CL_GATHER_MOUNT_ALWAYS 0x01
+/*
+ * Use this changelist_gather() flag to prevent unmounting of legacy
+ * file systems. Useful when renaming legacy file systems, where there is
+ * no need to unmount them.
+ */
+#define CL_GATHER_KEEP_LEGACY 0x02
typedef struct prop_changelist prop_changelist_t;
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
index 498352e..140af06 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
@@ -2461,7 +2461,7 @@ dsl_valid_rename(const char *oldname, void *arg)
#pragma weak dmu_objset_rename = dsl_dataset_rename
int
-dsl_dataset_rename(char *oldname, const char *newname, boolean_t recursive)
+dsl_dataset_rename(char *oldname, const char *newname, int flags)
{
dsl_dir_t *dd;
dsl_dataset_t *ds;
@@ -2481,7 +2481,7 @@ dsl_dataset_rename(char *oldname, const char *newname, boolean_t recursive)
&delta, DS_FIND_CHILDREN | DS_FIND_SNAPSHOTS);
if (err == 0)
- err = dsl_dir_rename(dd, newname);
+ err = dsl_dir_rename(dd, newname, flags);
dsl_dir_close(dd, FTAG);
return (err);
}
@@ -2502,7 +2502,7 @@ dsl_dataset_rename(char *oldname, const char *newname, boolean_t recursive)
if (strncmp(oldname, newname, tail - newname) != 0)
return (EXDEV);
- if (recursive) {
+ if (flags & ZFS_RENAME_RECURSIVE) {
err = dsl_recursive_rename(oldname, newname);
} else {
err = dsl_dataset_hold(oldname, FTAG, &ds);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c
index 013e811..bb22dfb 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c
@@ -37,6 +37,7 @@
#include <sys/arc.h>
#include <sys/sunddi.h>
#include <sys/zvol.h>
+#include <sys/zfs_vfsops.h>
#include "zfs_namecheck.h"
static uint64_t dsl_dir_space_towrite(dsl_dir_t *dd);
@@ -1245,6 +1246,7 @@ would_change(dsl_dir_t *dd, int64_t delta, dsl_dir_t *ancestor)
struct renamearg {
dsl_dir_t *newparent;
const char *mynewname;
+ boolean_t islegacy;
};
static int
@@ -1263,9 +1265,13 @@ dsl_dir_rename_check(void *arg1, void *arg2, dmu_tx_t *tx)
* stats), but any that are present in open context will likely
* be gone by syncing context, so only fail from syncing
* context.
+ * Don't check if we are renaming dataset with mountpoint set to
+ * "legacy" or "none".
*/
- if (dmu_tx_is_syncing(tx) && dmu_buf_refcount(dd->dd_dbuf) > 1)
+ if (!ra->islegacy && dmu_tx_is_syncing(tx) &&
+ dmu_buf_refcount(dd->dd_dbuf) > 1) {
return (EBUSY);
+ }
/* check for existing name */
err = zap_lookup(mos, ra->newparent->dd_phys->dd_child_dir_zapobj,
@@ -1302,7 +1308,7 @@ dsl_dir_rename_sync(void *arg1, void *arg2, dmu_tx_t *tx)
objset_t *mos = dp->dp_meta_objset;
int err;
- ASSERT(dmu_buf_refcount(dd->dd_dbuf) <= 2);
+ ASSERT(ra->islegacy || dmu_buf_refcount(dd->dd_dbuf) <= 2);
if (ra->newparent != dd->dd_parent) {
dsl_dir_diduse_space(dd->dd_parent, DD_USED_CHILD,
@@ -1345,6 +1351,7 @@ dsl_dir_rename_sync(void *arg1, void *arg2, dmu_tx_t *tx)
ASSERT3U(err, ==, 0);
dsl_dir_name(dd, newname);
#ifdef _KERNEL
+ zfsvfs_update_fromname(oldname, newname);
zvol_rename_minors(oldname, newname);
#endif
@@ -1353,7 +1360,7 @@ dsl_dir_rename_sync(void *arg1, void *arg2, dmu_tx_t *tx)
}
int
-dsl_dir_rename(dsl_dir_t *dd, const char *newname)
+dsl_dir_rename(dsl_dir_t *dd, const char *newname, int flags)
{
struct renamearg ra;
int err;
@@ -1375,6 +1382,8 @@ dsl_dir_rename(dsl_dir_t *dd, const char *newname)
goto out;
}
+ ra.islegacy = !!(flags & ZFS_RENAME_IS_LEGACY);
+
err = dsl_sync_task_do(dd->dd_pool,
dsl_dir_rename_check, dsl_dir_rename_sync, dd, &ra, 3);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h
index 22733d0..ba2446e 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h
@@ -178,6 +178,12 @@ struct dsl_ds_holdarg {
char failed[MAXPATHLEN];
};
+/*
+ * Flags for dsl_dataset_rename().
+ */
+#define ZFS_RENAME_RECURSIVE 0x01
+#define ZFS_RENAME_IS_LEGACY 0x02
+
#define dsl_dataset_is_snapshot(ds) \
((ds)->ds_phys->ds_num_children != 0)
@@ -211,7 +217,7 @@ dsl_syncfunc_t dsl_dataset_destroy_sync;
dsl_checkfunc_t dsl_dataset_snapshot_check;
dsl_syncfunc_t dsl_dataset_snapshot_sync;
dsl_syncfunc_t dsl_dataset_user_hold_sync;
-int dsl_dataset_rename(char *name, const char *newname, boolean_t recursive);
+int dsl_dataset_rename(char *name, const char *newname, int flags);
int dsl_dataset_promote(const char *name, char *conflsnap);
int dsl_dataset_clone_swap(dsl_dataset_t *clone, dsl_dataset_t *origin_head,
boolean_t force);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dir.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dir.h
index 2191635..1ff03f4 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dir.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dir.h
@@ -131,7 +131,7 @@ int dsl_dir_set_quota(const char *ddname, zprop_source_t source,
uint64_t quota);
int dsl_dir_set_reservation(const char *ddname, zprop_source_t source,
uint64_t reservation);
-int dsl_dir_rename(dsl_dir_t *dd, const char *newname);
+int dsl_dir_rename(dsl_dir_t *dd, const char *newname, int flags);
int dsl_dir_transfer_possible(dsl_dir_t *sdd, dsl_dir_t *tdd, uint64_t space);
int dsl_dir_set_reservation_check(void *arg1, void *arg2, dmu_tx_t *tx);
boolean_t dsl_dir_is_clone(dsl_dir_t *dd);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_vfsops.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_vfsops.h
index 0560672..d4ef330 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_vfsops.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_vfsops.h
@@ -153,6 +153,10 @@ extern void zfsvfs_free(zfsvfs_t *zfsvfs);
extern int zfs_check_global_label(const char *dsname, const char *hexsl);
extern int zfs_vnode_lock(vnode_t *vp, int flags);
+#ifdef _KERNEL
+extern void zfsvfs_update_fromname(const char *oldname, const char *newname);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
index 7372ee7..f7a4fb3 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
@@ -785,7 +785,7 @@ zfsctl_snapdir_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm,
return (ENOENT);
}
- err = dmu_objset_rename(from, to, B_FALSE);
+ err = dmu_objset_rename(from, to, 0);
if (err == 0)
zfsctl_rename_snap(sdp, sep, tnm);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
index 17174b2..8fe9287 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
@@ -3261,7 +3261,12 @@ out:
static int
zfs_ioc_rename(zfs_cmd_t *zc)
{
- boolean_t recursive = zc->zc_cookie & 1;
+ int flags = 0;
+
+ if (zc->zc_cookie & 1)
+ flags |= ZFS_RENAME_RECURSIVE;
+ if (zc->zc_cookie & 2)
+ flags |= ZFS_RENAME_IS_LEGACY;
zc->zc_value[sizeof (zc->zc_value) - 1] = '\0';
if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 ||
@@ -3273,13 +3278,14 @@ zfs_ioc_rename(zfs_cmd_t *zc)
* in which case the dataset code figures out which snapshots
* to unmount.
*/
- if (!recursive && strchr(zc->zc_name, '@') != NULL &&
+ if (!(flags & ZFS_RENAME_RECURSIVE) &&
+ strchr(zc->zc_name, '@') != NULL &&
zc->zc_objset_type == DMU_OST_ZFS) {
int err = zfs_unmount_snap(zc->zc_name, NULL);
if (err)
return (err);
}
- return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive));
+ return (dmu_objset_rename(zc->zc_name, zc->zc_value, flags));
}
static int
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
index eff9779..2e57eab 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
@@ -2416,3 +2416,35 @@ zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value)
}
return (error);
}
+
+#ifdef _KERNEL
+void
+zfsvfs_update_fromname(const char *oldname, const char *newname)
+{
+ char tmpbuf[MAXPATHLEN];
+ struct mount *mp;
+ char *fromname;
+ size_t oldlen;
+
+ oldlen = strlen(oldname);
+
+ mtx_lock(&mountlist_mtx);
+ TAILQ_FOREACH(mp, &mountlist, mnt_list) {
+ fromname = mp->mnt_stat.f_mntfromname;
+ if (strcmp(fromname, oldname) == 0) {
+ (void)strlcpy(fromname, newname,
+ sizeof(mp->mnt_stat.f_mntfromname));
+ continue;
+ }
+ if (strncmp(fromname, oldname, oldlen) == 0 &&
+ fromname[oldlen] == '/') {
+ (void)snprintf(tmpbuf, sizeof(tmpbuf), "%s%s",
+ newname, fromname + oldlen);
+ (void)strlcpy(fromname, tmpbuf,
+ sizeof(mp->mnt_stat.f_mntfromname));
+ continue;
+ }
+ }
+ mtx_unlock(&mountlist_mtx);
+}
+#endif
OpenPOWER on IntegriCloud