mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 18:40:43 +03:00
Add 'zfs rename -u' to rename without remounting
Allow to rename file systems without remounting if it is possible. It is possible for file systems with 'mountpoint' property 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. Authored by: Pawel Jakub Dawidek <pjd@FreeBSD.org> Reviewed-by: Allan Jude <allan@klarasystems.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Ported by: Matt Macy <mmacy@freebsd.org> Signed-off-by: Ryan Moeller <ryan@iXsystems.com> Closes #10839
This commit is contained in:
+30
-13
@@ -311,7 +311,8 @@ get_usage(zfs_help_t idx)
|
||||
case HELP_RENAME:
|
||||
return (gettext("\trename [-f] <filesystem|volume|snapshot> "
|
||||
"<filesystem|volume|snapshot>\n"
|
||||
"\trename [-f] -p <filesystem|volume> <filesystem|volume>\n"
|
||||
"\trename -p [-f] <filesystem|volume> <filesystem|volume>\n"
|
||||
"\trename -u [-f] <filesystem> <filesystem>\n"
|
||||
"\trename -r <snapshot> <snapshot>\n"));
|
||||
case HELP_ROLLBACK:
|
||||
return (gettext("\trollback [-rRf] <snapshot>\n"));
|
||||
@@ -3603,36 +3604,40 @@ zfs_do_list(int argc, char **argv)
|
||||
}
|
||||
|
||||
/*
|
||||
* zfs rename [-f] <fs | snap | vol> <fs | snap | vol>
|
||||
* zfs rename [-fu] <fs | snap | vol> <fs | snap | vol>
|
||||
* zfs rename [-f] -p <fs | vol> <fs | vol>
|
||||
* zfs rename -r <snap> <snap>
|
||||
* zfs rename [-u] -r <snap> <snap>
|
||||
*
|
||||
* Renames the given dataset to another of the same type.
|
||||
*
|
||||
* The '-p' flag creates all the non-existing ancestors of the target first.
|
||||
* The '-u' flag prevents file systems from being remounted during rename.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
zfs_do_rename(int argc, char **argv)
|
||||
{
|
||||
zfs_handle_t *zhp;
|
||||
renameflags_t flags = { 0 };
|
||||
int c;
|
||||
int ret = 0;
|
||||
boolean_t recurse = B_FALSE;
|
||||
int types;
|
||||
boolean_t parents = B_FALSE;
|
||||
boolean_t force_unmount = B_FALSE;
|
||||
|
||||
/* check options */
|
||||
while ((c = getopt(argc, argv, "prf")) != -1) {
|
||||
while ((c = getopt(argc, argv, "pruf")) != -1) {
|
||||
switch (c) {
|
||||
case 'p':
|
||||
parents = B_TRUE;
|
||||
break;
|
||||
case 'r':
|
||||
recurse = B_TRUE;
|
||||
flags.recursive = B_TRUE;
|
||||
break;
|
||||
case 'u':
|
||||
flags.nounmount = B_TRUE;
|
||||
break;
|
||||
case 'f':
|
||||
force_unmount = B_TRUE;
|
||||
flags.forceunmount = B_TRUE;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
@@ -3661,20 +3666,32 @@ zfs_do_rename(int argc, char **argv)
|
||||
usage(B_FALSE);
|
||||
}
|
||||
|
||||
if (recurse && parents) {
|
||||
if (flags.recursive && parents) {
|
||||
(void) fprintf(stderr, gettext("-p and -r options are mutually "
|
||||
"exclusive\n"));
|
||||
usage(B_FALSE);
|
||||
}
|
||||
|
||||
if (recurse && strchr(argv[0], '@') == 0) {
|
||||
if (flags.nounmount && parents) {
|
||||
(void) fprintf(stderr, gettext("-u and -p options are mutually "
|
||||
"exclusive\n"));
|
||||
usage(B_FALSE);
|
||||
}
|
||||
|
||||
if (flags.recursive && strchr(argv[0], '@') == 0) {
|
||||
(void) fprintf(stderr, gettext("source dataset for recursive "
|
||||
"rename must be a snapshot\n"));
|
||||
usage(B_FALSE);
|
||||
}
|
||||
|
||||
if ((zhp = zfs_open(g_zfs, argv[0], parents ? ZFS_TYPE_FILESYSTEM |
|
||||
ZFS_TYPE_VOLUME : ZFS_TYPE_DATASET)) == NULL)
|
||||
if (flags.nounmount)
|
||||
types = ZFS_TYPE_FILESYSTEM;
|
||||
else if (parents)
|
||||
types = ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME;
|
||||
else
|
||||
types = ZFS_TYPE_DATASET;
|
||||
|
||||
if ((zhp = zfs_open(g_zfs, argv[0], types)) == NULL)
|
||||
return (1);
|
||||
|
||||
/* If we were asked and the name looks good, try to create ancestors. */
|
||||
@@ -3684,7 +3701,7 @@ zfs_do_rename(int argc, char **argv)
|
||||
return (1);
|
||||
}
|
||||
|
||||
ret = (zfs_rename(zhp, argv[1], recurse, force_unmount) != 0);
|
||||
ret = (zfs_rename(zhp, argv[1], flags) != 0);
|
||||
|
||||
zfs_close(zhp);
|
||||
return (ret);
|
||||
|
||||
Reference in New Issue
Block a user