Index: cddl/contrib/opensolaris/cmd/ztest/ztest.c =================================================================== --- cddl/contrib/opensolaris/cmd/ztest/ztest.c +++ cddl/contrib/opensolaris/cmd/ztest/ztest.c @@ -3481,7 +3481,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 @@ -1560,17 +1560,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); } @@ -2012,6 +2001,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; @@ -2072,11 +2062,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_MAXNAMELEN]; dsl_dataset_rename_snapshot_arg_t *ddrsa = arg; dsl_dataset_t *ds; uint64_t val; @@ -2104,23 +2090,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); } @@ -2145,7 +2119,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; @@ -2153,6 +2128,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, @@ -2342,6 +2318,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 */ @@ -2536,9 +2513,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; @@ -2606,14 +2580,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)) { @@ -2639,6 +2605,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); @@ -2648,12 +2617,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) { @@ -2692,12 +2655,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 @@ -2866,7 +2823,7 @@ * in with the name. (It must be at least MAXNAMELEN 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; @@ -2888,6 +2845,7 @@ return (error); ddpa.ddpa_clonename = name; + ddpa.ddpa_moved = moved; ddpa.err_ds = conflsnap; 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 @@ -1904,13 +1904,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 @@ -286,8 +286,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); typedef struct dmu_buf { uint64_t db_object; /* object that this buffer is part of */ 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 @@ -262,11 +262,12 @@ uint64_t dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin, uint64_t flags, dmu_tx_t *tx); int dsl_dataset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors); -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 @@ -3419,6 +3419,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); } @@ -3776,6 +3785,7 @@ boolean_t recursive = zc->zc_cookie & 1; char *at; boolean_t allow_mounted = B_TRUE; + int error; #ifdef __FreeBSD__ allow_mounted = (zc->zc_cookie & 2) != 0; @@ -3788,9 +3798,12 @@ at = strchr(zc->zc_name, '@'); if (at != NULL) { - /* snaps must be in same fs */ - int error; + nvlist_t *renamed; + nvpair_t *pair; + 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'; @@ -3803,17 +3816,46 @@ 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) { + for (pair = nvlist_next_nvpair(renamed, NULL); + pair != NULL; + pair = nvlist_next_nvpair(renamed, pair)) { + char oldname[ZFS_MAXNAMELEN]; + char newname[ZFS_MAXNAMELEN]; + const char *fsname; + + fsname = nvpair_name(pair); + snprintf(oldname, MAXPATHLEN, "%s@%s", fsname, + oldsnapname); + snprintf(newname, MAXPATHLEN, "%s@%s", fsname, + newsnapname); + zfsvfs_update_fromname(oldname, newname); + zvol_rename_minors(oldname, newname); + } + } +#endif *at = '@'; - + fnvlist_free(renamed); return (error); } 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) { + zfsvfs_update_fromname(zc->zc_name, zc->zc_value); + zvol_rename_minors(zc->zc_name, zc->zc_value); + } +#endif + return (error); } } @@ -4837,7 +4879,9 @@ static int zfs_ioc_promote(zfs_cmd_t *zc) { + nvlist_t *moved; char *cp; + int error; /* * We don't need to unmount *all* the origin fs's snapshots, but @@ -4848,7 +4892,29 @@ *cp = '\0'; (void) dmu_objset_find(zc->zc_value, zfs_unmount_snap_cb, NULL, DS_FIND_SNAPSHOTS); - return (dsl_dataset_promote(zc->zc_name, zc->zc_string)); + moved = fnvlist_alloc(); + error = dsl_dataset_promote(zc->zc_name, zc->zc_string, moved); + if (error == 0) { + nvpair_t *pair; + + for (pair = nvlist_next_nvpair(moved, NULL); + pair != NULL; + pair = nvlist_next_nvpair(moved, pair)) { + char oldname[ZFS_MAXNAMELEN]; + char newname[ZFS_MAXNAMELEN]; + const char *snapname; + + snapname = nvpair_name(pair); + snprintf(oldname, MAXPATHLEN, "%s@%s", zc->zc_value, + snapname); + snprintf(newname, MAXPATHLEN, "%s@%s", zc->zc_name, + snapname); + zfsvfs_update_fromname(oldname, newname); + zvol_rename_minors(oldname, newname); + } + } + fnvlist_free(moved); + return (error); } /*