Module Name:    src
Committed By:   ad
Date:           Wed Apr 22 21:35:52 UTC 2020

Modified Files:
        src/sys/kern: vfs_cache.c vfs_lookup.c

Log Message:
lookup_fastforward(): handle dotdot lookups and give up less often in
the union mount case.


To generate a diff of this commit:
cvs rdiff -u -r1.139 -r1.140 src/sys/kern/vfs_cache.c
cvs rdiff -u -r1.218 -r1.219 src/sys/kern/vfs_lookup.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/vfs_cache.c
diff -u src/sys/kern/vfs_cache.c:1.139 src/sys/kern/vfs_cache.c:1.140
--- src/sys/kern/vfs_cache.c:1.139	Mon Apr 13 19:23:18 2020
+++ src/sys/kern/vfs_cache.c	Wed Apr 22 21:35:52 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_cache.c,v 1.139 2020/04/13 19:23:18 ad Exp $	*/
+/*	$NetBSD: vfs_cache.c,v 1.140 2020/04/22 21:35:52 ad Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2019, 2020 The NetBSD Foundation, Inc.
@@ -172,7 +172,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_cache.c,v 1.139 2020/04/13 19:23:18 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_cache.c,v 1.140 2020/04/22 21:35:52 ad Exp $");
 
 #define __NAMECACHE_PRIVATE
 #ifdef _KERNEL_OPT
@@ -664,10 +664,17 @@ cache_lookup_linked(struct vnode *dvp, c
 	 * before we get its lock.
 	 *
 	 * Note that the two locks can be the same if looking up a dot, for
-	 * example: /usr/bin/.
+	 * example: /usr/bin/.  If looking up the parent (..) we can't wait
+	 * on the lock as child -> parent is the wrong direction.
 	 */
 	if (*plock != &dvi->vi_nc_lock) {
-		rw_enter(&dvi->vi_nc_lock, RW_READER);
+		if (namelen == 2 && name[0] == '.' && name[1] == '.') {
+			if (!rw_tryenter(&dvi->vi_nc_lock, RW_READER)) {
+				return false;
+			}
+		} else {
+			rw_enter(&dvi->vi_nc_lock, RW_READER);
+		}
 		if (*plock != NULL) {
 			rw_exit(*plock);
 		}

Index: src/sys/kern/vfs_lookup.c
diff -u src/sys/kern/vfs_lookup.c:1.218 src/sys/kern/vfs_lookup.c:1.219
--- src/sys/kern/vfs_lookup.c:1.218	Tue Apr 21 21:42:47 2020
+++ src/sys/kern/vfs_lookup.c	Wed Apr 22 21:35:52 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_lookup.c,v 1.218 2020/04/21 21:42:47 ad Exp $	*/
+/*	$NetBSD: vfs_lookup.c,v 1.219 2020/04/22 21:35:52 ad Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.218 2020/04/21 21:42:47 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.219 2020/04/22 21:35:52 ad Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_magiclinks.h"
@@ -1286,14 +1286,19 @@ lookup_fastforward(struct namei_state *s
 		}
 
 		/*
-		 * Can't deal with dotdot lookups, because it means lock
-		 * order reversal, and there are checks in lookup_once()
-		 * that need to be made.  Also check for missing mountpoints.
+		 * Can't deal with DOTDOT lookups if NOCROSSMOUNT or the
+		 * lookup is chrooted.
 		 */
-		if ((cnp->cn_flags & ISDOTDOT) != 0 ||
-		    searchdir->v_mount == NULL) {
-			error = EOPNOTSUPP;
-			break;
+		if ((cnp->cn_flags & ISDOTDOT) != 0) {
+			if ((searchdir->v_vflag & VV_ROOT) != 0 &&
+			    (cnp->cn_flags & NOCROSSMOUNT)) {
+			    	error = EOPNOTSUPP;
+				break;
+			}
+			if (ndp->ni_rootdir != rootvnode) {
+			    	error = EOPNOTSUPP;
+				break;
+			}
 		}
 
 		/*
@@ -1309,13 +1314,6 @@ lookup_fastforward(struct namei_state *s
 			}
 		}
 
-		/* Can't deal with -o union lookups. */
-		if ((searchdir->v_vflag & VV_ROOT) != 0 &&
-		    (searchdir->v_mount->mnt_flag & MNT_UNION) != 0) {
-		    	error = EOPNOTSUPP;
-		    	break;
-		}
-
 		/*
 		 * Good, now look for it in cache.  cache_lookup_linked()
 		 * will fail if there's nothing there, or if there's no
@@ -1329,9 +1327,18 @@ lookup_fastforward(struct namei_state *s
 		}
 		KASSERT(plock != NULL && rw_lock_held(plock));
 
-		/* Scored a hit.  Negative is good too (ENOENT). */
+		/*
+		 * Scored a hit.  Negative is good too (ENOENT).  If there's
+		 * a '-o union' mount here, punt and let lookup_once() deal
+		 * with it.
+		 */
 		if (foundobj == NULL) {
-			error = ENOENT;
+			if ((searchdir->v_vflag & VV_ROOT) != 0 &&
+			    (searchdir->v_mount->mnt_flag & MNT_UNION) != 0) {
+			    	error = EOPNOTSUPP;
+			} else {
+				error = ENOENT;
+			}
 			break;
 		}
 

Reply via email to