Changeset View
Changeset View
Standalone View
Standalone View
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
Show First 20 Lines • Show All 218 Lines • ▼ Show 20 Lines | |||||
typedef int zfs_ioc_legacy_func_t(zfs_cmd_t *); | typedef int zfs_ioc_legacy_func_t(zfs_cmd_t *); | ||||
typedef int zfs_ioc_func_t(const char *, nvlist_t *, nvlist_t *); | typedef int zfs_ioc_func_t(const char *, nvlist_t *, nvlist_t *); | ||||
typedef int zfs_secpolicy_func_t(zfs_cmd_t *, nvlist_t *, cred_t *); | typedef int zfs_secpolicy_func_t(zfs_cmd_t *, nvlist_t *, cred_t *); | ||||
typedef enum { | typedef enum { | ||||
NO_NAME, | NO_NAME, | ||||
POOL_NAME, | POOL_NAME, | ||||
DATASET_NAME | DATASET_NAME, | ||||
ENTITY_NAME | |||||
} zfs_ioc_namecheck_t; | } zfs_ioc_namecheck_t; | ||||
typedef enum { | typedef enum { | ||||
POOL_CHECK_NONE = 1 << 0, | POOL_CHECK_NONE = 1 << 0, | ||||
POOL_CHECK_SUSPENDED = 1 << 1, | POOL_CHECK_SUSPENDED = 1 << 1, | ||||
POOL_CHECK_READONLY = 1 << 2, | POOL_CHECK_READONLY = 1 << 2, | ||||
} zfs_ioc_poolcheck_t; | } zfs_ioc_poolcheck_t; | ||||
▲ Show 20 Lines • Show All 681 Lines • ▼ Show 20 Lines | zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) | ||||
return (error); | return (error); | ||||
} | } | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
static int | static int | ||||
zfs_secpolicy_rename(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr) | zfs_secpolicy_rename(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr) | ||||
{ | { | ||||
char *at = NULL; | char *at = NULL; | ||||
char *pound; | |||||
int error; | int error; | ||||
if ((pound = strchr(zc->zc_name, '#')) != NULL) { | |||||
*pound = '\0'; | |||||
error = zfs_secpolicy_write_perms(zc->zc_name, | |||||
ZFS_DELEG_PERM_RENAME, cr); | |||||
if (error == 0) { | |||||
error = zfs_secpolicy_write_perms(zc->zc_name, | |||||
ZFS_DELEG_PERM_BOOKMARK, cr); | |||||
} | |||||
*pound = '#'; | |||||
return (error); | |||||
} | |||||
if ((zc->zc_cookie & 1) != 0) { | if ((zc->zc_cookie & 1) != 0) { | ||||
/* | /* | ||||
* This is recursive rename, so the starting snapshot might | * This is recursive rename, so the starting snapshot might | ||||
* not exist. Check file system or volume permission instead. | * not exist. Check file system or volume permission instead. | ||||
*/ | */ | ||||
at = strchr(zc->zc_name, '@'); | at = strchr(zc->zc_name, '@'); | ||||
if (at == NULL) | if (at == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
▲ Show 20 Lines • Show All 3,080 Lines • ▼ Show 20 Lines | recursive_unmount(const char *fsname, void *arg) | ||||
(void) snprintf(fullname, sizeof (fullname), "%s@%s", fsname, snapname); | (void) snprintf(fullname, sizeof (fullname), "%s@%s", fsname, snapname); | ||||
zfs_unmount_snap(fullname); | zfs_unmount_snap(fullname); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* inputs: | * inputs: | ||||
* zc_name old name of dataset | * zc_name old name of dataset or bookmark | ||||
* zc_value new name of dataset | * zc_value new name of dataset or bookmark | ||||
* zc_cookie recursive flag (only valid for snapshots) | * zc_cookie recursive flag (only valid for snapshots) | ||||
* | * | ||||
* outputs: none | * outputs: none | ||||
*/ | */ | ||||
static int | static int | ||||
zfs_ioc_rename(zfs_cmd_t *zc) | zfs_ioc_rename(zfs_cmd_t *zc) | ||||
{ | { | ||||
objset_t *os; | objset_t *os; | ||||
dmu_objset_type_t ost; | dmu_objset_type_t ost; | ||||
boolean_t recursive = zc->zc_cookie & 1; | boolean_t recursive = zc->zc_cookie & 1; | ||||
char *at; | char *pos, *pos2; | ||||
boolean_t allow_mounted = B_TRUE; | boolean_t allow_mounted = B_TRUE; | ||||
int err; | int err; | ||||
#ifdef __FreeBSD__ | #ifdef __FreeBSD__ | ||||
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_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'; | ||||
pos = strchr(zc->zc_name, '#'); | |||||
if (pos != NULL) { | |||||
/* Bookmarks must be in same fs. */ | |||||
pos2 = strchr(zc->zc_value, '#'); | |||||
if (pos2 == NULL) | |||||
return (SET_ERROR(EINVAL)); | |||||
/* Recursive flag is not supported yet. */ | |||||
if (recursive) | |||||
return (SET_ERROR(ENOTSUP)); | |||||
*pos = '\0'; | |||||
*pos2 = '\0'; | |||||
if (strcmp(zc->zc_name, zc->zc_value) == 0) { | |||||
err = dsl_bookmark_rename(zc->zc_name, | |||||
pos + 1, pos2 + 1); | |||||
} else { | |||||
err = SET_ERROR(EXDEV); | |||||
} | |||||
*pos = '#'; | |||||
*pos2 = '#'; | |||||
return (err); | |||||
} | |||||
/* "zfs rename" from and to ...%recv datasets should both fail */ | |||||
if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0 || | if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0 || | ||||
dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || | dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || | ||||
strchr(zc->zc_name, '%') || strchr(zc->zc_value, '%')) | strchr(zc->zc_name, '%') || strchr(zc->zc_value, '%')) | ||||
return (SET_ERROR(EINVAL)); | return (SET_ERROR(EINVAL)); | ||||
err = dmu_objset_hold(zc->zc_name, FTAG, &os); | err = dmu_objset_hold(zc->zc_name, FTAG, &os); | ||||
if (err != 0) | if (err != 0) | ||||
return (err); | return (err); | ||||
ost = dmu_objset_type(os); | ost = dmu_objset_type(os); | ||||
dmu_objset_rele(os, FTAG); | dmu_objset_rele(os, FTAG); | ||||
at = strchr(zc->zc_name, '@'); | pos = strchr(zc->zc_name, '@'); | ||||
if (at != NULL) { | if (pos != NULL) { | ||||
/* snaps must be in same fs */ | /* Snapshots must be in same fs. */ | ||||
int error; | pos2 = strchr(zc->zc_value, '@'); | ||||
if (pos2 == NULL) | |||||
if (strncmp(zc->zc_name, zc->zc_value, at - zc->zc_name + 1)) | return (SET_ERROR(EINVAL)); | ||||
return (SET_ERROR(EXDEV)); | *pos = '\0'; | ||||
*at = '\0'; | *pos2 = '\0'; | ||||
if (strcmp(zc->zc_name, zc->zc_value) != 0) { | |||||
err = SET_ERROR(EXDEV); | |||||
} else { | |||||
if (ost == DMU_OST_ZFS && !allow_mounted) { | if (ost == DMU_OST_ZFS && !allow_mounted) { | ||||
error = dmu_objset_find(zc->zc_name, | err = dmu_objset_find(zc->zc_name, | ||||
recursive_unmount, at + 1, | recursive_unmount, pos + 1, | ||||
recursive ? DS_FIND_CHILDREN : 0); | recursive ? DS_FIND_CHILDREN : 0); | ||||
if (error != 0) { | |||||
*at = '@'; | |||||
return (error); | |||||
} | } | ||||
if (err == 0) { | |||||
err = dsl_dataset_rename_snapshot(zc->zc_name, | |||||
pos + 1, pos2 + 1, recursive); | |||||
} | } | ||||
error = dsl_dataset_rename_snapshot(zc->zc_name, | } | ||||
at + 1, strchr(zc->zc_value, '@') + 1, recursive); | *pos = '@'; | ||||
*at = '@'; | *pos2 = '@'; | ||||
return (err); | |||||
return (error); | |||||
} else { | } else { | ||||
#ifdef illumos | #ifdef illumos | ||||
if (ost == DMU_OST_ZVOL) | if (ost == DMU_OST_ZVOL) | ||||
(void) zvol_remove_minor(zc->zc_name); | (void) zvol_remove_minor(zc->zc_name); | ||||
#endif | #endif | ||||
return (dsl_dir_rename(zc->zc_name, zc->zc_value)); | return (dsl_dir_rename(zc->zc_name, zc->zc_value)); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 2,260 Lines • ▼ Show 20 Lines | zfs_ioctl_register_dataset_read_secpolicy(ZFS_IOC_USERSPACE_MANY, | ||||
zfs_ioc_userspace_many, zfs_secpolicy_userspace_many); | zfs_ioc_userspace_many, zfs_secpolicy_userspace_many); | ||||
zfs_ioctl_register_dataset_read_secpolicy(ZFS_IOC_SEND, | zfs_ioctl_register_dataset_read_secpolicy(ZFS_IOC_SEND, | ||||
zfs_ioc_send, zfs_secpolicy_send); | zfs_ioc_send, zfs_secpolicy_send); | ||||
zfs_ioctl_register_dataset_modify(ZFS_IOC_SET_PROP, zfs_ioc_set_prop, | zfs_ioctl_register_dataset_modify(ZFS_IOC_SET_PROP, zfs_ioc_set_prop, | ||||
zfs_secpolicy_none); | zfs_secpolicy_none); | ||||
zfs_ioctl_register_dataset_modify(ZFS_IOC_DESTROY, zfs_ioc_destroy, | zfs_ioctl_register_dataset_modify(ZFS_IOC_DESTROY, zfs_ioc_destroy, | ||||
zfs_secpolicy_destroy); | zfs_secpolicy_destroy); | ||||
zfs_ioctl_register_dataset_modify(ZFS_IOC_RENAME, zfs_ioc_rename, | |||||
zfs_secpolicy_rename); | |||||
zfs_ioctl_register_dataset_modify(ZFS_IOC_RECV, zfs_ioc_recv, | zfs_ioctl_register_dataset_modify(ZFS_IOC_RECV, zfs_ioc_recv, | ||||
zfs_secpolicy_recv); | zfs_secpolicy_recv); | ||||
zfs_ioctl_register_dataset_modify(ZFS_IOC_PROMOTE, zfs_ioc_promote, | zfs_ioctl_register_dataset_modify(ZFS_IOC_PROMOTE, zfs_ioc_promote, | ||||
zfs_secpolicy_promote); | zfs_secpolicy_promote); | ||||
zfs_ioctl_register_dataset_modify(ZFS_IOC_INHERIT_PROP, | zfs_ioctl_register_dataset_modify(ZFS_IOC_INHERIT_PROP, | ||||
zfs_ioc_inherit_prop, zfs_secpolicy_inherit_prop); | zfs_ioc_inherit_prop, zfs_secpolicy_inherit_prop); | ||||
zfs_ioctl_register_dataset_modify(ZFS_IOC_SET_FSACL, zfs_ioc_set_fsacl, | zfs_ioctl_register_dataset_modify(ZFS_IOC_SET_FSACL, zfs_ioc_set_fsacl, | ||||
zfs_secpolicy_set_fsacl); | zfs_secpolicy_set_fsacl); | ||||
/* | |||||
* Not using zfs_ioctl_register_dataset_modify as DATASET_NAME check | |||||
* won't allow a bookmark name. | |||||
*/ | |||||
zfs_ioctl_register_legacy(ZFS_IOC_RENAME, zfs_ioc_rename, | |||||
zfs_secpolicy_rename, ENTITY_NAME, B_TRUE, | |||||
POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY); | |||||
zfs_ioctl_register_dataset_nolog(ZFS_IOC_SHARE, zfs_ioc_share, | zfs_ioctl_register_dataset_nolog(ZFS_IOC_SHARE, zfs_ioc_share, | ||||
zfs_secpolicy_share, POOL_CHECK_NONE); | zfs_secpolicy_share, POOL_CHECK_NONE); | ||||
zfs_ioctl_register_dataset_nolog(ZFS_IOC_SMB_ACL, zfs_ioc_smb_acl, | zfs_ioctl_register_dataset_nolog(ZFS_IOC_SMB_ACL, zfs_ioc_smb_acl, | ||||
zfs_secpolicy_smb_acl, POOL_CHECK_NONE); | zfs_secpolicy_smb_acl, POOL_CHECK_NONE); | ||||
zfs_ioctl_register_dataset_nolog(ZFS_IOC_USERSPACE_UPGRADE, | zfs_ioctl_register_dataset_nolog(ZFS_IOC_USERSPACE_UPGRADE, | ||||
zfs_ioc_userspace_upgrade, zfs_secpolicy_userspace_upgrade, | zfs_ioc_userspace_upgrade, zfs_secpolicy_userspace_upgrade, | ||||
POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY); | POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY); | ||||
zfs_ioctl_register_dataset_nolog(ZFS_IOC_TMP_SNAPSHOT, | zfs_ioctl_register_dataset_nolog(ZFS_IOC_TMP_SNAPSHOT, | ||||
Show All 13 Lines | |||||
int | int | ||||
pool_status_check(const char *name, zfs_ioc_namecheck_t type, | pool_status_check(const char *name, zfs_ioc_namecheck_t type, | ||||
zfs_ioc_poolcheck_t check) | zfs_ioc_poolcheck_t check) | ||||
{ | { | ||||
spa_t *spa; | spa_t *spa; | ||||
int error; | int error; | ||||
ASSERT(type == POOL_NAME || type == DATASET_NAME); | ASSERT(type == POOL_NAME || type == DATASET_NAME || | ||||
type == ENTITY_NAME); | |||||
if (check & POOL_CHECK_NONE) | if (check & POOL_CHECK_NONE) | ||||
return (0); | return (0); | ||||
error = spa_open(name, &spa, FTAG); | error = spa_open(name, &spa, FTAG); | ||||
if (error == 0) { | if (error == 0) { | ||||
if ((check & POOL_CHECK_SUSPENDED) && spa_suspended(spa)) | if ((check & POOL_CHECK_SUSPENDED) && spa_suspended(spa)) | ||||
error = SET_ERROR(EAGAIN); | error = SET_ERROR(EAGAIN); | ||||
▲ Show 20 Lines • Show All 314 Lines • ▼ Show 20 Lines | case POOL_NAME: | ||||
break; | break; | ||||
case DATASET_NAME: | case DATASET_NAME: | ||||
if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0) | if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0) | ||||
error = SET_ERROR(EINVAL); | error = SET_ERROR(EINVAL); | ||||
else | else | ||||
error = pool_status_check(zc->zc_name, | error = pool_status_check(zc->zc_name, | ||||
vec->zvec_namecheck, vec->zvec_pool_check); | vec->zvec_namecheck, vec->zvec_pool_check); | ||||
break; | |||||
case ENTITY_NAME: | |||||
if (entity_namecheck(zc->zc_name, NULL, NULL) != 0) { | |||||
error = SET_ERROR(EINVAL); | |||||
} else { | |||||
error = pool_status_check(zc->zc_name, | |||||
vec->zvec_namecheck, vec->zvec_pool_check); | |||||
} | |||||
break; | break; | ||||
case NO_NAME: | case NO_NAME: | ||||
break; | break; | ||||
} | } | ||||
if (error == 0) | if (error == 0) | ||||
error = vec->zvec_secpolicy(zc, innvl, cr); | error = vec->zvec_secpolicy(zc, innvl, cr); | ||||
▲ Show 20 Lines • Show All 451 Lines • Show Last 20 Lines |