From 24d44898020531c24ba8914b294876e52f304e4f Mon Sep 17 00:00:00 2001 From: pjd Date: Sat, 21 Apr 2007 12:02:57 +0000 Subject: MFp4: @118370 Correct typo. @118371 Integrate changes from vendor. @118491 Show backtrace on unexpected code paths. @118494 Integrate changes from vendor. @118504 Fix sendfile(2). I had two ways of fixing it: 1. Fixing sendfile(2) itself to use VOP_GETPAGES() instead of hacking around with vn_rdwr(UIO_NOCOPY), which was suggested by ups. 2. Modify ZFS behaviour to handle this special case. Although 1 is more correct, I've choosen 2, because hack from 1 have a side-effect of beeing faster - it reads ahead MAXBSIZE bytes instead of reading page by page. This is not easy to implement with VOP_GETPAGES(), at least not for me in this very moment. Reported by: Andrey V. Elsukov @118525 Reorganize the code to reduce diff. @118526 This code path is expected. It is simply when file is opened with O_FSYNC flag. Reported by: kris Reported by: Michal Suszko --- sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c | 2 +- .../contrib/opensolaris/uts/common/fs/zfs/spa.c | 9 +++---- .../contrib/opensolaris/uts/common/fs/zfs/vdev.c | 4 ++-- .../opensolaris/uts/common/fs/zfs/zfs_vnops.c | 28 +++++++++++++++------- .../contrib/opensolaris/uts/common/fs/zfs/zio.c | 20 ++++++++++------ sys/compat/opensolaris/kern/opensolaris_vfs.c | 2 +- sys/contrib/opensolaris/uts/common/fs/zfs/spa.c | 9 +++---- sys/contrib/opensolaris/uts/common/fs/zfs/vdev.c | 4 ++-- .../opensolaris/uts/common/fs/zfs/zfs_vnops.c | 28 +++++++++++++++------- sys/contrib/opensolaris/uts/common/fs/zfs/zio.c | 20 ++++++++++------ 10 files changed, 76 insertions(+), 50 deletions(-) (limited to 'sys') diff --git a/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c b/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c index 35404ca..ef184b4 100644 --- a/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c +++ b/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c @@ -206,7 +206,7 @@ domount(kthread_t *td, vnode_t *vp, const char *fstype, char *fspath, mp->mnt_flag |= fsflags & (MNT_UPDATEMASK | MNT_FORCE | MNT_ROOTFS); /* * Unprivileged user can trigger mounting a snapshot, but we don't want - * him to unmount it, so we switch to privileged credential. + * him to unmount it, so we switch to privileged credentials. */ crfree(mp->mnt_cred); mp->mnt_cred = crdup(kcred); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c index f8d9465..c6a95a1 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c @@ -499,10 +499,9 @@ spa_load(spa_t *spa, nvlist_t *config, spa_load_state_t state, int mosconfig) /* * Try to open all vdevs, loading each label in the process. */ - if (vdev_open(rvd) != 0) { - error = ENXIO; + error = vdev_open(rvd); + if (error != 0) goto out; - } /* * Validate the labels for all leaf vdevs. We need to grab the config @@ -513,10 +512,8 @@ spa_load(spa_t *spa, nvlist_t *config, spa_load_state_t state, int mosconfig) error = vdev_validate(rvd); spa_config_exit(spa, FTAG); - if (error != 0) { - error = EBADF; + if (error != 0) goto out; - } if (rvd->vdev_state <= VDEV_STATE_CANT_OPEN) { error = ENXIO; diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c index 0fceb8d..d15f6e2 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c @@ -931,7 +931,7 @@ vdev_validate(vdev_t *vd) for (c = 0; c < vd->vdev_children; c++) if (vdev_validate(vd->vdev_child[c]) != 0) - return (-1); + return (EBADF); /* * If the device has already failed, or was marked offline, don't do @@ -974,7 +974,7 @@ vdev_validate(vdev_t *vd) if (spa->spa_load_state == SPA_LOAD_OPEN && state != POOL_STATE_ACTIVE) - return (-1); + return (EBADF); } /* diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c index 5f74eb8..7af6b20 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c @@ -165,10 +165,8 @@ zfs_open(ap) int flag = ap->a_mode; /* Keep a count of the synchronous opens in the znode */ - if (flag & FFSYNC) { + if (flag & FFSYNC) atomic_inc_32(&zp->z_sync_cnt); - ZFS_LOG(0, "Unexpected code path, report to pjd@FreeBSD.org"); - } vnode_create_vobject(vp, zp->z_phys->zp_size, ap->a_td); return (0); @@ -188,10 +186,8 @@ zfs_close(ap) int flag = ap->a_fflag; /* Decrement the synchronous opens in the znode */ - if (flag & FFSYNC) { + if (flag & FFSYNC) atomic_dec_32(&zp->z_sync_cnt); - ZFS_LOG(0, "Unexpected code path, report to pjd@FreeBSD.org"); - } return (0); } @@ -362,6 +358,7 @@ mappedread(vnode_t *vp, int nbytes, uio_t *uio) vm_page_t m; struct sf_buf *sf; int64_t start, off; + caddr_t va; int len = nbytes; int error = 0; @@ -378,8 +375,6 @@ mappedread(vnode_t *vp, int nbytes, uio_t *uio) again: if ((m = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL && vm_page_is_valid(m, (vm_offset_t)off, bytes)) { - caddr_t va; - if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) goto again; vm_page_busy(m); @@ -392,6 +387,21 @@ again: sched_unpin(); VM_OBJECT_LOCK(obj); vm_page_wakeup(m); + } else if (m != NULL && uio->uio_segflg == UIO_NOCOPY) { + if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) + goto again; + vm_page_busy(m); + VM_OBJECT_UNLOCK(obj); + sched_pin(); + sf = sf_buf_alloc(m, SFB_CPUPRIVATE); + va = (caddr_t)sf_buf_kva(sf); + error = dmu_read(os, zp->z_id, start + off, bytes, + (void *)(va + off)); + sf_buf_free(sf); + sched_unpin(); + VM_OBJECT_LOCK(obj); + vm_page_wakeup(m); + uio->uio_resid -= bytes; } else { VM_OBJECT_UNLOCK(obj); error = dmu_read_uio(os, zp->z_id, uio, bytes); @@ -2461,7 +2471,7 @@ top: if (tvp) vrele(tvp); else { - ZFS_LOG(0, "Unexpected code path, report to pjd@FreeBSD.org"); + ZFS_LOG(0x100, "Unexpected code path, report to pjd@FreeBSD.org"); tvp = ZTOV(tzp); vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY, curthread); } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c index 6bc4a36..99c0dd3 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c @@ -79,12 +79,13 @@ zio_sync_pass_t zio_sync_pass = { 1, /* zp_rewrite */ }; -#ifdef ZIO_USE_UMA /* * ========================================================================== * I/O kmem caches * ========================================================================== */ +kmem_cache_t *zio_cache; +#ifdef ZIO_USE_UMA kmem_cache_t *zio_buf_cache[SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT]; kmem_cache_t *zio_data_buf_cache[SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT]; #endif @@ -107,6 +108,9 @@ zio_init(void) #endif #endif + zio_cache = kmem_cache_create("zio_cache", sizeof (zio_t), 0, + NULL, NULL, NULL, NULL, NULL, 0); + #ifdef ZIO_USE_UMA /* * For small buffers, we want a cache for each multiple of @@ -183,6 +187,8 @@ zio_fini(void) } #endif + kmem_cache_destroy(zio_cache); + zio_inject_fini(); } @@ -329,7 +335,8 @@ zio_create(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp, ASSERT3U(size, <=, SPA_MAXBLOCKSIZE); ASSERT(P2PHASE(size, SPA_MINBLOCKSIZE) == 0); - zio = kmem_zalloc(sizeof (zio_t), KM_SLEEP); + zio = kmem_cache_alloc(zio_cache, KM_SLEEP); + bzero(zio, sizeof (zio_t)); zio->io_parent = pio; zio->io_spa = spa; zio->io_txg = txg; @@ -777,7 +784,7 @@ zio_wait(zio_t *zio) error = zio->io_error; cv_destroy(&zio->io_cv); mutex_destroy(&zio->io_lock); - kmem_free(zio, sizeof (zio_t)); + kmem_cache_free(zio_cache, zio); return (error); } @@ -957,9 +964,8 @@ zio_done(zio_t *zio) } /* - * Note: this I/O is now done, and will shortly be - * kmem_free()'d, so there is no need to clear this (or any - * other) flag. + * Note: this I/O is now done, and will shortly be freed, so there is no + * need to clear this (or any other) flag. */ if (zio->io_flags & ZIO_FLAG_CONFIG_GRABBED) spa_config_exit(spa, zio); @@ -971,7 +977,7 @@ zio_done(zio_t *zio) cv_broadcast(&zio->io_cv); mutex_exit(&zio->io_lock); } else { - kmem_free(zio, sizeof (zio_t)); + kmem_cache_free(zio_cache, zio); } } diff --git a/sys/compat/opensolaris/kern/opensolaris_vfs.c b/sys/compat/opensolaris/kern/opensolaris_vfs.c index 35404ca..ef184b4 100644 --- a/sys/compat/opensolaris/kern/opensolaris_vfs.c +++ b/sys/compat/opensolaris/kern/opensolaris_vfs.c @@ -206,7 +206,7 @@ domount(kthread_t *td, vnode_t *vp, const char *fstype, char *fspath, mp->mnt_flag |= fsflags & (MNT_UPDATEMASK | MNT_FORCE | MNT_ROOTFS); /* * Unprivileged user can trigger mounting a snapshot, but we don't want - * him to unmount it, so we switch to privileged credential. + * him to unmount it, so we switch to privileged credentials. */ crfree(mp->mnt_cred); mp->mnt_cred = crdup(kcred); diff --git a/sys/contrib/opensolaris/uts/common/fs/zfs/spa.c b/sys/contrib/opensolaris/uts/common/fs/zfs/spa.c index f8d9465..c6a95a1 100644 --- a/sys/contrib/opensolaris/uts/common/fs/zfs/spa.c +++ b/sys/contrib/opensolaris/uts/common/fs/zfs/spa.c @@ -499,10 +499,9 @@ spa_load(spa_t *spa, nvlist_t *config, spa_load_state_t state, int mosconfig) /* * Try to open all vdevs, loading each label in the process. */ - if (vdev_open(rvd) != 0) { - error = ENXIO; + error = vdev_open(rvd); + if (error != 0) goto out; - } /* * Validate the labels for all leaf vdevs. We need to grab the config @@ -513,10 +512,8 @@ spa_load(spa_t *spa, nvlist_t *config, spa_load_state_t state, int mosconfig) error = vdev_validate(rvd); spa_config_exit(spa, FTAG); - if (error != 0) { - error = EBADF; + if (error != 0) goto out; - } if (rvd->vdev_state <= VDEV_STATE_CANT_OPEN) { error = ENXIO; diff --git a/sys/contrib/opensolaris/uts/common/fs/zfs/vdev.c b/sys/contrib/opensolaris/uts/common/fs/zfs/vdev.c index 0fceb8d..d15f6e2 100644 --- a/sys/contrib/opensolaris/uts/common/fs/zfs/vdev.c +++ b/sys/contrib/opensolaris/uts/common/fs/zfs/vdev.c @@ -931,7 +931,7 @@ vdev_validate(vdev_t *vd) for (c = 0; c < vd->vdev_children; c++) if (vdev_validate(vd->vdev_child[c]) != 0) - return (-1); + return (EBADF); /* * If the device has already failed, or was marked offline, don't do @@ -974,7 +974,7 @@ vdev_validate(vdev_t *vd) if (spa->spa_load_state == SPA_LOAD_OPEN && state != POOL_STATE_ACTIVE) - return (-1); + return (EBADF); } /* diff --git a/sys/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c index 5f74eb8..7af6b20 100644 --- a/sys/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c +++ b/sys/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c @@ -165,10 +165,8 @@ zfs_open(ap) int flag = ap->a_mode; /* Keep a count of the synchronous opens in the znode */ - if (flag & FFSYNC) { + if (flag & FFSYNC) atomic_inc_32(&zp->z_sync_cnt); - ZFS_LOG(0, "Unexpected code path, report to pjd@FreeBSD.org"); - } vnode_create_vobject(vp, zp->z_phys->zp_size, ap->a_td); return (0); @@ -188,10 +186,8 @@ zfs_close(ap) int flag = ap->a_fflag; /* Decrement the synchronous opens in the znode */ - if (flag & FFSYNC) { + if (flag & FFSYNC) atomic_dec_32(&zp->z_sync_cnt); - ZFS_LOG(0, "Unexpected code path, report to pjd@FreeBSD.org"); - } return (0); } @@ -362,6 +358,7 @@ mappedread(vnode_t *vp, int nbytes, uio_t *uio) vm_page_t m; struct sf_buf *sf; int64_t start, off; + caddr_t va; int len = nbytes; int error = 0; @@ -378,8 +375,6 @@ mappedread(vnode_t *vp, int nbytes, uio_t *uio) again: if ((m = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL && vm_page_is_valid(m, (vm_offset_t)off, bytes)) { - caddr_t va; - if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) goto again; vm_page_busy(m); @@ -392,6 +387,21 @@ again: sched_unpin(); VM_OBJECT_LOCK(obj); vm_page_wakeup(m); + } else if (m != NULL && uio->uio_segflg == UIO_NOCOPY) { + if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) + goto again; + vm_page_busy(m); + VM_OBJECT_UNLOCK(obj); + sched_pin(); + sf = sf_buf_alloc(m, SFB_CPUPRIVATE); + va = (caddr_t)sf_buf_kva(sf); + error = dmu_read(os, zp->z_id, start + off, bytes, + (void *)(va + off)); + sf_buf_free(sf); + sched_unpin(); + VM_OBJECT_LOCK(obj); + vm_page_wakeup(m); + uio->uio_resid -= bytes; } else { VM_OBJECT_UNLOCK(obj); error = dmu_read_uio(os, zp->z_id, uio, bytes); @@ -2461,7 +2471,7 @@ top: if (tvp) vrele(tvp); else { - ZFS_LOG(0, "Unexpected code path, report to pjd@FreeBSD.org"); + ZFS_LOG(0x100, "Unexpected code path, report to pjd@FreeBSD.org"); tvp = ZTOV(tzp); vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY, curthread); } diff --git a/sys/contrib/opensolaris/uts/common/fs/zfs/zio.c b/sys/contrib/opensolaris/uts/common/fs/zfs/zio.c index 6bc4a36..99c0dd3 100644 --- a/sys/contrib/opensolaris/uts/common/fs/zfs/zio.c +++ b/sys/contrib/opensolaris/uts/common/fs/zfs/zio.c @@ -79,12 +79,13 @@ zio_sync_pass_t zio_sync_pass = { 1, /* zp_rewrite */ }; -#ifdef ZIO_USE_UMA /* * ========================================================================== * I/O kmem caches * ========================================================================== */ +kmem_cache_t *zio_cache; +#ifdef ZIO_USE_UMA kmem_cache_t *zio_buf_cache[SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT]; kmem_cache_t *zio_data_buf_cache[SPA_MAXBLOCKSIZE >> SPA_MINBLOCKSHIFT]; #endif @@ -107,6 +108,9 @@ zio_init(void) #endif #endif + zio_cache = kmem_cache_create("zio_cache", sizeof (zio_t), 0, + NULL, NULL, NULL, NULL, NULL, 0); + #ifdef ZIO_USE_UMA /* * For small buffers, we want a cache for each multiple of @@ -183,6 +187,8 @@ zio_fini(void) } #endif + kmem_cache_destroy(zio_cache); + zio_inject_fini(); } @@ -329,7 +335,8 @@ zio_create(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp, ASSERT3U(size, <=, SPA_MAXBLOCKSIZE); ASSERT(P2PHASE(size, SPA_MINBLOCKSIZE) == 0); - zio = kmem_zalloc(sizeof (zio_t), KM_SLEEP); + zio = kmem_cache_alloc(zio_cache, KM_SLEEP); + bzero(zio, sizeof (zio_t)); zio->io_parent = pio; zio->io_spa = spa; zio->io_txg = txg; @@ -777,7 +784,7 @@ zio_wait(zio_t *zio) error = zio->io_error; cv_destroy(&zio->io_cv); mutex_destroy(&zio->io_lock); - kmem_free(zio, sizeof (zio_t)); + kmem_cache_free(zio_cache, zio); return (error); } @@ -957,9 +964,8 @@ zio_done(zio_t *zio) } /* - * Note: this I/O is now done, and will shortly be - * kmem_free()'d, so there is no need to clear this (or any - * other) flag. + * Note: this I/O is now done, and will shortly be freed, so there is no + * need to clear this (or any other) flag. */ if (zio->io_flags & ZIO_FLAG_CONFIG_GRABBED) spa_config_exit(spa, zio); @@ -971,7 +977,7 @@ zio_done(zio_t *zio) cv_broadcast(&zio->io_cv); mutex_exit(&zio->io_lock); } else { - kmem_free(zio, sizeof (zio_t)); + kmem_cache_free(zio_cache, zio); } } -- cgit v1.1