svn commit: r366582 - in head/sys: fs/deadfs kern

Mateusz Guzik mjg at FreeBSD.org
Fri Oct 9 19:10:01 UTC 2020


Author: mjg
Date: Fri Oct  9 19:10:00 2020
New Revision: 366582
URL: https://svnweb.freebsd.org/changeset/base/366582

Log:
  cache: fix vexec panic when racing against vgone
  
  Use of dead_vnodeops would result in a panic instead of returning the intended
  EOPNOTSUPP error.
  
  While here make sure to abort, not just try to return a partial result.
  The former allows the regular lookup to restart from scratch, while the latter
  makes it stuck with an unusable vnode.
  
  Reported by:	kevans

Modified:
  head/sys/fs/deadfs/dead_vnops.c
  head/sys/kern/vfs_cache.c

Modified: head/sys/fs/deadfs/dead_vnops.c
==============================================================================
--- head/sys/fs/deadfs/dead_vnops.c	Fri Oct  9 18:30:49 2020	(r366581)
+++ head/sys/fs/deadfs/dead_vnops.c	Fri Oct  9 19:10:00 2020	(r366582)
@@ -79,6 +79,7 @@ struct vop_vector dead_vnodeops = {
 	.vop_vptocnp =		VOP_EBADF,
 	.vop_unset_text =	dead_unset_text,
 	.vop_write =		dead_write,
+	.vop_fplookup_vexec =	VOP_EOPNOTSUPP,
 };
 VFS_VOP_VECTOR_REGISTER(dead_vnodeops);
 

Modified: head/sys/kern/vfs_cache.c
==============================================================================
--- head/sys/kern/vfs_cache.c	Fri Oct  9 18:30:49 2020	(r366581)
+++ head/sys/kern/vfs_cache.c	Fri Oct  9 19:10:00 2020	(r366582)
@@ -4040,32 +4040,46 @@ cache_fplookup_parse_advance(struct cache_fpl *fpl)
 	}
 }
 
+/*
+ * See the API contract for VOP_FPLOOKUP_VEXEC.
+ */
 static int __noinline
 cache_fplookup_failed_vexec(struct cache_fpl *fpl, int error)
 {
+	struct vnode *dvp;
+	seqc_t dvp_seqc;
 
+	dvp = fpl->dvp;
+	dvp_seqc = fpl->dvp_seqc;
+
 	/*
 	 * Hack: they may be looking up foo/bar, where foo is a
 	 * regular file. In such a case we need to turn ENOTDIR,
 	 * but we may happen to get here with a different error.
 	 */
-	if (fpl->dvp->v_type != VDIR) {
+	if (dvp->v_type != VDIR) {
+		/*
+		 * The check here is predominantly to catch
+		 * EOPNOTSUPP from dead_vnodeops. If the vnode
+		 * gets doomed past this point it is going to
+		 * fail seqc verification.
+		 */
+		if (VN_IS_DOOMED(dvp)) {
+			return (cache_fpl_aborted(fpl));
+		}
 		error = ENOTDIR;
 	}
 
 	switch (error) {
 	case EAGAIN:
-		/*
-		 * Can happen when racing against vgone.
-		 * */
-	case EOPNOTSUPP:
-		cache_fpl_partial(fpl);
+		if (!vn_seqc_consistent(dvp, dvp_seqc)) {
+			error = cache_fpl_aborted(fpl);
+		} else {
+			cache_fpl_partial(fpl);
+		}
 		break;
 	default:
-		/*
-		 * See the API contract for VOP_FPLOOKUP_VEXEC.
-		 */
-		if (!vn_seqc_consistent(fpl->dvp, fpl->dvp_seqc)) {
+		if (!vn_seqc_consistent(dvp, dvp_seqc)) {
 			error = cache_fpl_aborted(fpl);
 		} else {
 			cache_fpl_smr_exit(fpl);


More information about the svn-src-all mailing list