Date: Thu, 16 Oct 2014 08:39:44 +0000 (UTC) From: Steven Hartland <smh@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-releng@freebsd.org Subject: svn commit: r273162 - releng/10.1/sys/cddl/contrib/opensolaris/uts/common/fs/zfs Message-ID: <201410160839.s9G8diBZ089660@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: smh Date: Thu Oct 16 08:39:44 2014 New Revision: 273162 URL: https://svnweb.freebsd.org/changeset/base/273162 Log: MFS10 r272883 MFC r272474 Fix ZFS ZVOL deadlock and rename issues Approved by: re@ (delphij) Sponsored by: Multiplay Modified: releng/10.1/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c releng/10.1/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c releng/10.1/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c Directory Properties: releng/10.1/ (props changed) Modified: releng/10.1/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c ============================================================================== --- releng/10.1/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c Thu Oct 16 08:33:11 2014 (r273161) +++ releng/10.1/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c Thu Oct 16 08:39:44 2014 (r273162) @@ -2257,6 +2257,9 @@ dsl_dataset_promote_sync(void *arg, dmu_ 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; @@ -2322,6 +2325,14 @@ dsl_dataset_promote_sync(void *arg, dmu_ dd->dd_phys->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)) { @@ -2356,6 +2367,12 @@ dsl_dataset_promote_sync(void *arg, dmu_ 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 (ds->ds_phys->ds_next_clones_obj && spa_version(dp->dp_spa) >= SPA_VERSION_DIR_CLONES) { @@ -2393,6 +2410,12 @@ dsl_dataset_promote_sync(void *arg, dmu_ 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 Modified: releng/10.1/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c ============================================================================== --- releng/10.1/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c Thu Oct 16 08:33:11 2014 (r273161) +++ releng/10.1/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c Thu Oct 16 08:39:44 2014 (r273162) @@ -3541,6 +3541,7 @@ zfs_destroy_unmount_origin(const char *f static int zfs_ioc_destroy_snaps(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl) { + int error, poollen; nvlist_t *snaps; nvpair_t *pair; boolean_t defer; @@ -3549,9 +3550,25 @@ zfs_ioc_destroy_snaps(const char *poolna return (SET_ERROR(EINVAL)); defer = nvlist_exists(innvl, "defer"); + poollen = strlen(poolname); for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL; pair = nvlist_next_nvpair(snaps, pair)) { - (void) zfs_unmount_snap(nvpair_name(pair)); + const char *name = nvpair_name(pair); + + /* + * The snap must be in the specified pool to prevent the + * invalid removal of zvol minors below. + */ + if (strncmp(name, poolname, poollen) != 0 || + (name[poollen] != '/' && name[poollen] != '@')) + return (SET_ERROR(EXDEV)); + + error = zfs_unmount_snap(name); + if (error != 0) + return (error); +#if defined(__FreeBSD__) + zvol_remove_minors(name); +#endif } return (dsl_destroy_snapshots_nvl(snaps, defer, outnvl)); @@ -3676,7 +3693,11 @@ zfs_ioc_destroy(zfs_cmd_t *zc) else err = dsl_destroy_head(zc->zc_name); if (zc->zc_objset_type == DMU_OST_ZVOL && err == 0) +#ifdef __FreeBSD__ + zvol_remove_minors(zc->zc_name); +#else (void) zvol_remove_minor(zc->zc_name); +#endif return (err); } Modified: releng/10.1/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c ============================================================================== --- releng/10.1/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c Thu Oct 16 08:33:11 2014 (r273161) +++ releng/10.1/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c Thu Oct 16 08:39:44 2014 (r273162) @@ -883,7 +883,8 @@ zvol_remove_minors(const char *name) LIST_FOREACH_SAFE(zv, &all_zvols, zv_links, tzv) { if (strcmp(zv->zv_name, name) == 0 || (strncmp(zv->zv_name, name, namelen) == 0 && - zv->zv_name[namelen] == '/')) { + strlen(zv->zv_name) > namelen && (zv->zv_name[namelen] == '/' || + zv->zv_name[namelen] == '@'))) { (void) zvol_remove_zv(zv); } } @@ -2571,9 +2572,10 @@ zvol_create_minors(const char *name) if (dmu_objset_type(os) == DMU_OST_ZVOL) { dsl_dataset_long_hold(os->os_dsl_dataset, FTAG); dsl_pool_rele(dmu_objset_pool(os), FTAG); - if ((error = zvol_create_minor(name)) == 0) + error = zvol_create_minor(name); + if (error == 0 || error == EEXIST) { error = zvol_create_snapshots(os, name); - else { + } else { printf("ZFS WARNING: Unable to create ZVOL %s (error=%d).\n", name, error); } @@ -2674,12 +2676,17 @@ zvol_rename_minors(const char *oldname, size_t oldnamelen, newnamelen; zvol_state_t *zv; char *namebuf; + boolean_t locked = B_FALSE; oldnamelen = strlen(oldname); newnamelen = strlen(newname); DROP_GIANT(); - mutex_enter(&spa_namespace_lock); + /* See comment in zvol_open(). */ + if (!MUTEX_HELD(&spa_namespace_lock)) { + mutex_enter(&spa_namespace_lock); + locked = B_TRUE; + } LIST_FOREACH(zv, &all_zvols, zv_links) { if (strcmp(zv->zv_name, oldname) == 0) { @@ -2694,7 +2701,8 @@ zvol_rename_minors(const char *oldname, } } - mutex_exit(&spa_namespace_lock); + if (locked) + mutex_exit(&spa_namespace_lock); PICKUP_GIANT(); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201410160839.s9G8diBZ089660>