diff options
author | pjd <pjd@FreeBSD.org> | 2011-10-24 00:38:09 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2011-10-24 00:38:09 +0000 |
commit | abdbea665980cd149a350baa8450b4fc59a80b9e (patch) | |
tree | db90d18a179398559a19672e801a29f12acd49a4 /cddl | |
parent | 26b45aef71d0af57c82518de4e87288d5c515180 (diff) | |
download | FreeBSD-src-abdbea665980cd149a350baa8450b4fc59a80b9e.zip FreeBSD-src-abdbea665980cd149a350baa8450b4fc59a80b9e.tar.gz |
Allow to rename file systems without remounting if it is possible.
It is possible for file systems with 'mountpoint' preperty set to 'legacy'
or 'none' - we don't have to change mount directory for them.
Currently such file systems are unmounted on rename and not even mounted back.
This introduces layering violation, as we need to update 'f_mntfromname'
field in statfs structure related to mountpoint (for the dataset we are
renaming and all its children).
In my opinion it is worth it, as it allow to update FreeBSD in even cleaner
way - in ZFS-only configuration root file system is ZFS file system with
'mountpoint' property set to 'legacy'. If root dataset is named system/rootfs,
we can snapshot it (system/rootfs@upgrade), clone it (system/oldrootfs),
update FreeBSD and if it doesn't boot we can boot back from system/oldrootfs
and rename it back to system/rootfs while it is mounted as /. Before it was
not possible, because unmounting / was not possible.
MFC after: 2 weeks
Diffstat (limited to 'cddl')
3 files changed, 22 insertions, 3 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; |