Thu Apr 23 22:58:36 2020 UTC ()
cache_lookup_linked(): We can't use the name to decide how to lock the dir,
since the name refers to the child (found object) not the parent (the thing
that's being locked).

Fix it by always doing rw_tryenter().  There's not much to be won by
optimising for the contended case, and were this routine doing lockless
lookups (the eventual goal) it wouldn't be hanging around waiting for
changes either.


(ad)
diff -r1.140 -r1.141 src/sys/kern/vfs_cache.c

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

--- src/sys/kern/vfs_cache.c 2020/04/22 21:35:52 1.140
+++ src/sys/kern/vfs_cache.c 2020/04/23 22:58:36 1.141
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: vfs_cache.c,v 1.140 2020/04/22 21:35:52 ad Exp $ */ 1/* $NetBSD: vfs_cache.c,v 1.141 2020/04/23 22:58:36 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.140 2020/04/22 21:35:52 ad Exp $"); 175__KERNEL_RCSID(0, "$NetBSD: vfs_cache.c,v 1.141 2020/04/23 22:58:36 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>
@@ -658,32 +658,28 @@ cache_lookup_linked(struct vnode *dvp, c @@ -658,32 +658,28 @@ cache_lookup_linked(struct vnode *dvp, c
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/. If looking up the parent (..) we can't wait 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 * on the lock as child -> parent is the wrong direction.
669 */ 669 */
670 if (*plock != &dvi->vi_nc_lock) { 670 if (*plock != &dvi->vi_nc_lock) {
671 if (namelen == 2 && name[0] == '.' && name[1] == '.') { 671 if (!rw_tryenter(&dvi->vi_nc_lock, RW_READER)) {
672 if (!rw_tryenter(&dvi->vi_nc_lock, RW_READER)) { 672 return false;
673 return false; 
674 } 
675 } else { 
676 rw_enter(&dvi->vi_nc_lock, RW_READER); 
677 } 673 }
678 if (*plock != NULL) { 674 if (*plock != NULL) {
679 rw_exit(*plock); 675 rw_exit(*plock);
680 } 676 }
681 *plock = &dvi->vi_nc_lock; 677 *plock = &dvi->vi_nc_lock;
682 } else if (*plock == NULL) { 678 } else if (*plock == NULL) {
683 KASSERT(vrefcnt(dvp) > 0); 679 KASSERT(vrefcnt(dvp) > 0);
684 } 680 }
685 681
686 /* 682 /*
687 * First up check if the user is allowed to look up files in this 683 * First up check if the user is allowed to look up files in this
688 * directory. 684 * directory.
689 */ 685 */