From owner-svn-src-stable-10@FreeBSD.ORG Wed Jan 21 09:45:49 2015 Return-Path: Delivered-To: svn-src-stable-10@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id BC0C58CE; Wed, 21 Jan 2015 09:45:49 +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 A4ACD36A; Wed, 21 Jan 2015 09:45:49 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t0L9jnGQ097871; Wed, 21 Jan 2015 09:45:49 GMT (envelope-from smh@FreeBSD.org) Received: (from smh@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t0L9jnT3097866; Wed, 21 Jan 2015 09:45:49 GMT (envelope-from smh@FreeBSD.org) Message-Id: <201501210945.t0L9jnT3097866@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: smh set sender to smh@FreeBSD.org using -f From: Steven Hartland Date: Wed, 21 Jan 2015 09:45:49 +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: r277483 - in stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs: . sys 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-10@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 21 Jan 2015 09:45:49 -0000 Author: smh Date: Wed Jan 21 09:45:48 2015 New Revision: 277483 URL: https://svnweb.freebsd.org/changeset/base/277483 Log: MFC r276063: Standardise on illumos for #ifdef's in zvol.c MFC r276066: Refactor zvol locking to minimise diff with upstream MFC r276069: Fix panic when resizing ZFS zvol's Sponsored by: Multiplay Modified: stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zvol.h 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/sys/zvol.h ============================================================================== --- stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zvol.h Wed Jan 21 09:39:20 2015 (r277482) +++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zvol.h Wed Jan 21 09:45:48 2015 (r277483) @@ -43,7 +43,7 @@ extern void zvol_create_cb(objset_t *os, extern int zvol_create_minor(const char *); extern int zvol_remove_minor(const char *); extern void zvol_remove_minors(const char *); -extern int zvol_set_volsize(const char *, major_t, uint64_t); +extern int zvol_set_volsize(const char *, uint64_t); #ifdef sun extern int zvol_open(dev_t *devp, int flag, int otyp, cred_t *cr); 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 Wed Jan 21 09:39:20 2015 (r277482) +++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c Wed Jan 21 09:45:48 2015 (r277483) @@ -2483,8 +2483,7 @@ zfs_prop_set_special(const char *dsname, err = dsl_dataset_set_refreservation(dsname, source, intval); break; case ZFS_PROP_VOLSIZE: - err = zvol_set_volsize(dsname, ddi_driver_major(zfs_dip), - intval); + err = zvol_set_volsize(dsname, intval); break; case ZFS_PROP_VERSION: { 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 Wed Jan 21 09:39:20 2015 (r277482) +++ stable/10/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c Wed Jan 21 09:45:48 2015 (r277483) @@ -97,6 +97,7 @@ #include "zfs_namecheck.h" +#ifndef illumos struct g_class zfs_zvol_class = { .name = "ZFS::ZVOL", .version = G_VERSION, @@ -104,19 +105,30 @@ struct g_class zfs_zvol_class = { DECLARE_GEOM_CLASS(zfs_zvol_class, zfs_zvol); +#endif void *zfsdev_state; static char *zvol_tag = "zvol_tag"; #define ZVOL_DUMPSIZE "dumpsize" /* - * The spa_namespace_lock protects the zfsdev_state structure from being - * modified while it's being used, e.g. an open that comes in before a - * create finishes. It also protects temporary opens of the dataset so that, + * This lock protects the zfsdev_state structure from being modified + * while it's being used, e.g. an open that comes in before a create + * finishes. It also protects temporary opens of the dataset so that, * e.g., an open doesn't get a spurious EBUSY. */ +#ifdef illumos +kmutex_t zfsdev_state_lock; +#else +/* + * In FreeBSD we've replaced the upstream zfsdev_state_lock with the + * spa_namespace_lock in the ZVOL code. + */ +#define zfsdev_state_lock spa_namespace_lock +#endif static uint32_t zvol_minors; +#ifndef illumos SYSCTL_DECL(_vfs_zfs); SYSCTL_NODE(_vfs_zfs, OID_AUTO, vol, CTLFLAG_RW, 0, "ZFS VOLUME"); static int volmode = ZFS_VOLMODE_GEOM; @@ -124,6 +136,7 @@ TUNABLE_INT("vfs.zfs.vol.mode", &volmode SYSCTL_INT(_vfs_zfs_vol, OID_AUTO, mode, CTLFLAG_RWTUN, &volmode, 0, "Expose as GEOM providers (1), device files (2) or neither"); +#endif typedef struct zvol_extent { list_node_t ze_node; dva_t ze_dva; /* dva associated with this extent */ @@ -134,28 +147,40 @@ typedef struct zvol_extent { * The in-core state of each volume. */ typedef struct zvol_state { +#ifndef illumos LIST_ENTRY(zvol_state) zv_links; +#endif char zv_name[MAXPATHLEN]; /* pool/dd name */ uint64_t zv_volsize; /* amount of space we advertise */ uint64_t zv_volblocksize; /* volume block size */ +#ifdef illumos + minor_t zv_minor; /* minor number */ +#else struct cdev *zv_dev; /* non-GEOM device */ struct g_provider *zv_provider; /* GEOM provider */ +#endif uint8_t zv_min_bs; /* minimum addressable block shift */ uint8_t zv_flags; /* readonly, dumpified, etc. */ objset_t *zv_objset; /* objset handle */ +#ifdef illumos + uint32_t zv_open_count[OTYPCNT]; /* open counts */ +#endif uint32_t zv_total_opens; /* total open count */ zilog_t *zv_zilog; /* ZIL handle */ list_t zv_extents; /* List of extents for dump */ znode_t zv_znode; /* for range locking */ dmu_buf_t *zv_dbuf; /* bonus handle */ +#ifndef illumos int zv_state; int zv_volmode; /* Provide GEOM or cdev */ struct bio_queue_head zv_queue; struct mtx zv_queue_mtx; /* zv_queue mutex */ +#endif } zvol_state_t; +#ifndef illumos static LIST_HEAD(, zvol_state) all_zvols; - +#endif /* * zvol specific flags */ @@ -173,6 +198,7 @@ int zvol_maxphys = DMU_MAX_ACCESS/2; * Toggle unmap functionality. */ boolean_t zvol_unmap_enabled = B_TRUE; +#ifndef illumos SYSCTL_INT(_vfs_zfs_vol, OID_AUTO, unmap_enabled, CTLFLAG_RWTUN, &zvol_unmap_enabled, 0, "Enable UNMAP functionality"); @@ -196,28 +222,30 @@ static struct cdevsw zvol_cdevsw = { .d_flags = D_DISK | D_TRACKCLOSE, }; -extern int zfs_set_prop_nvlist(const char *, zprop_source_t, - nvlist_t *, nvlist_t *); +static void zvol_geom_run(zvol_state_t *zv); +static void zvol_geom_destroy(zvol_state_t *zv); +static int zvol_geom_access(struct g_provider *pp, int acr, int acw, int ace); +static void zvol_geom_start(struct bio *bp); +static void zvol_geom_worker(void *arg); static void zvol_log_truncate(zvol_state_t *zv, dmu_tx_t *tx, uint64_t off, uint64_t len, boolean_t sync); +#endif /* !illumos */ + +extern int zfs_set_prop_nvlist(const char *, zprop_source_t, + nvlist_t *, nvlist_t *); static int zvol_remove_zv(zvol_state_t *); static int zvol_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio); static int zvol_dumpify(zvol_state_t *zv); static int zvol_dump_fini(zvol_state_t *zv); static int zvol_dump_init(zvol_state_t *zv, boolean_t resize); -static void zvol_geom_run(zvol_state_t *zv); -static void zvol_geom_destroy(zvol_state_t *zv); -static int zvol_geom_access(struct g_provider *pp, int acr, int acw, int ace); -static void zvol_geom_start(struct bio *bp); -static void zvol_geom_worker(void *arg); - static void -zvol_size_changed(zvol_state_t *zv) +zvol_size_changed(zvol_state_t *zv, uint64_t volsize) { -#ifdef sun - dev_t dev = makedevice(maj, min); +#ifdef illumos + dev_t dev = makedevice(ddi_driver_major(zfs_dip), zv->zv_minor); + zv->zv_volsize = volsize; VERIFY(ddi_prop_update_int64(dev, zfs_dip, "Size", volsize) == DDI_SUCCESS); VERIFY(ddi_prop_update_int64(dev, zfs_dip, @@ -226,7 +254,8 @@ zvol_size_changed(zvol_state_t *zv) /* Notify specfs to invalidate the cached size */ spec_size_invalidate(dev, VBLK); spec_size_invalidate(dev, VCHR); -#else /* !sun */ +#else /* !illumos */ + zv->zv_volsize = volsize; if (zv->zv_volmode == ZFS_VOLMODE_GEOM) { struct g_provider *pp; @@ -237,7 +266,7 @@ zvol_size_changed(zvol_state_t *zv) g_resize_provider(pp, zv->zv_volsize); g_topology_unlock(); } -#endif /* !sun */ +#endif /* illumos */ } int @@ -293,16 +322,26 @@ zvol_get_stats(objset_t *os, nvlist_t *n static zvol_state_t * zvol_minor_lookup(const char *name) { +#ifdef illumos + minor_t minor; +#endif zvol_state_t *zv; - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(MUTEX_HELD(&zfsdev_state_lock)); +#ifdef illumos + for (minor = 1; minor <= ZFSDEV_MAX_MINOR; minor++) { + zv = zfsdev_get_soft_state(minor, ZSST_ZVOL); + if (zv == NULL) + continue; +#else LIST_FOREACH(zv, &all_zvols, zv_links) { +#endif if (strcmp(zv->zv_name, name) == 0) - break; + return (zv); } - return (zv); + return (NULL); } /* extent mapping arg */ @@ -518,20 +557,20 @@ zil_replay_func_t *zvol_replay_vector[TX zvol_replay_err, /* TX_WRITE2 */ }; -#ifdef sun +#ifdef illumos int zvol_name2minor(const char *name, minor_t *minor) { zvol_state_t *zv; - mutex_enter(&spa_namespace_lock); + mutex_enter(&zfsdev_state_lock); zv = zvol_minor_lookup(name); if (minor && zv) *minor = zv->zv_minor; - mutex_exit(&spa_namespace_lock); + mutex_exit(&zfsdev_state_lock); return (zv ? 0 : -1); } -#endif /* sun */ +#endif /* illumos */ /* * Create a minor node (plus a whole lot more) for the specified volume. @@ -542,19 +581,26 @@ zvol_create_minor(const char *name) zfs_soft_state_t *zs; zvol_state_t *zv; objset_t *os; + dmu_object_info_t doi; +#ifdef illumos + minor_t minor = 0; + char chrbuf[30], blkbuf[30]; +#else struct cdev *dev; struct g_provider *pp; struct g_geom *gp; - dmu_object_info_t doi; uint64_t volsize, mode; +#endif int error; +#ifndef illumos ZFS_LOG(1, "Creating ZVOL %s...", name); +#endif - mutex_enter(&spa_namespace_lock); + mutex_enter(&zfsdev_state_lock); if (zvol_minor_lookup(name) != NULL) { - mutex_exit(&spa_namespace_lock); + mutex_exit(&zfsdev_state_lock); return (SET_ERROR(EEXIST)); } @@ -562,20 +608,20 @@ zvol_create_minor(const char *name) error = dmu_objset_own(name, DMU_OST_ZVOL, B_TRUE, FTAG, &os); if (error) { - mutex_exit(&spa_namespace_lock); + mutex_exit(&zfsdev_state_lock); return (error); } -#ifdef sun +#ifdef illumos if ((minor = zfsdev_minor_alloc()) == 0) { dmu_objset_disown(os, FTAG); - mutex_exit(&spa_namespace_lock); + mutex_exit(&zfsdev_state_lock); return (SET_ERROR(ENXIO)); } if (ddi_soft_state_zalloc(zfsdev_state, minor) != DDI_SUCCESS) { dmu_objset_disown(os, FTAG); - mutex_exit(&spa_namespace_lock); + mutex_exit(&zfsdev_state_lock); return (SET_ERROR(EAGAIN)); } (void) ddi_prop_update_string(minor, zfs_dip, ZVOL_PROP_NAME, @@ -587,7 +633,7 @@ zvol_create_minor(const char *name) minor, DDI_PSEUDO, 0) == DDI_FAILURE) { ddi_soft_state_free(zfsdev_state, minor); dmu_objset_disown(os, FTAG); - mutex_exit(&spa_namespace_lock); + mutex_exit(&zfsdev_state_lock); return (SET_ERROR(EAGAIN)); } @@ -598,14 +644,14 @@ zvol_create_minor(const char *name) ddi_remove_minor_node(zfs_dip, chrbuf); ddi_soft_state_free(zfsdev_state, minor); dmu_objset_disown(os, FTAG); - mutex_exit(&spa_namespace_lock); + mutex_exit(&zfsdev_state_lock); return (SET_ERROR(EAGAIN)); } zs = ddi_get_soft_state(zfsdev_state, minor); zs->zss_type = ZSST_ZVOL; zv = zs->zss_data = kmem_zalloc(sizeof (zvol_state_t), KM_SLEEP); -#else /* !sun */ +#else /* !illumos */ zv = kmem_zalloc(sizeof(*zv), KM_SLEEP); zv->zv_state = 0; @@ -613,7 +659,7 @@ zvol_create_minor(const char *name) if (error) { kmem_free(zv, sizeof(*zv)); dmu_objset_disown(os, zvol_tag); - mutex_exit(&spa_namespace_lock); + mutex_exit(&zfsdev_state_lock); return (error); } error = dsl_prop_get_integer(name, @@ -644,7 +690,7 @@ zvol_create_minor(const char *name) 0640, "%s/%s", ZVOL_DRIVER, name) != 0) { kmem_free(zv, sizeof(*zv)); dmu_objset_disown(os, FTAG); - mutex_exit(&spa_namespace_lock); + mutex_exit(&zfsdev_state_lock); return (SET_ERROR(ENXIO)); } zv->zv_dev = dev; @@ -652,10 +698,13 @@ zvol_create_minor(const char *name) dev->si_drv2 = zv; } LIST_INSERT_HEAD(&all_zvols, zv, zv_links); -#endif /* !sun */ +#endif /* illumos */ (void) strlcpy(zv->zv_name, name, MAXPATHLEN); zv->zv_min_bs = DEV_BSHIFT; +#ifdef illumos + zv->zv_minor = minor; +#endif zv->zv_objset = os; if (dmu_objset_is_snapshot(os) || !spa_writeable(dmu_objset_spa(os))) zv->zv_flags |= ZVOL_RDONLY; @@ -680,17 +729,16 @@ zvol_create_minor(const char *name) zvol_minors++; - mutex_exit(&spa_namespace_lock); - -#ifndef sun + mutex_exit(&zfsdev_state_lock); +#ifndef illumos if (zv->zv_volmode == ZFS_VOLMODE_GEOM) { zvol_geom_run(zv); g_topology_unlock(); } PICKUP_GIANT(); -#endif ZFS_LOG(1, "ZVOL %s created.", name); +#endif return (0); } @@ -701,20 +749,24 @@ zvol_create_minor(const char *name) static int zvol_remove_zv(zvol_state_t *zv) { -#ifdef sun +#ifdef illumos + char nmbuf[20]; minor_t minor = zv->zv_minor; #endif - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(MUTEX_HELD(&zfsdev_state_lock)); if (zv->zv_total_opens != 0) return (SET_ERROR(EBUSY)); - ZFS_LOG(1, "ZVOL %s destroyed.", zv->zv_name); - -#ifdef sun +#ifdef illumos (void) snprintf(nmbuf, sizeof (nmbuf), "%u,raw", minor); ddi_remove_minor_node(zfs_dip, nmbuf); + + (void) snprintf(nmbuf, sizeof (nmbuf), "%u", minor); + ddi_remove_minor_node(zfs_dip, nmbuf); #else + ZFS_LOG(1, "ZVOL %s destroyed.", zv->zv_name); + LIST_REMOVE(zv, zv_links); if (zv->zv_volmode == ZFS_VOLMODE_GEOM) { g_topology_lock(); @@ -722,13 +774,15 @@ zvol_remove_zv(zvol_state_t *zv) g_topology_unlock(); } else if (zv->zv_volmode == ZFS_VOLMODE_DEV) destroy_dev(zv->zv_dev); -#endif /* sun */ +#endif avl_destroy(&zv->zv_znode.z_range_avl); mutex_destroy(&zv->zv_znode.z_range_lock); - kmem_free(zv, sizeof(*zv)); - + kmem_free(zv, sizeof (zvol_state_t)); +#ifdef illumos + ddi_soft_state_free(zfsdev_state, minor); +#endif zvol_minors--; return (0); } @@ -739,13 +793,13 @@ zvol_remove_minor(const char *name) zvol_state_t *zv; int rc; - mutex_enter(&spa_namespace_lock); + mutex_enter(&zfsdev_state_lock); if ((zv = zvol_minor_lookup(name)) == NULL) { - mutex_exit(&spa_namespace_lock); + mutex_exit(&zfsdev_state_lock); return (SET_ERROR(ENXIO)); } rc = zvol_remove_zv(zv); - mutex_exit(&spa_namespace_lock); + mutex_exit(&zfsdev_state_lock); return (rc); } @@ -763,21 +817,22 @@ zvol_first_open(zvol_state_t *zv) if (error) return (error); + zv->zv_objset = os; error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &volsize); if (error) { ASSERT(error == 0); dmu_objset_disown(os, zvol_tag); return (error); } - zv->zv_objset = os; + error = dmu_bonus_hold(os, ZVOL_OBJ, zvol_tag, &zv->zv_dbuf); if (error) { dmu_objset_disown(os, zvol_tag); return (error); } - zv->zv_volsize = volsize; + + zvol_size_changed(zv, volsize); zv->zv_zilog = zil_open(os, zvol_get_data); - zvol_size_changed(zv); VERIFY(dsl_prop_get_integer(zv->zv_name, "readonly", &readonly, NULL) == 0); @@ -810,7 +865,7 @@ zvol_last_close(zvol_state_t *zv) zv->zv_objset = NULL; } -#ifdef sun +#ifdef illumos int zvol_prealloc(zvol_state_t *zv) { @@ -849,7 +904,7 @@ zvol_prealloc(zvol_state_t *zv) return (0); } -#endif /* sun */ +#endif /* illumos */ static int zvol_update_volsize(objset_t *os, uint64_t volsize) @@ -857,7 +912,7 @@ zvol_update_volsize(objset_t *os, uint64 dmu_tx_t *tx; int error; - ASSERT(MUTEX_HELD(&spa_namespace_lock)); + ASSERT(MUTEX_HELD(&zfsdev_state_lock)); tx = dmu_tx_create(os); dmu_tx_hold_zap(tx, ZVOL_ZAP_OBJ, TRUE, NULL); @@ -881,13 +936,34 @@ zvol_update_volsize(objset_t *os, uint64 void zvol_remove_minors(const char *name) { +#ifdef illumos + zvol_state_t *zv; + char *namebuf; + minor_t minor; + + namebuf = kmem_zalloc(strlen(name) + 2, KM_SLEEP); + (void) strncpy(namebuf, name, strlen(name)); + (void) strcat(namebuf, "/"); + mutex_enter(&zfsdev_state_lock); + for (minor = 1; minor <= ZFSDEV_MAX_MINOR; minor++) { + + zv = zfsdev_get_soft_state(minor, ZSST_ZVOL); + if (zv == NULL) + continue; + if (strncmp(namebuf, zv->zv_name, strlen(namebuf)) == 0) + (void) zvol_remove_zv(zv); + } + kmem_free(namebuf, strlen(name) + 2); + + mutex_exit(&zfsdev_state_lock); +#else /* !illumos */ zvol_state_t *zv, *tzv; size_t namelen; namelen = strlen(name); DROP_GIANT(); - mutex_enter(&spa_namespace_lock); + mutex_enter(&zfsdev_state_lock); LIST_FOREACH_SAFE(zv, &all_zvols, zv_links, tzv) { if (strcmp(zv->zv_name, name) == 0 || @@ -898,69 +974,48 @@ zvol_remove_minors(const char *name) } } - mutex_exit(&spa_namespace_lock); + mutex_exit(&zfsdev_state_lock); PICKUP_GIANT(); +#endif /* illumos */ } -int -zvol_set_volsize(const char *name, major_t maj, uint64_t volsize) +static int +zvol_update_live_volsize(zvol_state_t *zv, uint64_t volsize) { - zvol_state_t *zv = NULL; - objset_t *os; - int error; - dmu_object_info_t doi; uint64_t old_volsize = 0ULL; - uint64_t readonly; - - mutex_enter(&spa_namespace_lock); - zv = zvol_minor_lookup(name); - if ((error = dmu_objset_hold(name, FTAG, &os)) != 0) { - mutex_exit(&spa_namespace_lock); - return (error); - } + int error = 0; - if ((error = dmu_object_info(os, ZVOL_OBJ, &doi)) != 0 || - (error = zvol_check_volsize(volsize, - doi.doi_data_block_size)) != 0) - goto out; + ASSERT(MUTEX_HELD(&zfsdev_state_lock)); - VERIFY(dsl_prop_get_integer(name, "readonly", &readonly, - NULL) == 0); - if (readonly) { - error = EROFS; - goto out; - } - - error = zvol_update_volsize(os, volsize); /* * Reinitialize the dump area to the new size. If we * failed to resize the dump area then restore it back to - * its original size. + * its original size. We must set the new volsize prior + * to calling dumpvp_resize() to ensure that the devices' + * size(9P) is not visible by the dump subsystem. */ - if (zv && error == 0) { + old_volsize = zv->zv_volsize; + zvol_size_changed(zv, volsize); + #ifdef ZVOL_DUMP - if (zv->zv_flags & ZVOL_DUMPIFIED) { - old_volsize = zv->zv_volsize; - zv->zv_volsize = volsize; - if ((error = zvol_dumpify(zv)) != 0 || - (error = dumpvp_resize()) != 0) { - (void) zvol_update_volsize(os, old_volsize); - zv->zv_volsize = old_volsize; - error = zvol_dumpify(zv); - } - } -#endif /* ZVOL_DUMP */ - if (error == 0) { - zv->zv_volsize = volsize; - zvol_size_changed(zv); + if (zv->zv_flags & ZVOL_DUMPIFIED) { + if ((error = zvol_dumpify(zv)) != 0 || + (error = dumpvp_resize()) != 0) { + int dumpify_error; + + (void) zvol_update_volsize(zv->zv_objset, old_volsize); + zvol_size_changed(zv, old_volsize); + dumpify_error = zvol_dumpify(zv); + error = dumpify_error ? dumpify_error : error; } } +#endif /* ZVOL_DUMP */ -#ifdef sun +#ifdef illumos /* * Generate a LUN expansion event. */ - if (zv && error == 0) { + if (error == 0) { sysevent_id_t eid; nvlist_t *attr; char *physpath = kmem_zalloc(MAXPATHLEN, KM_SLEEP); @@ -977,22 +1032,89 @@ zvol_set_volsize(const char *name, major nvlist_free(attr); kmem_free(physpath, MAXPATHLEN); } -#endif /* sun */ +#endif /* illumos */ + return (error); +} -out: - dmu_objset_rele(os, FTAG); +int +zvol_set_volsize(const char *name, uint64_t volsize) +{ + zvol_state_t *zv = NULL; + objset_t *os; + int error; + dmu_object_info_t doi; + uint64_t readonly; + boolean_t owned = B_FALSE; + + error = dsl_prop_get_integer(name, + zfs_prop_to_name(ZFS_PROP_READONLY), &readonly, NULL); + if (error != 0) + return (error); + if (readonly) + return (SET_ERROR(EROFS)); + + mutex_enter(&zfsdev_state_lock); + zv = zvol_minor_lookup(name); + + if (zv == NULL || zv->zv_objset == NULL) { + if ((error = dmu_objset_own(name, DMU_OST_ZVOL, B_FALSE, + FTAG, &os)) != 0) { + mutex_exit(&zfsdev_state_lock); + return (error); + } + owned = B_TRUE; + if (zv != NULL) + zv->zv_objset = os; + } else { + os = zv->zv_objset; + } + + if ((error = dmu_object_info(os, ZVOL_OBJ, &doi)) != 0 || + (error = zvol_check_volsize(volsize, doi.doi_data_block_size)) != 0) + goto out; - mutex_exit(&spa_namespace_lock); + error = zvol_update_volsize(os, volsize); + if (error == 0 && zv != NULL) + error = zvol_update_live_volsize(zv, volsize); +out: + if (owned) { + dmu_objset_disown(os, FTAG); + if (zv != NULL) + zv->zv_objset = NULL; + } + mutex_exit(&zfsdev_state_lock); return (error); } /*ARGSUSED*/ +#ifdef illumos +int +zvol_open(dev_t *devp, int flag, int otyp, cred_t *cr) +#else static int zvol_open(struct g_provider *pp, int flag, int count) +#endif { zvol_state_t *zv; int err = 0; +#ifdef illumos + + mutex_enter(&zfsdev_state_lock); + + zv = zfsdev_get_soft_state(getminor(*devp), ZSST_ZVOL); + if (zv == NULL) { + mutex_exit(&zfsdev_state_lock); + return (SET_ERROR(ENXIO)); + } + + if (zv->zv_total_opens == 0) + err = zvol_first_open(zv); + if (err) { + mutex_exit(&zfsdev_state_lock); + return (err); + } +#else /* !illumos */ boolean_t locked = B_FALSE; /* @@ -1006,15 +1128,15 @@ zvol_open(struct g_provider *pp, int fla * recursively, but that function already has all the * necessary protection. */ - if (!MUTEX_HELD(&spa_namespace_lock)) { - mutex_enter(&spa_namespace_lock); + if (!MUTEX_HELD(&zfsdev_state_lock)) { + mutex_enter(&zfsdev_state_lock); locked = B_TRUE; } zv = pp->private; if (zv == NULL) { if (locked) - mutex_exit(&spa_namespace_lock); + mutex_exit(&zfsdev_state_lock); return (SET_ERROR(ENXIO)); } @@ -1022,13 +1144,14 @@ zvol_open(struct g_provider *pp, int fla err = zvol_first_open(zv); if (err) { if (locked) - mutex_exit(&spa_namespace_lock); + mutex_exit(&zfsdev_state_lock); return (err); } pp->mediasize = zv->zv_volsize; pp->stripeoffset = 0; pp->stripesize = zv->zv_volblocksize; } +#endif /* illumos */ if ((flag & FWRITE) && (zv->zv_flags & ZVOL_RDONLY)) { err = SET_ERROR(EROFS); goto out; @@ -1047,20 +1170,46 @@ zvol_open(struct g_provider *pp, int fla } #endif +#ifdef illumos + if (zv->zv_open_count[otyp] == 0 || otyp == OTYP_LYR) { + zv->zv_open_count[otyp]++; + zv->zv_total_opens++; + } + mutex_exit(&zfsdev_state_lock); +#else zv->zv_total_opens += count; if (locked) - mutex_exit(&spa_namespace_lock); + mutex_exit(&zfsdev_state_lock); +#endif return (err); out: if (zv->zv_total_opens == 0) zvol_last_close(zv); +#ifdef illumos + mutex_exit(&zfsdev_state_lock); +#else if (locked) - mutex_exit(&spa_namespace_lock); + mutex_exit(&zfsdev_state_lock); +#endif return (err); } /*ARGSUSED*/ +#ifdef illumos +int +zvol_close(dev_t dev, int flag, int otyp, cred_t *cr) +{ + minor_t minor = getminor(dev); + zvol_state_t *zv; + int error = 0; + + mutex_enter(&zfsdev_state_lock); + + zv = zfsdev_get_soft_state(minor, ZSST_ZVOL); + if (zv == NULL) { + mutex_exit(&zfsdev_state_lock); +#else /* !illumos */ static int zvol_close(struct g_provider *pp, int flag, int count) { @@ -1069,15 +1218,16 @@ zvol_close(struct g_provider *pp, int fl boolean_t locked = B_FALSE; /* See comment in zvol_open(). */ - if (!MUTEX_HELD(&spa_namespace_lock)) { - mutex_enter(&spa_namespace_lock); + if (!MUTEX_HELD(&zfsdev_state_lock)) { + mutex_enter(&zfsdev_state_lock); locked = B_TRUE; } zv = pp->private; if (zv == NULL) { if (locked) - mutex_exit(&spa_namespace_lock); + mutex_exit(&zfsdev_state_lock); +#endif /* illumos */ return (SET_ERROR(ENXIO)); } @@ -1090,18 +1240,30 @@ zvol_close(struct g_provider *pp, int fl * If the open count is zero, this is a spurious close. * That indicates a bug in the kernel / DDI framework. */ +#ifdef illumos + ASSERT(zv->zv_open_count[otyp] != 0); +#endif ASSERT(zv->zv_total_opens != 0); /* * You may get multiple opens, but only one close. */ +#ifdef illumos + zv->zv_open_count[otyp]--; + zv->zv_total_opens--; +#else zv->zv_total_opens -= count; +#endif if (zv->zv_total_opens == 0) zvol_last_close(zv); +#ifdef illumos + mutex_exit(&zfsdev_state_lock); +#else if (locked) - mutex_exit(&spa_namespace_lock); + mutex_exit(&zfsdev_state_lock); +#endif return (error); } @@ -1261,7 +1423,7 @@ zvol_log_write(zvol_state_t *zv, dmu_tx_ } } -#ifdef sun +#ifdef illumos static int zvol_dumpio_vdev(vdev_t *vd, void *addr, uint64_t offset, uint64_t origoffset, uint64_t size, boolean_t doread, boolean_t isdump) @@ -1354,11 +1516,16 @@ zvol_dumpio(zvol_state_t *zv, void *addr return (error); } -#endif /* sun */ +int +zvol_strategy(buf_t *bp) +{ + zfs_soft_state_t *zs = NULL; +#else /* !illumos */ void zvol_strategy(struct bio *bp) { +#endif /* illumos */ zvol_state_t *zv; uint64_t off, volsize; size_t resid; @@ -1366,22 +1533,53 @@ zvol_strategy(struct bio *bp) objset_t *os; rl_t *rl; int error = 0; +#ifdef illumos + boolean_t doread = bp->b_flags & B_READ; +#else boolean_t doread = 0; +#endif boolean_t is_dumpified; boolean_t sync; +#ifdef illumos + if (getminor(bp->b_edev) == 0) { + error = SET_ERROR(EINVAL); + } else { + zs = ddi_get_soft_state(zfsdev_state, getminor(bp->b_edev)); + if (zs == NULL) + error = SET_ERROR(ENXIO); + else if (zs->zss_type != ZSST_ZVOL) + error = SET_ERROR(EINVAL); + } + + if (error) { + bioerror(bp, error); + biodone(bp); + return (0); + } + + zv = zs->zss_data; + + if (!(bp->b_flags & B_READ) && (zv->zv_flags & ZVOL_RDONLY)) { + bioerror(bp, EROFS); + biodone(bp); + return (0); + } + + off = ldbtob(bp->b_blkno); +#else /* !illumos */ if (bp->bio_to) zv = bp->bio_to->private; else zv = bp->bio_dev->si_drv2; if (zv == NULL) { - error = ENXIO; + error = SET_ERROR(ENXIO); goto out; } if (bp->bio_cmd != BIO_READ && (zv->zv_flags & ZVOL_RDONLY)) { - error = EROFS; + error = SET_ERROR(EROFS); goto out; } @@ -1399,26 +1597,41 @@ zvol_strategy(struct bio *bp) } off = bp->bio_offset; +#endif /* illumos */ volsize = zv->zv_volsize; os = zv->zv_objset; ASSERT(os != NULL); +#ifdef illumos + bp_mapin(bp); + addr = bp->b_un.b_addr; + resid = bp->b_bcount; + + if (resid > 0 && (off < 0 || off >= volsize)) { + bioerror(bp, EIO); + biodone(bp); + return (0); + } + + is_dumpified = zv->zv_flags & ZVOL_DUMPIFIED; + sync = ((!(bp->b_flags & B_ASYNC) && + !(zv->zv_flags & ZVOL_WCE)) || + (zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS)) && + !doread && !is_dumpified; +#else /* !illumos */ addr = bp->bio_data; resid = bp->bio_length; if (resid > 0 && (off < 0 || off >= volsize)) { - error = EIO; + error = SET_ERROR(EIO); goto out; } -#ifdef illumos - is_dumpified = zv->zv_flags & ZVOL_DUMPIFIED; -#else is_dumpified = B_FALSE; -#endif - sync = !doread && !is_dumpified && + sync = !doread && !is_dumpified && zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS; +#endif /* illumos */ /* * There must be no buffer changes when doing a dmu_sync() because @@ -1427,6 +1640,7 @@ zvol_strategy(struct bio *bp) rl = zfs_range_lock(&zv->zv_znode, off, resid, doread ? RL_READER : RL_WRITER); +#ifndef illumos if (bp->bio_cmd == BIO_DELETE) { dmu_tx_t *tx = dmu_tx_create(zv->zv_objset); error = dmu_tx_assign(tx, TXG_WAIT); @@ -1441,7 +1655,7 @@ zvol_strategy(struct bio *bp) } goto unlock; } - +#endif *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***