From owner-svn-src-stable@FreeBSD.ORG Fri Oct 10 01:01:06 2014 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 46234DD3; Fri, 10 Oct 2014 01:01:06 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 311AB842; Fri, 10 Oct 2014 01:01:06 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s9A116tB024346; Fri, 10 Oct 2014 01:01:06 GMT (envelope-from smh@FreeBSD.org) Received: (from smh@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s9A115i3024343; Fri, 10 Oct 2014 01:01:05 GMT (envelope-from smh@FreeBSD.org) Message-Id: <201410100101.s9A115i3024343@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: smh set sender to smh@FreeBSD.org using -f From: Steven Hartland Date: Fri, 10 Oct 2014 01:01:05 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r272883 - stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 10 Oct 2014 01:01:06 -0000 Author: smh Date: Fri Oct 10 01:01:04 2014 New Revision: 272883 URL: https://svnweb.freebsd.org/changeset/base/272883 Log: MFC r272474: Fix various issues with zvols Sponsored by: Multiplay Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c ============================================================================== --- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c Fri Oct 10 00:51:23 2014 (r272882) +++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c Fri Oct 10 01:01:04 2014 (r272883) @@ -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: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c ============================================================================== --- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c Fri Oct 10 00:51:23 2014 (r272882) +++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c Fri Oct 10 01:01:04 2014 (r272883) @@ -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: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c ============================================================================== --- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c Fri Oct 10 00:51:23 2014 (r272882) +++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c Fri Oct 10 01:01:04 2014 (r272883) @@ -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(); }