Module Name: src Committed By: hannken Date: Tue Jan 1 10:09:27 UTC 2019
Modified Files: src/external/cddl/osnet/dist/uts/common/fs/zfs: zfs_vnops.c Log Message: Cannot use ZFS_ENTER() / ZFS_EXIT() as zfs_netbsd_putpages() is used during vnode reclaim. Add missing protection with fstrans. To generate a diff of this commit: cvs rdiff -u -r1.40 -r1.41 \ src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c diff -u src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c:1.40 src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c:1.41 --- src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c:1.40 Tue Jan 1 10:08:42 2019 +++ src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c Tue Jan 1 10:09:26 2019 @@ -84,6 +84,7 @@ #include <miscfs/genfs/genfs.h> #include <miscfs/genfs/genfs_node.h> #include <uvm/uvm_extern.h> +#include <sys/fstrans.h> uint_t zfs_putpage_key; #endif @@ -5972,9 +5973,6 @@ zfs_netbsd_putpages(void *v) bool async = (flags & PGO_SYNCIO) == 0; bool cleaning = (flags & PGO_CLEANIT) != 0; - ZFS_ENTER(zfsvfs); - ZFS_VERIFY_ZP(zp); - if (cleaning) { ASSERT((offlo & PAGE_MASK) == 0 && (offhi & PAGE_MASK) == 0); ASSERT(offlo < offhi || offhi == 0); @@ -5983,25 +5981,38 @@ zfs_netbsd_putpages(void *v) else len = offhi - offlo; mutex_exit(vp->v_interlock); + if (curlwp == uvm.pagedaemon_lwp) { + error = fstrans_start_nowait(vp->v_mount); + if (error) + return error; + } else { + vfs_t *mp = vp->v_mount; + fstrans_start(mp); + if (vp->v_mount != mp) { + fstrans_done(mp); + ASSERT(!vn_has_cached_data(vp)); + return 0; + } + } rl = zfs_range_lock(zp, offlo, len, RL_WRITER); mutex_enter(vp->v_interlock); tsd_set(zfs_putpage_key, &cleaned); } error = genfs_putpages(v); - if (rl) { + if (cleaning) { tsd_set(zfs_putpage_key, NULL); zfs_range_unlock(rl); - } - /* - * Only zil_commit() if we cleaned something. - * This avoids deadlock if we're called from zfs_netbsd_setsize(). - */ + /* + * Only zil_commit() if we cleaned something. This avoids + * deadlock if we're called from zfs_netbsd_setsize(). + */ - if (cleaned) - if (!async || zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS) - zil_commit(zfsvfs->z_log, zp->z_id); - ZFS_EXIT(zfsvfs); + if (cleaned) + if (!async || zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS) + zil_commit(zfsvfs->z_log, zp->z_id); + fstrans_done(vp->v_mount); + } return error; }