Extend r226676 to allow rename without unmount even for file systems with
non-legacy mountpoints. It is better to be able to rename such file systems and let them be mounted in old places until next reboot than using live CD, etc. to rename with remount. This is implemented by adding -u option to 'zfs rename'. If file system's mountpoint property is set to 'legacy' or 'none', there is no need to specify -u. Update zfs(8) manual page to reflect this addition. MFC after: 2 weeks
This commit is contained in:
parent
3fa9ebcdfe
commit
3ebce5e218
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=226705
@ -74,6 +74,11 @@ zfs \- configures ZFS file systems
|
||||
\fBzfs\fR \fBrename\fR \fB-r\fR \fIsnapshot\fR \fIsnapshot\fR
|
||||
.fi
|
||||
|
||||
.LP
|
||||
.nf
|
||||
\fBzfs\fR \fBrename\fR \fB-u\fR [\fB-p\fR] \fIfilesystem\fR \fIfilesystem\fR
|
||||
.fi
|
||||
|
||||
.LP
|
||||
.nf
|
||||
\fBzfs\fR \fBlist\fR [\fB-r\fR|\fB-d\fR \fIdepth\fR][\fB-H\fR][\fB-o\fR \fIproperty\fR[,...]] [\fB-t\fR \fItype\fR[,...]]
|
||||
@ -1479,6 +1484,10 @@ The snapshot that was cloned, and any snapshots previous to this snapshot, are n
|
||||
.na
|
||||
\fB\fBzfs rename\fR [\fB-p\fR] \fIfilesystem\fR|\fIvolume\fR \fIfilesystem\fR|\fIvolume\fR\fR
|
||||
.ad
|
||||
.br
|
||||
.na
|
||||
\fB\fBzfs rename\fR \fB-u\fR [\fB-p\fR] \fIfilesystem\fR \fIfilesystem\fR\fR
|
||||
.ad
|
||||
.sp .6
|
||||
.RS 4n
|
||||
Renames the given dataset. The new target can be located anywhere in the \fBZFS\fR hierarchy, with the exception of snapshots. Snapshots can only be renamed within the parent file system or volume. When renaming a snapshot, the parent file system of the snapshot does not need to be specified as part of the second argument. Renamed file systems can inherit new mount points, in which case they are unmounted and remounted at the new mount point.
|
||||
@ -1493,6 +1502,17 @@ Renames the given dataset. The new target can be located anywhere in the \fBZFS\
|
||||
Creates all the nonexistent parent datasets. Datasets created in this manner are automatically mounted according to the \fBmountpoint\fR property inherited from their parent.
|
||||
.RE
|
||||
|
||||
.sp
|
||||
.ne 2
|
||||
.mk
|
||||
.na
|
||||
\fB\fB-u\fR\fR
|
||||
.ad
|
||||
.sp .6
|
||||
.RS 4n
|
||||
Do not remount file systems during rename. If a file system's \fBmountpoint\fR property is set to \fBlegacy\fR or \fBnone\fR, file system is not unmounted even if this option is not given.
|
||||
.RE
|
||||
|
||||
.RE
|
||||
|
||||
.sp
|
||||
|
@ -253,7 +253,8 @@ get_usage(zfs_help_t idx)
|
||||
return (gettext("\trename <filesystem|volume|snapshot> "
|
||||
"<filesystem|volume|snapshot>\n"
|
||||
"\trename -p <filesystem|volume> <filesystem|volume>\n"
|
||||
"\trename -r <snapshot> <snapshot>"));
|
||||
"\trename -r <snapshot> <snapshot>\n"
|
||||
"\trename -u [-p] <filesystem> <filesystem>"));
|
||||
case HELP_ROLLBACK:
|
||||
return (gettext("\trollback [-rRf] <snapshot>\n"));
|
||||
case HELP_SEND:
|
||||
@ -2851,6 +2852,7 @@ zfs_do_list(int argc, char **argv)
|
||||
* zfs rename <fs | snap | vol> <fs | snap | vol>
|
||||
* zfs rename -p <fs | vol> <fs | vol>
|
||||
* zfs rename -r <snap> <snap>
|
||||
* zfs rename -u [-p] <fs> <fs>
|
||||
*
|
||||
* Renames the given dataset to another of the same type.
|
||||
*
|
||||
@ -2861,19 +2863,21 @@ static int
|
||||
zfs_do_rename(int argc, char **argv)
|
||||
{
|
||||
zfs_handle_t *zhp;
|
||||
int c;
|
||||
int ret;
|
||||
boolean_t recurse = B_FALSE;
|
||||
renameflags_t flags = { 0 };
|
||||
int c, ret, types;
|
||||
boolean_t parents = B_FALSE;
|
||||
|
||||
/* check options */
|
||||
while ((c = getopt(argc, argv, "pr")) != -1) {
|
||||
while ((c = getopt(argc, argv, "pru")) != -1) {
|
||||
switch (c) {
|
||||
case 'p':
|
||||
parents = B_TRUE;
|
||||
break;
|
||||
case 'r':
|
||||
recurse = B_TRUE;
|
||||
flags.recurse = B_TRUE;
|
||||
break;
|
||||
case 'u':
|
||||
flags.nounmount = B_TRUE;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
@ -2902,20 +2906,32 @@ zfs_do_rename(int argc, char **argv)
|
||||
usage(B_FALSE);
|
||||
}
|
||||
|
||||
if (recurse && parents) {
|
||||
if (flags.recurse && parents) {
|
||||
(void) fprintf(stderr, gettext("-p and -r options are mutually "
|
||||
"exclusive\n"));
|
||||
usage(B_FALSE);
|
||||
}
|
||||
|
||||
if (recurse && strchr(argv[0], '@') == 0) {
|
||||
if (flags.recurse && 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 && parents) {
|
||||
(void) fprintf(stderr, gettext("-u and -r options are mutually "
|
||||
"exclusive\n"));
|
||||
usage(B_FALSE);
|
||||
}
|
||||
|
||||
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. */
|
||||
@ -2925,7 +2941,7 @@ zfs_do_rename(int argc, char **argv)
|
||||
return (1);
|
||||
}
|
||||
|
||||
ret = (zfs_rename(zhp, argv[1], recurse) != 0);
|
||||
ret = (zfs_rename(zhp, argv[1], flags) != 0);
|
||||
|
||||
zfs_close(zhp);
|
||||
return (ret);
|
||||
|
@ -518,7 +518,16 @@ extern int zfs_destroy_snaps(zfs_handle_t *, char *, boolean_t);
|
||||
extern int zfs_clone(zfs_handle_t *, const char *, nvlist_t *);
|
||||
extern int zfs_snapshot(libzfs_handle_t *, const char *, boolean_t, nvlist_t *);
|
||||
extern int zfs_rollback(zfs_handle_t *, zfs_handle_t *, boolean_t);
|
||||
extern int zfs_rename(zfs_handle_t *, const char *, boolean_t);
|
||||
|
||||
typedef struct renameflags {
|
||||
/* recursive rename */
|
||||
int recurse : 1;
|
||||
|
||||
/* don't unmount file systems */
|
||||
int nounmount : 1;
|
||||
} renameflags_t;
|
||||
|
||||
extern int zfs_rename(zfs_handle_t *, const char *, renameflags_t flags);
|
||||
|
||||
typedef struct sendflags {
|
||||
/* print informational messages (ie, -v was specified) */
|
||||
|
@ -122,10 +122,8 @@ 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)) {
|
||||
if (clp->cl_gflags & CL_GATHER_DONT_UNMOUNT)
|
||||
break;
|
||||
}
|
||||
if (zfs_unmount(cn->cn_handle, NULL,
|
||||
clp->cl_mflags) != 0) {
|
||||
ret = -1;
|
||||
@ -172,8 +170,10 @@ changelist_postfix(prop_changelist_t *clp)
|
||||
if ((cn = uu_list_last(clp->cl_list)) == NULL)
|
||||
return (0);
|
||||
|
||||
if (clp->cl_prop == ZFS_PROP_MOUNTPOINT)
|
||||
if (clp->cl_prop == ZFS_PROP_MOUNTPOINT &&
|
||||
!(clp->cl_gflags & CL_GATHER_DONT_UNMOUNT)) {
|
||||
remove_mountpoint(cn->cn_handle);
|
||||
}
|
||||
|
||||
/*
|
||||
* It is possible that the changelist_prefix() used libshare
|
||||
@ -228,7 +228,8 @@ changelist_postfix(prop_changelist_t *clp)
|
||||
shareopts, sizeof (shareopts), NULL, NULL, 0,
|
||||
B_FALSE) == 0) && (strcmp(shareopts, "off") != 0));
|
||||
|
||||
mounted = zfs_is_mounted(cn->cn_handle, NULL);
|
||||
mounted = (clp->cl_gflags & CL_GATHER_DONT_UNMOUNT) ||
|
||||
zfs_is_mounted(cn->cn_handle, NULL);
|
||||
|
||||
if (!mounted && (cn->cn_mounted ||
|
||||
((sharenfs || sharesmb || clp->cl_waslegacy) &&
|
||||
|
@ -3480,7 +3480,7 @@ zfs_iter_dependents(zfs_handle_t *zhp, boolean_t allowrecursion,
|
||||
* Renames the given dataset.
|
||||
*/
|
||||
int
|
||||
zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive)
|
||||
zfs_rename(zfs_handle_t *zhp, const char *target, renameflags_t flags)
|
||||
{
|
||||
int ret;
|
||||
zfs_cmd_t zc = { 0 };
|
||||
@ -3536,7 +3536,7 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive)
|
||||
if (!zfs_validate_name(hdl, target, zhp->zfs_type, B_TRUE))
|
||||
return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
|
||||
} else {
|
||||
if (recursive) {
|
||||
if (flags.recurse) {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"recursive rename must be a snapshot"));
|
||||
return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
|
||||
@ -3577,7 +3577,20 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive)
|
||||
return (zfs_error(hdl, EZFS_ZONED, errbuf));
|
||||
}
|
||||
|
||||
if (recursive) {
|
||||
/*
|
||||
* Avoid unmounting file systems with mountpoint property set to
|
||||
* 'legacy' or 'none' even if -u option is not given.
|
||||
*/
|
||||
if (zhp->zfs_type == ZFS_TYPE_FILESYSTEM &&
|
||||
!flags.recurse && !flags.nounmount &&
|
||||
zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, property,
|
||||
sizeof (property), NULL, NULL, 0, B_FALSE) == 0 &&
|
||||
(strcmp(property, "legacy") == 0 ||
|
||||
strcmp(property, "none") == 0)) {
|
||||
flags.nounmount = B_TRUE;
|
||||
}
|
||||
|
||||
if (flags.recurse) {
|
||||
|
||||
parentname = zfs_strdup(zhp->zfs_hdl, zhp->zfs_name);
|
||||
if (parentname == NULL) {
|
||||
@ -3594,7 +3607,7 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive)
|
||||
|
||||
} else {
|
||||
if ((cl = changelist_gather(zhp, ZFS_PROP_NAME,
|
||||
CL_GATHER_KEEP_LEGACY, 0)) == NULL) {
|
||||
flags.nounmount ? CL_GATHER_DONT_UNMOUNT : 0, 0)) == NULL) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@ -3618,13 +3631,9 @@ 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 ? 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 = flags.recurse ? 1 : 0;
|
||||
if (flags.nounmount)
|
||||
zc.zc_cookie |= 2;
|
||||
}
|
||||
|
||||
if ((ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_RENAME, &zc)) != 0) {
|
||||
/*
|
||||
@ -3634,7 +3643,7 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive)
|
||||
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
|
||||
"cannot rename '%s'"), zc.zc_name);
|
||||
|
||||
if (recursive && errno == EEXIST) {
|
||||
if (flags.recurse && errno == EEXIST) {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"a child dataset already has a snapshot "
|
||||
"with the new name"));
|
||||
@ -3647,10 +3656,10 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive)
|
||||
* On failure, we still want to remount any filesystems that
|
||||
* were previously mounted, so we don't alter the system state.
|
||||
*/
|
||||
if (!recursive)
|
||||
if (!flags.recurse)
|
||||
(void) changelist_postfix(cl);
|
||||
} else {
|
||||
if (!recursive) {
|
||||
if (!flags.recurse) {
|
||||
changelist_rename(cl, zfs_get_name(zhp), target);
|
||||
ret = changelist_postfix(cl);
|
||||
}
|
||||
|
@ -160,11 +160,9 @@ int zprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp,
|
||||
*/
|
||||
#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.
|
||||
* Use this changelist_gather() flag to prevent unmounting of file systems.
|
||||
*/
|
||||
#define CL_GATHER_KEEP_LEGACY 0x02
|
||||
#define CL_GATHER_DONT_UNMOUNT 0x02
|
||||
|
||||
typedef struct prop_changelist prop_changelist_t;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user