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;
 }
 

Reply via email to