Changeset View
Changeset View
Standalone View
Standalone View
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
Context not available. | |||||
ZFS_DELEG_PERM_GROUPQUOTA, | ZFS_DELEG_PERM_GROUPQUOTA, | ||||
}; | }; | ||||
typedef enum { | |||||
RENAME_OP, | |||||
PROMOTE_OP | |||||
} zfs_ioc_queue_op_t; | |||||
typedef struct zfs_ioc_cmd_entry { | |||||
STAILQ_ENTRY(zfs_ioc_cmd_entry) link; | |||||
zfs_ioc_queue_op_t op; | |||||
zfs_cmd_t *cmd; | |||||
} zfs_ioc_cmd_entry_t; | |||||
static kmutex_t zfs_cmdq_lock; | |||||
static kcondvar_t zfs_cmdq_cv; | |||||
static STAILQ_HEAD(, zfs_ioc_cmd_entry) zfs_ioc_cmd_queue = | |||||
STAILQ_HEAD_INITIALIZER(zfs_ioc_cmd_queue); | |||||
static int zfs_ioc_userspace_upgrade(zfs_cmd_t *zc); | static int zfs_ioc_userspace_upgrade(zfs_cmd_t *zc); | ||||
static int zfs_check_settable(const char *name, nvpair_t *property, | static int zfs_check_settable(const char *name, nvpair_t *property, | ||||
cred_t *cr); | cred_t *cr); | ||||
Context not available. | |||||
} | } | ||||
error = dsl_dataset_snapshot(snaps, props, outnvl); | error = dsl_dataset_snapshot(snaps, props, outnvl); | ||||
#if defined(__FreeBSD__) && defined(_KERNEL) | |||||
if (error == 0) { | |||||
for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL; | |||||
pair = nvlist_next_nvpair(snaps, pair)) { | |||||
const char *snapname = nvpair_name(pair); | |||||
(void) zvol_create_minor(snapname); | |||||
} | |||||
} | |||||
#endif | |||||
return (error); | return (error); | ||||
} | } | ||||
Context not available. | |||||
return (0); | return (0); | ||||
} | } | ||||
static void | |||||
zfs_common_zvol_rename(zfs_cmd_t *zc, nvlist_t *renamed, | |||||
const char *oldsnapname, const char *newsnapname) | |||||
{ | |||||
nvpair_t *pair; | |||||
zfs_ioc_cmd_entry_t *entry; | |||||
mutex_enter(&zfs_cmdq_lock); | |||||
do { | |||||
entry = STAILQ_FIRST(&zfs_ioc_cmd_queue); | |||||
if (entry->cmd == zc) { | |||||
mutex_exit(&zfs_cmdq_lock); | |||||
switch (entry->op) { | |||||
case RENAME_OP: | |||||
if (renamed == NULL) { | |||||
zfsvfs_update_fromname(zc->zc_name, zc->zc_value); | |||||
zvol_rename_minors(zc->zc_name, zc->zc_value); | |||||
} else { | |||||
for (pair = nvlist_next_nvpair(renamed, NULL); | |||||
pair != NULL; | |||||
pair = nvlist_next_nvpair(renamed, pair)) { | |||||
char oldname[ZFS_MAX_DATASET_NAME_LEN]; | |||||
char newname[ZFS_MAX_DATASET_NAME_LEN]; | |||||
const char *fsname; | |||||
fsname = nvpair_name(pair); | |||||
snprintf(oldname, sizeof (oldname), "%s@%s", fsname, | |||||
oldsnapname); | |||||
snprintf(newname, sizeof (newname), "%s@%s", fsname, | |||||
newsnapname); | |||||
zfsvfs_update_fromname(oldname, newname); | |||||
zvol_rename_minors(oldname, newname); | |||||
} | |||||
} | |||||
break; | |||||
case PROMOTE_OP: | |||||
for (pair = nvlist_next_nvpair(renamed, NULL); | |||||
pair != NULL; | |||||
pair = nvlist_next_nvpair(renamed, pair)) { | |||||
char oldname[ZFS_MAX_DATASET_NAME_LEN]; | |||||
char newname[ZFS_MAX_DATASET_NAME_LEN]; | |||||
const char *snapname; | |||||
snapname = nvpair_name(pair); | |||||
snprintf(oldname, sizeof (oldname), "%s@%s", zc->zc_value, | |||||
snapname); | |||||
snprintf(newname, sizeof (newname), "%s@%s", zc->zc_name, | |||||
snapname); | |||||
zfsvfs_update_fromname(oldname, newname); | |||||
zvol_rename_minors(oldname, newname); | |||||
} | |||||
break; | |||||
} | |||||
return; | |||||
} | |||||
cv_wait(&zfs_cmdq_cv, &zfs_cmdq_lock); | |||||
} while (1); | |||||
mutex_exit(&zfs_cmdq_lock); | |||||
} | |||||
/* | /* | ||||
* inputs: | * inputs: | ||||
* zc_name old name of dataset | * zc_name old name of dataset | ||||
Context not available. | |||||
boolean_t recursive = zc->zc_cookie & 1; | boolean_t recursive = zc->zc_cookie & 1; | ||||
char *at; | char *at; | ||||
boolean_t allow_mounted = B_TRUE; | boolean_t allow_mounted = B_TRUE; | ||||
int error; | |||||
zfs_ioc_cmd_entry_t cmd_entry = {NULL, RENAME_OP, zc}; | |||||
#ifdef __FreeBSD__ | #ifdef __FreeBSD__ | ||||
allow_mounted = (zc->zc_cookie & 2) != 0; | allow_mounted = (zc->zc_cookie & 2) != 0; | ||||
Context not available. | |||||
strchr(zc->zc_name, '%') || strchr(zc->zc_value, '%')) | strchr(zc->zc_name, '%') || strchr(zc->zc_value, '%')) | ||||
return (SET_ERROR(EINVAL)); | return (SET_ERROR(EINVAL)); | ||||
mutex_enter(&zfs_cmdq_lock); | |||||
STAILQ_INSERT_TAIL(&zfs_ioc_cmd_queue, &cmd_entry, link); | |||||
mutex_exit(&zfs_cmdq_lock); | |||||
at = strchr(zc->zc_name, '@'); | at = strchr(zc->zc_name, '@'); | ||||
if (at != NULL) { | if (at != NULL) { | ||||
/* snaps must be in same fs */ | nvlist_t *renamed; | ||||
int error; | const char *oldsnapname; | ||||
const char *newsnapname; | |||||
/* snaps must be in same fs */ | |||||
if (strncmp(zc->zc_name, zc->zc_value, at - zc->zc_name + 1)) | if (strncmp(zc->zc_name, zc->zc_value, at - zc->zc_name + 1)) | ||||
return (SET_ERROR(EXDEV)); | return (SET_ERROR(EXDEV)); | ||||
*at = '\0'; | *at = '\0'; | ||||
Context not available. | |||||
return (error); | return (error); | ||||
} | } | ||||
} | } | ||||
renamed = fnvlist_alloc(); | |||||
oldsnapname = at + 1; | |||||
newsnapname = strchr(zc->zc_value, '@') + 1; | |||||
error = dsl_dataset_rename_snapshot(zc->zc_name, | error = dsl_dataset_rename_snapshot(zc->zc_name, | ||||
at + 1, strchr(zc->zc_value, '@') + 1, recursive); | oldsnapname, newsnapname, recursive, renamed); | ||||
#if defined(__FreeBSD__) && defined(_KERNEL) | |||||
if (error == 0) { | |||||
zfs_common_zvol_rename(zc, renamed, oldsnapname, newsnapname); | |||||
} | |||||
#endif | |||||
*at = '@'; | *at = '@'; | ||||
fnvlist_free(renamed); | |||||
return (error); | |||||
} else { | } else { | ||||
#ifdef illumos | #ifdef illumos | ||||
if (zc->zc_objset_type == DMU_OST_ZVOL) | if (zc->zc_objset_type == 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)); | error = dsl_dir_rename(zc->zc_name, zc->zc_value); | ||||
#if defined(__FreeBSD__) && defined(_KERNEL) | |||||
if (error == 0) { | |||||
zfs_common_zvol_rename(zc, NULL, NULL, NULL); | |||||
} | |||||
#endif | |||||
} | } | ||||
mutex_enter(&zfs_cmdq_lock); | |||||
STAILQ_REMOVE_HEAD(&zfs_ioc_cmd_queue, link); | |||||
cv_broadcast(&zfs_cmdq_cv); | |||||
mutex_exit(&zfs_cmdq_lock); | |||||
return (error); | |||||
} | } | ||||
static int | static int | ||||
Context not available. | |||||
dsl_pool_t *dp; | dsl_pool_t *dp; | ||||
dsl_dataset_t *ds, *ods; | dsl_dataset_t *ds, *ods; | ||||
char origin[ZFS_MAX_DATASET_NAME_LEN]; | char origin[ZFS_MAX_DATASET_NAME_LEN]; | ||||
nvlist_t *moved; | |||||
char *cp; | char *cp; | ||||
int error; | int error; | ||||
zfs_ioc_cmd_entry_t cmd_entry = {NULL, PROMOTE_OP, zc}; | |||||
zc->zc_name[sizeof (zc->zc_name) - 1] = '\0'; | zc->zc_name[sizeof (zc->zc_name) - 1] = '\0'; | ||||
if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0 || | if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0 || | ||||
Context not available. | |||||
*cp = '\0'; | *cp = '\0'; | ||||
(void) dmu_objset_find(origin, | (void) dmu_objset_find(origin, | ||||
zfs_unmount_snap_cb, NULL, DS_FIND_SNAPSHOTS); | zfs_unmount_snap_cb, NULL, DS_FIND_SNAPSHOTS); | ||||
return (dsl_dataset_promote(zc->zc_name, zc->zc_string)); | |||||
mutex_enter(&zfs_cmdq_lock); | |||||
STAILQ_INSERT_TAIL(&zfs_ioc_cmd_queue, &cmd_entry, link); | |||||
mutex_exit(&zfs_cmdq_lock); | |||||
moved = fnvlist_alloc(); | |||||
error = dsl_dataset_promote(zc->zc_name, zc->zc_string, moved); | |||||
if (error == 0) { | |||||
zfs_common_zvol_rename(zc, moved, NULL, NULL); | |||||
} | |||||
fnvlist_free(moved); | |||||
mutex_enter(&zfs_cmdq_lock); | |||||
STAILQ_REMOVE_HEAD(&zfs_ioc_cmd_queue, link); | |||||
cv_broadcast(&zfs_cmdq_cv); | |||||
mutex_exit(&zfs_cmdq_lock); | |||||
return (error); | |||||
} | } | ||||
/* | /* | ||||
Context not available. | |||||
mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL); | mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL); | ||||
mutex_init(&zfs_cmdq_lock, "zfs_cmdq_lock", NULL, 0); | |||||
cv_init(&zfs_cmdq_cv, NULL, CV_DEFAULT, NULL); | |||||
spa_init(FREAD | FWRITE); | spa_init(FREAD | FWRITE); | ||||
zfs_init(); | zfs_init(); | ||||
zvol_init(); | zvol_init(); | ||||
Context not available. | |||||
tsd_destroy(&rrw_tsd_key); | tsd_destroy(&rrw_tsd_key); | ||||
tsd_destroy(&zfs_allow_log_key); | tsd_destroy(&zfs_allow_log_key); | ||||
cv_destroy(&zfs_cmdq_cv); | |||||
mutex_destroy(&zfs_cmdq_lock); | |||||
mutex_destroy(&zfs_share_lock); | mutex_destroy(&zfs_share_lock); | ||||
return (0); | return (0); | ||||
Context not available. |