Wed Apr 22 21:35:52 2020 UTC ()
lookup_fastforward(): handle dotdot lookups and give up less often in
the union mount case.


(ad)
diff -r1.139 -r1.140 src/sys/kern/vfs_cache.c
diff -r1.218 -r1.219 src/sys/kern/vfs_lookup.c

cvs diff -r1.139 -r1.140 src/sys/kern/vfs_cache.c (expand / switch to unified diff)

--- src/sys/kern/vfs_cache.c 2020/04/13 19:23:18 1.139
+++ src/sys/kern/vfs_cache.c 2020/04/22 21:35:52 1.140
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: vfs_cache.c,v 1.139 2020/04/13 19:23:18 ad Exp $ */ 1/* $NetBSD: vfs_cache.c,v 1.140 2020/04/22 21:35:52 ad Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2008, 2019, 2020 The NetBSD Foundation, Inc. 4 * Copyright (c) 2008, 2019, 2020 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran. 8 * by Andrew Doran.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -162,27 +162,27 @@ @@ -162,27 +162,27 @@
162 * 162 *
163 * 1) vi->vi_nc_lock (tree or parent -> child direction, 163 * 1) vi->vi_nc_lock (tree or parent -> child direction,
164 * used during forward lookup) 164 * used during forward lookup)
165 * 165 *
166 * 2) vi->vi_nc_listlock (list or child -> parent direction, 166 * 2) vi->vi_nc_listlock (list or child -> parent direction,
167 * used during reverse lookup) 167 * used during reverse lookup)
168 * 168 *
169 * 3) cache_lru_lock (LRU list direction, used during reclaim) 169 * 3) cache_lru_lock (LRU list direction, used during reclaim)
170 * 170 *
171 * 4) vp->v_interlock (what the cache entry points to) 171 * 4) vp->v_interlock (what the cache entry points to)
172 */ 172 */
173 173
174#include <sys/cdefs.h> 174#include <sys/cdefs.h>
175__KERNEL_RCSID(0, "$NetBSD: vfs_cache.c,v 1.139 2020/04/13 19:23:18 ad Exp $"); 175__KERNEL_RCSID(0, "$NetBSD: vfs_cache.c,v 1.140 2020/04/22 21:35:52 ad Exp $");
176 176
177#define __NAMECACHE_PRIVATE 177#define __NAMECACHE_PRIVATE
178#ifdef _KERNEL_OPT 178#ifdef _KERNEL_OPT
179#include "opt_ddb.h" 179#include "opt_ddb.h"
180#include "opt_dtrace.h" 180#include "opt_dtrace.h"
181#endif 181#endif
182 182
183#include <sys/types.h> 183#include <sys/types.h>
184#include <sys/atomic.h> 184#include <sys/atomic.h>
185#include <sys/callout.h> 185#include <sys/callout.h>
186#include <sys/cpu.h> 186#include <sys/cpu.h>
187#include <sys/errno.h> 187#include <sys/errno.h>
188#include <sys/evcnt.h> 188#include <sys/evcnt.h>
@@ -654,30 +654,37 @@ cache_lookup_linked(struct vnode *dvp, c @@ -654,30 +654,37 @@ cache_lookup_linked(struct vnode *dvp, c
654 * Acquire the directory lock. Once we have that, we can drop the 654 * Acquire the directory lock. Once we have that, we can drop the
655 * previous one (if any). 655 * previous one (if any).
656 * 656 *
657 * The two lock holds mean that the directory can't go away while 657 * The two lock holds mean that the directory can't go away while
658 * here: the directory must be purged with cache_purge() before 658 * here: the directory must be purged with cache_purge() before
659 * being freed, and both parent & child's vi_nc_lock must be taken 659 * being freed, and both parent & child's vi_nc_lock must be taken
660 * before that point is passed. 660 * before that point is passed.
661 * 661 *
662 * However if there's no previous lock, like at the root of the 662 * However if there's no previous lock, like at the root of the
663 * chain, then "dvp" must be referenced to prevent dvp going away 663 * chain, then "dvp" must be referenced to prevent dvp going away
664 * before we get its lock. 664 * before we get its lock.
665 * 665 *
666 * Note that the two locks can be the same if looking up a dot, for 666 * Note that the two locks can be the same if looking up a dot, for
667 * example: /usr/bin/. 667 * example: /usr/bin/. If looking up the parent (..) we can't wait
 668 * on the lock as child -> parent is the wrong direction.
668 */ 669 */
669 if (*plock != &dvi->vi_nc_lock) { 670 if (*plock != &dvi->vi_nc_lock) {
670 rw_enter(&dvi->vi_nc_lock, RW_READER); 671 if (namelen == 2 && name[0] == '.' && name[1] == '.') {
 672 if (!rw_tryenter(&dvi->vi_nc_lock, RW_READER)) {
 673 return false;
 674 }
 675 } else {
 676 rw_enter(&dvi->vi_nc_lock, RW_READER);
 677 }
671 if (*plock != NULL) { 678 if (*plock != NULL) {
672 rw_exit(*plock); 679 rw_exit(*plock);
673 } 680 }
674 *plock = &dvi->vi_nc_lock; 681 *plock = &dvi->vi_nc_lock;
675 } else if (*plock == NULL) { 682 } else if (*plock == NULL) {
676 KASSERT(vrefcnt(dvp) > 0); 683 KASSERT(vrefcnt(dvp) > 0);
677 } 684 }
678 685
679 /* 686 /*
680 * First up check if the user is allowed to look up files in this 687 * First up check if the user is allowed to look up files in this
681 * directory. 688 * directory.
682 */ 689 */
683 KASSERT(dvi->vi_nc_mode != VNOVAL && dvi->vi_nc_uid != VNOVAL && 690 KASSERT(dvi->vi_nc_mode != VNOVAL && dvi->vi_nc_uid != VNOVAL &&

cvs diff -r1.218 -r1.219 src/sys/kern/vfs_lookup.c (expand / switch to unified diff)

--- src/sys/kern/vfs_lookup.c 2020/04/21 21:42:47 1.218
+++ src/sys/kern/vfs_lookup.c 2020/04/22 21:35:52 1.219
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: vfs_lookup.c,v 1.218 2020/04/21 21:42:47 ad Exp $ */ 1/* $NetBSD: vfs_lookup.c,v 1.219 2020/04/22 21:35:52 ad Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1982, 1986, 1989, 1993 4 * Copyright (c) 1982, 1986, 1989, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * (c) UNIX System Laboratories, Inc. 6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed 7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph 8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc. 10 * the permission of UNIX System Laboratories, Inc.
11 * 11 *
12 * Redistribution and use in source and binary forms, with or without 12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions 13 * modification, are permitted provided that the following conditions
14 * are met: 14 * are met:
@@ -27,27 +27,27 @@ @@ -27,27 +27,27 @@
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE. 34 * SUCH DAMAGE.
35 * 35 *
36 * @(#)vfs_lookup.c 8.10 (Berkeley) 5/27/95 36 * @(#)vfs_lookup.c 8.10 (Berkeley) 5/27/95
37 */ 37 */
38 38
39#include <sys/cdefs.h> 39#include <sys/cdefs.h>
40__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.218 2020/04/21 21:42:47 ad Exp $"); 40__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.219 2020/04/22 21:35:52 ad Exp $");
41 41
42#ifdef _KERNEL_OPT 42#ifdef _KERNEL_OPT
43#include "opt_magiclinks.h" 43#include "opt_magiclinks.h"
44#endif 44#endif
45 45
46#include <sys/param.h> 46#include <sys/param.h>
47#include <sys/systm.h> 47#include <sys/systm.h>
48#include <sys/kernel.h> 48#include <sys/kernel.h>
49#include <sys/syslimits.h> 49#include <sys/syslimits.h>
50#include <sys/time.h> 50#include <sys/time.h>
51#include <sys/namei.h> 51#include <sys/namei.h>
52#include <sys/vnode.h> 52#include <sys/vnode.h>
53#include <sys/vnode_impl.h> 53#include <sys/vnode_impl.h>
@@ -1276,72 +1276,79 @@ lookup_fastforward(struct namei_state *s @@ -1276,72 +1276,79 @@ lookup_fastforward(struct namei_state *s
1276 1276
1277 /* 1277 /*
1278 * Get the next component name. There should be no slashes 1278 * Get the next component name. There should be no slashes
1279 * here, and we shouldn't have looped around if we were 1279 * here, and we shouldn't have looped around if we were
1280 * done. 1280 * done.
1281 */ 1281 */
1282 KASSERT(cnp->cn_nameptr[0] != '/'); 1282 KASSERT(cnp->cn_nameptr[0] != '/');
1283 KASSERT(cnp->cn_nameptr[0] != '\0'); 1283 KASSERT(cnp->cn_nameptr[0] != '\0');
1284 if ((error = lookup_parsepath(state)) != 0) { 1284 if ((error = lookup_parsepath(state)) != 0) {
1285 break; 1285 break;
1286 } 1286 }
1287 1287
1288 /* 1288 /*
1289 * Can't deal with dotdot lookups, because it means lock 1289 * Can't deal with DOTDOT lookups if NOCROSSMOUNT or the
1290 * order reversal, and there are checks in lookup_once() 1290 * lookup is chrooted.
1291 * that need to be made. Also check for missing mountpoints. 
1292 */ 1291 */
1293 if ((cnp->cn_flags & ISDOTDOT) != 0 || 1292 if ((cnp->cn_flags & ISDOTDOT) != 0) {
1294 searchdir->v_mount == NULL) { 1293 if ((searchdir->v_vflag & VV_ROOT) != 0 &&
1295 error = EOPNOTSUPP; 1294 (cnp->cn_flags & NOCROSSMOUNT)) {
1296 break; 1295 error = EOPNOTSUPP;
 1296 break;
 1297 }
 1298 if (ndp->ni_rootdir != rootvnode) {
 1299 error = EOPNOTSUPP;
 1300 break;
 1301 }
1297 } 1302 }
1298 1303
1299 /* 1304 /*
1300 * Can't deal with last component when modifying; this needs 1305 * Can't deal with last component when modifying; this needs
1301 * searchdir locked and VOP_LOOKUP() called (which can and 1306 * searchdir locked and VOP_LOOKUP() called (which can and
1302 * does modify state, despite the name). 1307 * does modify state, despite the name).
1303 */ 1308 */
1304 if ((cnp->cn_flags & ISLASTCN) != 0) { 1309 if ((cnp->cn_flags & ISLASTCN) != 0) {
1305 if (cnp->cn_nameiop != LOOKUP || 1310 if (cnp->cn_nameiop != LOOKUP ||
1306 (cnp->cn_flags & LOCKPARENT) != 0) { 1311 (cnp->cn_flags & LOCKPARENT) != 0) {
1307 error = EOPNOTSUPP; 1312 error = EOPNOTSUPP;
1308 break; 1313 break;
1309 } 1314 }
1310 } 1315 }
1311 1316
1312 /* Can't deal with -o union lookups. */ 
1313 if ((searchdir->v_vflag & VV_ROOT) != 0 && 
1314 (searchdir->v_mount->mnt_flag & MNT_UNION) != 0) { 
1315 error = EOPNOTSUPP; 
1316 break; 
1317 } 
1318 
1319 /* 1317 /*
1320 * Good, now look for it in cache. cache_lookup_linked() 1318 * Good, now look for it in cache. cache_lookup_linked()
1321 * will fail if there's nothing there, or if there's no 1319 * will fail if there's nothing there, or if there's no
1322 * ownership info for the directory, or if the user doesn't 1320 * ownership info for the directory, or if the user doesn't
1323 * have permission to look up files in this directory. 1321 * have permission to look up files in this directory.
1324 */ 1322 */
1325 if (!cache_lookup_linked(searchdir, cnp->cn_nameptr, 1323 if (!cache_lookup_linked(searchdir, cnp->cn_nameptr,
1326 cnp->cn_namelen, &foundobj, &plock, cnp->cn_cred)) { 1324 cnp->cn_namelen, &foundobj, &plock, cnp->cn_cred)) {
1327 error = EOPNOTSUPP; 1325 error = EOPNOTSUPP;
1328 break; 1326 break;
1329 } 1327 }
1330 KASSERT(plock != NULL && rw_lock_held(plock)); 1328 KASSERT(plock != NULL && rw_lock_held(plock));
1331 1329
1332 /* Scored a hit. Negative is good too (ENOENT). */ 1330 /*
 1331 * Scored a hit. Negative is good too (ENOENT). If there's
 1332 * a '-o union' mount here, punt and let lookup_once() deal
 1333 * with it.
 1334 */
1333 if (foundobj == NULL) { 1335 if (foundobj == NULL) {
1334 error = ENOENT; 1336 if ((searchdir->v_vflag & VV_ROOT) != 0 &&
 1337 (searchdir->v_mount->mnt_flag & MNT_UNION) != 0) {
 1338 error = EOPNOTSUPP;
 1339 } else {
 1340 error = ENOENT;
 1341 }
1335 break; 1342 break;
1336 } 1343 }
1337 1344
1338 /* 1345 /*
1339 * Stop and get a hold on the vnode if there's something 1346 * Stop and get a hold on the vnode if there's something
1340 * that can't be handled here: 1347 * that can't be handled here:
1341 * 1348 *
1342 * - we've reached the last component. 1349 * - we've reached the last component.
1343 * - or encountered a mount point that needs to be crossed. 1350 * - or encountered a mount point that needs to be crossed.
1344 * - or encountered something other than a directory. 1351 * - or encountered something other than a directory.
1345 */ 1352 */
1346 if ((cnp->cn_flags & ISLASTCN) != 0 || 1353 if ((cnp->cn_flags & ISLASTCN) != 0 ||
1347 foundobj->v_type != VDIR || 1354 foundobj->v_type != VDIR ||