Page MenuHomeFreeBSD

D14669.id40213.diff
No OneTemporary

D14669.id40213.diff

Index: cddl/contrib/opensolaris/cmd/ztest/ztest.c
===================================================================
--- cddl/contrib/opensolaris/cmd/ztest/ztest.c
+++ cddl/contrib/opensolaris/cmd/ztest/ztest.c
@@ -3566,7 +3566,7 @@
error = dmu_objset_own(snap2name, DMU_OST_ANY, B_TRUE, FTAG, &os);
if (error)
fatal(0, "dmu_objset_own(%s) = %d", snap2name, error);
- error = dsl_dataset_promote(clone2name, NULL);
+ error = dsl_dataset_promote(clone2name, NULL, NULL);
if (error == ENOSPC) {
dmu_objset_disown(os, FTAG);
ztest_record_enospc(FTAG);
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
@@ -1639,17 +1639,6 @@
fnvlist_free(suspended);
}
-#ifdef __FreeBSD__
-#ifdef _KERNEL
- if (error == 0) {
- for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
- pair = nvlist_next_nvpair(snaps, pair)) {
- char *snapname = nvpair_name(pair);
- zvol_create_minors(snapname);
- }
- }
-#endif
-#endif
return (error);
}
@@ -2425,6 +2414,7 @@
const char *ddrsa_oldsnapname;
const char *ddrsa_newsnapname;
boolean_t ddrsa_recursive;
+ nvlist_t *ddrsa_renamed;
dmu_tx_t *ddrsa_tx;
} dsl_dataset_rename_snapshot_arg_t;
@@ -2485,11 +2475,7 @@
dsl_dataset_rename_snapshot_sync_impl(dsl_pool_t *dp,
dsl_dataset_t *hds, void *arg)
{
-#ifdef __FreeBSD__
-#ifdef _KERNEL
- char *oldname, *newname;
-#endif
-#endif
+ char namebuf[ZFS_MAX_DATASET_NAME_LEN];
dsl_dataset_rename_snapshot_arg_t *ddrsa = arg;
dsl_dataset_t *ds;
uint64_t val;
@@ -2517,23 +2503,11 @@
VERIFY0(zap_add(dp->dp_meta_objset,
dsl_dataset_phys(hds)->ds_snapnames_zapobj,
ds->ds_snapname, 8, 1, &ds->ds_object, tx));
-
-#ifdef __FreeBSD__
-#ifdef _KERNEL
- oldname = kmem_alloc(MAXPATHLEN, KM_SLEEP);
- newname = kmem_alloc(MAXPATHLEN, KM_SLEEP);
- snprintf(oldname, MAXPATHLEN, "%s@%s", ddrsa->ddrsa_fsname,
- ddrsa->ddrsa_oldsnapname);
- snprintf(newname, MAXPATHLEN, "%s@%s", ddrsa->ddrsa_fsname,
- ddrsa->ddrsa_newsnapname);
- zfsvfs_update_fromname(oldname, newname);
- zvol_rename_minors(oldname, newname);
- kmem_free(newname, MAXPATHLEN);
- kmem_free(oldname, MAXPATHLEN);
-#endif
-#endif
dsl_dataset_rele(ds, FTAG);
-
+ if (ddrsa->ddrsa_renamed != NULL) {
+ dsl_dataset_name(hds, namebuf);
+ fnvlist_add_boolean(ddrsa->ddrsa_renamed, namebuf);
+ }
return (0);
}
@@ -2558,7 +2532,8 @@
int
dsl_dataset_rename_snapshot(const char *fsname,
- const char *oldsnapname, const char *newsnapname, boolean_t recursive)
+ const char *oldsnapname, const char *newsnapname, boolean_t recursive,
+ nvlist_t *renamed)
{
dsl_dataset_rename_snapshot_arg_t ddrsa;
@@ -2566,6 +2541,7 @@
ddrsa.ddrsa_oldsnapname = oldsnapname;
ddrsa.ddrsa_newsnapname = newsnapname;
ddrsa.ddrsa_recursive = recursive;
+ ddrsa.ddrsa_renamed = renamed;
return (dsl_sync_task(fsname, dsl_dataset_rename_snapshot_check,
dsl_dataset_rename_snapshot_sync, &ddrsa,
@@ -3008,9 +2984,6 @@
dsl_dir_t *odd = NULL;
uint64_t oldnext_obj;
int64_t delta;
-#if defined(__FreeBSD__) && defined(_KERNEL)
- char *oldname, *newname;
-#endif
VERIFY0(promote_hold(ddpa, dp, FTAG));
hds = ddpa->ddpa_clone;
@@ -3078,14 +3051,6 @@
dsl_dir_phys(dd)->dd_clones, origin_head->ds_object, tx));
}
-#if defined(__FreeBSD__) && defined(_KERNEL)
- /* Take the spa_namespace_lock early so zvol renames don't deadlock. */
- mutex_enter(&spa_namespace_lock);
-
- oldname = kmem_alloc(MAXPATHLEN, KM_SLEEP);
- newname = kmem_alloc(MAXPATHLEN, KM_SLEEP);
-#endif
-
/* move snapshots to this dir */
for (snap = list_head(&ddpa->shared_snaps); snap;
snap = list_next(&ddpa->shared_snaps, snap)) {
@@ -3111,6 +3076,9 @@
dsl_fs_ss_count_adjust(hds->ds_dir, 1,
DD_FIELD_SNAPSHOT_COUNT, tx);
+ if (ddpa->ddpa_moved != NULL)
+ fnvlist_add_boolean(ddpa->ddpa_moved, ds->ds_snapname);
+
/* change containing dsl_dir */
dmu_buf_will_dirty(ds->ds_dbuf, tx);
ASSERT3U(dsl_dataset_phys(ds)->ds_dir_obj, ==, odd->dd_object);
@@ -3120,12 +3088,6 @@
VERIFY0(dsl_dir_hold_obj(dp, dd->dd_object,
NULL, ds, &ds->ds_dir));
-#if defined(__FreeBSD__) && defined(_KERNEL)
- dsl_dataset_name(ds, newname);
- zfsvfs_update_fromname(oldname, newname);
- zvol_rename_minors(oldname, newname);
-#endif
-
/* move any clone references */
if (dsl_dataset_phys(ds)->ds_next_clones_obj &&
spa_version(dp->dp_spa) >= SPA_VERSION_DIR_CLONES) {
@@ -3164,12 +3126,6 @@
ASSERT(!dsl_prop_hascb(ds));
}
-#if defined(__FreeBSD__) && defined(_KERNEL)
- mutex_exit(&spa_namespace_lock);
-
- kmem_free(newname, MAXPATHLEN);
- kmem_free(oldname, MAXPATHLEN);
-#endif
/*
* Change space accounting.
* Note, pa->*usedsnap and dd_used_breakdown[SNAP] will either
@@ -3338,7 +3294,7 @@
* in with the name. (It must be at least ZFS_MAX_DATASET_NAME_LEN bytes long.)
*/
int
-dsl_dataset_promote(const char *name, char *conflsnap)
+dsl_dataset_promote(const char *name, char *conflsnap, nvlist_t *moved)
{
dsl_dataset_promote_arg_t ddpa = { 0 };
uint64_t numsnaps;
@@ -3361,6 +3317,7 @@
return (error);
ddpa.ddpa_clonename = name;
+ ddpa.ddpa_moved = moved;
ddpa.err_ds = fnvlist_alloc();
ddpa.cr = CRED();
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c
@@ -2032,13 +2032,6 @@
VERIFY0(zap_add(mos, dsl_dir_phys(newparent)->dd_child_dir_zapobj,
dd->dd_myname, 8, 1, &dd->dd_object, tx));
-#ifdef __FreeBSD__
-#ifdef _KERNEL
- zfsvfs_update_fromname(ddra->ddra_oldname, ddra->ddra_newname);
- zvol_rename_minors(ddra->ddra_oldname, ddra->ddra_newname);
-#endif
-#endif
-
dsl_prop_notify_all(dd);
dsl_dir_rele(newparent, FTAG);
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h
@@ -291,8 +291,6 @@
int dmu_objset_find(char *name, int func(const char *, void *), void *arg,
int flags);
void dmu_objset_byteswap(void *buf, size_t size);
-int dsl_dataset_rename_snapshot(const char *fsname,
- const char *oldsnapname, const char *newsnapname, boolean_t recursive);
int dmu_objset_remap_indirects(const char *fsname);
typedef struct dmu_buf {
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h
@@ -252,6 +252,7 @@
typedef struct dsl_dataset_promote_arg {
const char *ddpa_clonename;
+ nvlist_t *ddpa_moved;
dsl_dataset_t *ddpa_clone;
list_t shared_snaps, origin_snaps, clone_snaps;
dsl_dataset_t *origin_origin; /* origin of the origin */
@@ -311,11 +312,12 @@
int dsl_dataset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors);
void dsl_dataset_promote_sync(void *arg, dmu_tx_t *tx);
int dsl_dataset_promote_check(void *arg, dmu_tx_t *tx);
-int dsl_dataset_promote(const char *name, char *conflsnap);
+int dsl_dataset_promote(const char *name, char *conflsnap, nvlist_t *moved);
int dsl_dataset_clone_swap(dsl_dataset_t *clone, dsl_dataset_t *origin_head,
boolean_t force);
int dsl_dataset_rename_snapshot(const char *fsname,
- const char *oldsnapname, const char *newsnapname, boolean_t recursive);
+ const char *oldsnapname, const char *newsnapname, boolean_t recursive,
+ nvlist_t *renamed);
int dsl_dataset_snapshot_tmp(const char *fsname, const char *snapname,
minor_t cleanup_minor, const char *htag);
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
@@ -250,6 +250,23 @@
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_check_settable(const char *name, nvpair_t *property,
cred_t *cr);
@@ -3462,6 +3479,15 @@
}
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);
}
@@ -3900,6 +3926,67 @@
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:
* zc_name old name of dataset
@@ -3914,6 +4001,8 @@
boolean_t recursive = zc->zc_cookie & 1;
char *at;
boolean_t allow_mounted = B_TRUE;
+ int error;
+ zfs_ioc_cmd_entry_t cmd_entry = {NULL, RENAME_OP, zc};
#ifdef __FreeBSD__
allow_mounted = (zc->zc_cookie & 2) != 0;
@@ -3927,11 +4016,16 @@
strchr(zc->zc_name, '%') || strchr(zc->zc_value, '%'))
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, '@');
if (at != NULL) {
- /* snaps must be in same fs */
- int error;
+ nvlist_t *renamed;
+ 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))
return (SET_ERROR(EXDEV));
*at = '\0';
@@ -3944,18 +4038,37 @@
return (error);
}
}
+ renamed = fnvlist_alloc();
+ oldsnapname = at + 1;
+ newsnapname = strchr(zc->zc_value, '@') + 1;
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 = '@';
-
- return (error);
+ fnvlist_free(renamed);
} else {
#ifdef illumos
if (zc->zc_objset_type == DMU_OST_ZVOL)
(void) zvol_remove_minor(zc->zc_name);
#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
@@ -4973,8 +5086,10 @@
dsl_pool_t *dp;
dsl_dataset_t *ds, *ods;
char origin[ZFS_MAX_DATASET_NAME_LEN];
+ nvlist_t *moved;
char *cp;
int error;
+ zfs_ioc_cmd_entry_t cmd_entry = {NULL, PROMOTE_OP, zc};
zc->zc_name[sizeof (zc->zc_name) - 1] = '\0';
if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0 ||
@@ -5019,7 +5134,24 @@
*cp = '\0';
(void) dmu_objset_find(origin,
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);
}
/*
@@ -6933,6 +7065,9 @@
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);
zfs_init();
zvol_init();
@@ -6968,6 +7103,9 @@
tsd_destroy(&rrw_tsd_key);
tsd_destroy(&zfs_allow_log_key);
+ cv_destroy(&zfs_cmdq_cv);
+ mutex_destroy(&zfs_cmdq_lock);
+
mutex_destroy(&zfs_share_lock);
return (0);

File Metadata

Mime Type
text/plain
Expires
Thu, Jun 25, 5:40 AM (16 h, 20 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34306680
Default Alt Text
D14669.id40213.diff (14 KB)

Event Timeline