diff options
author | avg <avg@FreeBSD.org> | 2017-09-19 08:39:54 +0000 |
---|---|---|
committer | avg <avg@FreeBSD.org> | 2017-09-19 08:39:54 +0000 |
commit | 18f51dea94fb18a51a6351748a7533a4b7f29348 (patch) | |
tree | 978c388dbfcbc22dcba89c3133afeb2041ac4cab | |
parent | 31c3680770a54ff4b4076534f83fe8a6c74508c7 (diff) | |
download | FreeBSD-src-18f51dea94fb18a51a6351748a7533a4b7f29348.zip FreeBSD-src-18f51dea94fb18a51a6351748a7533a4b7f29348.tar.gz |
MFC r320352: zfs: port vdev_file part of illumos change 3306
3306 zdb should be able to issue reads in parallel
illumos/illumos-gate/31d7e8fa33fae995f558673adb22641b5aa8b6e1
https://www.illumos.org/issues/3306
The upstream change was made before we started to import upstream commits
individually. It was imported into the illumos vendor area as r242733.
That commit was MFV-ed in r260138, but as the commit message says
vdev_file.c was left intact.
This commit actually implements the parallel I/O for vdev_file using a
taskqueue with multiple thread. This implementation does not depend on
the illumos or FreeBSD bio interface at all, but uses zio_t to pass
around all the relevent data. So, the code looks a bit different from
the upstream.
This commit also incorporates ZoL commit
zfsonlinux/zfs/bc25c9325b0e5ced897b9820dad239539d561ec9 that fixed
https://github.com/zfsonlinux/zfs/issues/2270
We need to use a dedicated taskqueue for exactly the same reason as ZoL
as we do not implement TASKQ_DYNAMIC.
3 files changed, 61 insertions, 20 deletions
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 cafa083..34b1b6e 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 <sys/zap.h> #include <sys/zil.h> #include <sys/vdev_impl.h> +#include <sys/vdev_file.h> #include <sys/metaslab.h> #include <sys/uberblock_impl.h> #include <sys/txg.h> @@ -2013,6 +2014,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(); @@ -2032,6 +2034,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 cd49673..0260b4a 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 8228af1..e083000 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 @@ -35,6 +35,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) { @@ -156,27 +171,58 @@ 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; 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; + ASSERT(zio->io_type == ZIO_TYPE_READ || zio->io_type == ZIO_TYPE_WRITE); + zio->io_error = vn_rdwr(zio->io_type == ZIO_TYPE_READ ? + UIO_READ : UIO_WRITE, vp, zio->io_data, zio->io_size, + zio->io_offset, UIO_SYSSPACE, 0, RLIM64_INFINITY, kcred, &resid); + + if (resid != 0 && zio->io_error == 0) + zio->io_error = ENOSPC; + + vdev_file_io_intr(zio); +} + +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(vp, FSYNC | FDSYNC, + zio->io_error = VOP_FSYNC(vf->vf_vnode, FSYNC | FDSYNC, kcred, NULL); break; default: @@ -190,19 +236,8 @@ vdev_file_io_start(zio_t *zio) ASSERT(zio->io_type == ZIO_TYPE_READ || zio->io_type == ZIO_TYPE_WRITE); zio->io_target_timestamp = zio_handle_io_delay(zio); - zio->io_error = vn_rdwr(zio->io_type == ZIO_TYPE_READ ? - UIO_READ : UIO_WRITE, vp, zio->io_data, zio->io_size, - zio->io_offset, UIO_SYSSPACE, 0, RLIM64_INFINITY, kcred, &resid); - - if (resid != 0 && zio->io_error == 0) - zio->io_error = ENOSPC; - - zio_delay_interrupt(zio); - -#ifdef illumos - VERIFY3U(taskq_dispatch(system_taskq, vdev_file_io_strategy, bp, + VERIFY3U(taskq_dispatch(vdev_file_taskq, vdev_file_io_strategy, zio, TQ_SLEEP), !=, 0); -#endif } /* ARGSUSED */ |