8942 zfs promote .../%recv should be an error
illumos/illumos-gate@add927f8c8 Reported on the ZFSonLinux https://github.com/zfsonlinux/zfs/issues/4843, fixed by https://github.com/zfsonlinux/zfs/pull/6339: If we are in the middle of an incremental zfs receive, the child .../%recv will exist. If you concurrently run zfs promote .../%recv, it will "work", but then zfs gets confused. For example, there's no obvious way to destroy the containing filesystem (because it is now a clone of its invisible child). Attempting to do this promote should be an error. We could fix this by having zfs_ioc_promote() check if zc_name contains a %, similar to zfs_ioc_rename(). Reviewed by: Paul Dagnelie <pcd@delphix.com> Reviewed by: Matthew Ahrens <mahrens@delphix.com> Approved by: Dan McDonald <danmcd@joyent.com> Author: loli10K <ezomori.nozomu@gmail.com>
This commit is contained in:
parent
f6563f72a3
commit
76f8fe62dd
@ -3786,6 +3786,9 @@ zfs_promote(zfs_handle_t *zhp)
|
|||||||
return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
|
return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!zfs_validate_name(hdl, zhp->zfs_name, zhp->zfs_type, B_TRUE))
|
||||||
|
return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
|
||||||
|
|
||||||
ret = lzc_promote(zhp->zfs_name, snapname, sizeof (snapname));
|
ret = lzc_promote(zhp->zfs_name, snapname, sizeof (snapname));
|
||||||
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
@ -4156,6 +4159,10 @@ zfs_rename(zfs_handle_t *zhp, const char *source, const char *target,
|
|||||||
zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
|
zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* make sure source name is valid */
|
||||||
|
if (!zfs_validate_name(hdl, zhp->zfs_name, zhp->zfs_type, B_TRUE))
|
||||||
|
return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure the target name is valid
|
* Make sure the target name is valid
|
||||||
*/
|
*/
|
||||||
|
@ -3942,9 +3942,12 @@ zfs_ioc_rename(zfs_cmd_t *zc)
|
|||||||
allow_mounted = (zc->zc_cookie & 2) != 0;
|
allow_mounted = (zc->zc_cookie & 2) != 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* "zfs rename" from and to ...%recv datasets should both fail */
|
||||||
|
zc->zc_name[sizeof (zc->zc_name) - 1] = '\0';
|
||||||
zc->zc_value[sizeof (zc->zc_value) - 1] = '\0';
|
zc->zc_value[sizeof (zc->zc_value) - 1] = '\0';
|
||||||
if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 ||
|
if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0 ||
|
||||||
strchr(zc->zc_value, '%'))
|
dataset_namecheck(zc->zc_value, NULL, NULL) != 0 ||
|
||||||
|
strchr(zc->zc_name, '%') || strchr(zc->zc_value, '%'))
|
||||||
return (SET_ERROR(EINVAL));
|
return (SET_ERROR(EINVAL));
|
||||||
|
|
||||||
at = strchr(zc->zc_name, '@');
|
at = strchr(zc->zc_name, '@');
|
||||||
@ -4996,6 +4999,11 @@ zfs_ioc_promote(zfs_cmd_t *zc)
|
|||||||
char *cp;
|
char *cp;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
zc->zc_name[sizeof (zc->zc_name) - 1] = '\0';
|
||||||
|
if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0 ||
|
||||||
|
strchr(zc->zc_name, '%'))
|
||||||
|
return (SET_ERROR(EINVAL));
|
||||||
|
|
||||||
error = dsl_pool_hold(zc->zc_name, FTAG, &dp);
|
error = dsl_pool_hold(zc->zc_name, FTAG, &dp);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user