diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c index 9cd6e57e09b4..c700a0ffd74f 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -2020,6 +2021,7 @@ spa_init(int mode) dmu_init(); zil_init(); vdev_cache_stat_init(); + vdev_file_init(); zfs_prop_init(); zpool_prop_init(); zpool_feature_init(); @@ -2039,6 +2041,7 @@ spa_fini(void) spa_evict_all(); + vdev_file_fini(); vdev_cache_stat_fini(); zil_fini(); dmu_fini(); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/vdev_file.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/vdev_file.h index cd496735778c..0260b4ab4f79 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/vdev_file.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/vdev_file.h @@ -39,6 +39,9 @@ typedef struct vdev_file { vnode_t *vf_vnode; } vdev_file_t; +extern void vdev_file_init(void); +extern void vdev_file_fini(void); + #ifdef __cplusplus } #endif diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_file.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_file.c index cdcd18e2b803..af6b406b3e5a 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_file.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_file.c @@ -36,6 +36,21 @@ * Virtual device vector for files. */ +static taskq_t *vdev_file_taskq; + +void +vdev_file_init(void) +{ + vdev_file_taskq = taskq_create("z_vdev_file", MAX(max_ncpus, 16), + minclsyspri, max_ncpus, INT_MAX, 0); +} + +void +vdev_file_fini(void) +{ + taskq_destroy(vdev_file_taskq); +} + static void vdev_file_hold(vdev_t *vd) { @@ -157,41 +172,32 @@ vdev_file_close(vdev_t *vd) vd->vdev_tsd = NULL; } +/* + * Implements the interrupt side for file vdev types. This routine will be + * called when the I/O completes allowing us to transfer the I/O to the + * interrupt taskqs. For consistency, the code structure mimics disk vdev + * types. + */ static void -vdev_file_io_start(zio_t *zio) +vdev_file_io_intr(zio_t *zio) { + zio_delay_interrupt(zio); +} + +static void +vdev_file_io_strategy(void *arg) +{ + zio_t *zio = arg; vdev_t *vd = zio->io_vd; vdev_file_t *vf; vnode_t *vp; void *addr; ssize_t resid; - if (!vdev_readable(vd)) { - zio->io_error = SET_ERROR(ENXIO); - zio_interrupt(zio); - return; - } - vf = vd->vdev_tsd; vp = vf->vf_vnode; - if (zio->io_type == ZIO_TYPE_IOCTL) { - switch (zio->io_cmd) { - case DKIOCFLUSHWRITECACHE: - zio->io_error = VOP_FSYNC(vp, FSYNC | FDSYNC, - kcred, NULL); - break; - default: - zio->io_error = SET_ERROR(ENOTSUP); - } - - zio_execute(zio); - return; - } - ASSERT(zio->io_type == ZIO_TYPE_READ || zio->io_type == ZIO_TYPE_WRITE); - zio->io_target_timestamp = zio_handle_io_delay(zio); - if (zio->io_type == ZIO_TYPE_READ) { addr = abd_borrow_buf(zio->io_abd, zio->io_size); } else { @@ -211,12 +217,41 @@ vdev_file_io_start(zio_t *zio) if (resid != 0 && zio->io_error == 0) zio->io_error = ENOSPC; - zio_delay_interrupt(zio); + vdev_file_io_intr(zio); +} -#ifdef illumos - VERIFY3U(taskq_dispatch(system_taskq, vdev_file_io_strategy, bp, +static void +vdev_file_io_start(zio_t *zio) +{ + vdev_t *vd = zio->io_vd; + vdev_file_t *vf = vd->vdev_tsd; + + if (zio->io_type == ZIO_TYPE_IOCTL) { + /* XXPOLICY */ + if (!vdev_readable(vd)) { + zio->io_error = SET_ERROR(ENXIO); + zio_interrupt(zio); + return; + } + + switch (zio->io_cmd) { + case DKIOCFLUSHWRITECACHE: + zio->io_error = VOP_FSYNC(vf->vf_vnode, FSYNC | FDSYNC, + kcred, NULL); + break; + default: + zio->io_error = SET_ERROR(ENOTSUP); + } + + zio_execute(zio); + return; + } + + ASSERT(zio->io_type == ZIO_TYPE_READ || zio->io_type == ZIO_TYPE_WRITE); + zio->io_target_timestamp = zio_handle_io_delay(zio); + + VERIFY3U(taskq_dispatch(vdev_file_taskq, vdev_file_io_strategy, zio, TQ_SLEEP), !=, 0); -#endif } /* ARGSUSED */