Deleted Added
full compact
vfs_cache.c (230143) vfs_cache.c (230394)
1/*-
2 * Copyright (c) 1989, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Poul-Henning Kamp of the FreeBSD Project.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 19 unchanged lines hidden (view full) ---

28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * @(#)vfs_cache.c 8.5 (Berkeley) 3/22/95
33 */
34
35#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1989, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Poul-Henning Kamp of the FreeBSD Project.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 19 unchanged lines hidden (view full) ---

28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * @(#)vfs_cache.c 8.5 (Berkeley) 3/22/95
33 */
34
35#include <sys/cdefs.h>
36__FBSDID("$FreeBSD: head/sys/kern/vfs_cache.c 230143 2012-01-15 18:08:15Z mm $");
36__FBSDID("$FreeBSD: head/sys/kern/vfs_cache.c 230394 2012-01-20 20:02:01Z jhb $");
37
38#include "opt_kdtrace.h"
39#include "opt_ktrace.h"
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/filedesc.h>
44#include <sys/fnv_hash.h>

--- 47 unchanged lines hidden (view full) ---

92 */
93
94struct namecache {
95 LIST_ENTRY(namecache) nc_hash; /* hash chain */
96 LIST_ENTRY(namecache) nc_src; /* source vnode list */
97 TAILQ_ENTRY(namecache) nc_dst; /* destination vnode list */
98 struct vnode *nc_dvp; /* vnode of parent of name */
99 struct vnode *nc_vp; /* vnode the name refers to */
37
38#include "opt_kdtrace.h"
39#include "opt_ktrace.h"
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/filedesc.h>
44#include <sys/fnv_hash.h>

--- 47 unchanged lines hidden (view full) ---

92 */
93
94struct namecache {
95 LIST_ENTRY(namecache) nc_hash; /* hash chain */
96 LIST_ENTRY(namecache) nc_src; /* source vnode list */
97 TAILQ_ENTRY(namecache) nc_dst; /* destination vnode list */
98 struct vnode *nc_dvp; /* vnode of parent of name */
99 struct vnode *nc_vp; /* vnode the name refers to */
100 struct timespec nc_time; /* timespec provided by fs */
101 int nc_ticks; /* ticks value when entry was added */
100 u_char nc_flag; /* flag bits */
101 u_char nc_nlen; /* length of name */
102 char nc_name[0]; /* segment name + nul */
103};
104
105/*
106 * Name caching works as follows:
107 *

--- 281 unchanged lines hidden (view full) ---

389 * ENOENT is returned.
390 *
391 * vpp is locked and ref'd on return. If we're looking up DOTDOT, dvp is
392 * unlocked. If we're looking up . an extra ref is taken, but the lock is
393 * not recursively acquired.
394 */
395
396int
102 u_char nc_flag; /* flag bits */
103 u_char nc_nlen; /* length of name */
104 char nc_name[0]; /* segment name + nul */
105};
106
107/*
108 * Name caching works as follows:
109 *

--- 281 unchanged lines hidden (view full) ---

391 * ENOENT is returned.
392 *
393 * vpp is locked and ref'd on return. If we're looking up DOTDOT, dvp is
394 * unlocked. If we're looking up . an extra ref is taken, but the lock is
395 * not recursively acquired.
396 */
397
398int
397cache_lookup(dvp, vpp, cnp)
399cache_lookup_times(dvp, vpp, cnp, tsp, ticksp)
398 struct vnode *dvp;
399 struct vnode **vpp;
400 struct componentname *cnp;
400 struct vnode *dvp;
401 struct vnode **vpp;
402 struct componentname *cnp;
403 struct timespec *tsp;
404 int *ticksp;
401{
402 struct namecache *ncp;
403 uint32_t hash;
404 int error, ltype, wlocked;
405
406 if (!doingcache) {
407 cnp->cn_flags &= ~MAKEENTRY;
408 return (0);

--- 8 unchanged lines hidden (view full) ---

417 if (cnp->cn_nameptr[0] == '.') {
418 if (cnp->cn_namelen == 1) {
419 *vpp = dvp;
420 CTR2(KTR_VFS, "cache_lookup(%p, %s) found via .",
421 dvp, cnp->cn_nameptr);
422 dothits++;
423 SDT_PROBE(vfs, namecache, lookup, hit, dvp, ".",
424 *vpp, 0, 0);
405{
406 struct namecache *ncp;
407 uint32_t hash;
408 int error, ltype, wlocked;
409
410 if (!doingcache) {
411 cnp->cn_flags &= ~MAKEENTRY;
412 return (0);

--- 8 unchanged lines hidden (view full) ---

421 if (cnp->cn_nameptr[0] == '.') {
422 if (cnp->cn_namelen == 1) {
423 *vpp = dvp;
424 CTR2(KTR_VFS, "cache_lookup(%p, %s) found via .",
425 dvp, cnp->cn_nameptr);
426 dothits++;
427 SDT_PROBE(vfs, namecache, lookup, hit, dvp, ".",
428 *vpp, 0, 0);
429 if (tsp != NULL)
430 timespecclear(tsp);
431 if (ticksp != NULL)
432 *ticksp = ticks;
425 goto success;
426 }
427 if (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.') {
428 dotdothits++;
429 if (dvp->v_cache_dd == NULL) {
430 SDT_PROBE(vfs, namecache, lookup, miss, dvp,
431 "..", NULL, 0, 0);
432 goto unlock;
433 }
434 if ((cnp->cn_flags & MAKEENTRY) == 0) {
435 if (!wlocked && !CACHE_UPGRADE_LOCK())
436 goto wlock;
437 if (dvp->v_cache_dd->nc_flag & NCF_ISDOTDOT)
438 cache_zap(dvp->v_cache_dd);
439 dvp->v_cache_dd = NULL;
440 CACHE_WUNLOCK();
441 return (0);
442 }
433 goto success;
434 }
435 if (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.') {
436 dotdothits++;
437 if (dvp->v_cache_dd == NULL) {
438 SDT_PROBE(vfs, namecache, lookup, miss, dvp,
439 "..", NULL, 0, 0);
440 goto unlock;
441 }
442 if ((cnp->cn_flags & MAKEENTRY) == 0) {
443 if (!wlocked && !CACHE_UPGRADE_LOCK())
444 goto wlock;
445 if (dvp->v_cache_dd->nc_flag & NCF_ISDOTDOT)
446 cache_zap(dvp->v_cache_dd);
447 dvp->v_cache_dd = NULL;
448 CACHE_WUNLOCK();
449 return (0);
450 }
443 if (dvp->v_cache_dd->nc_flag & NCF_ISDOTDOT)
444 *vpp = dvp->v_cache_dd->nc_vp;
451 ncp = dvp->v_cache_dd;
452 if (ncp->nc_flag & NCF_ISDOTDOT)
453 *vpp = ncp->nc_vp;
445 else
454 else
446 *vpp = dvp->v_cache_dd->nc_dvp;
455 *vpp = ncp->nc_dvp;
447 /* Return failure if negative entry was found. */
456 /* Return failure if negative entry was found. */
448 if (*vpp == NULL) {
449 ncp = dvp->v_cache_dd;
457 if (*vpp == NULL)
450 goto negative_success;
458 goto negative_success;
451 }
452 CTR3(KTR_VFS, "cache_lookup(%p, %s) found %p via ..",
453 dvp, cnp->cn_nameptr, *vpp);
454 SDT_PROBE(vfs, namecache, lookup, hit, dvp, "..",
455 *vpp, 0, 0);
459 CTR3(KTR_VFS, "cache_lookup(%p, %s) found %p via ..",
460 dvp, cnp->cn_nameptr, *vpp);
461 SDT_PROBE(vfs, namecache, lookup, hit, dvp, "..",
462 *vpp, 0, 0);
463 if (tsp != NULL)
464 *tsp = ncp->nc_time;
465 if (ticksp != NULL)
466 *ticksp = ncp->nc_ticks;
456 goto success;
457 }
458 }
459
460 hash = fnv_32_buf(cnp->cn_nameptr, cnp->cn_namelen, FNV1_32_INIT);
461 hash = fnv_32_buf(&dvp, sizeof(dvp), hash);
462 LIST_FOREACH(ncp, (NCHHASH(hash)), nc_hash) {
463 numchecks++;

--- 30 unchanged lines hidden (view full) ---

494 if (ncp->nc_vp) {
495 numposhits++;
496 nchstats.ncs_goodhits++;
497 *vpp = ncp->nc_vp;
498 CTR4(KTR_VFS, "cache_lookup(%p, %s) found %p via ncp %p",
499 dvp, cnp->cn_nameptr, *vpp, ncp);
500 SDT_PROBE(vfs, namecache, lookup, hit, dvp, ncp->nc_name,
501 *vpp, 0, 0);
467 goto success;
468 }
469 }
470
471 hash = fnv_32_buf(cnp->cn_nameptr, cnp->cn_namelen, FNV1_32_INIT);
472 hash = fnv_32_buf(&dvp, sizeof(dvp), hash);
473 LIST_FOREACH(ncp, (NCHHASH(hash)), nc_hash) {
474 numchecks++;

--- 30 unchanged lines hidden (view full) ---

505 if (ncp->nc_vp) {
506 numposhits++;
507 nchstats.ncs_goodhits++;
508 *vpp = ncp->nc_vp;
509 CTR4(KTR_VFS, "cache_lookup(%p, %s) found %p via ncp %p",
510 dvp, cnp->cn_nameptr, *vpp, ncp);
511 SDT_PROBE(vfs, namecache, lookup, hit, dvp, ncp->nc_name,
512 *vpp, 0, 0);
513 if (tsp != NULL)
514 *tsp = ncp->nc_time;
515 if (ticksp != NULL)
516 *ticksp = ncp->nc_ticks;
502 goto success;
503 }
504
505negative_success:
506 /* We found a negative match, and want to create it, so purge */
507 if (cnp->cn_nameiop == CREATE) {
508 numnegzaps++;
509 nchstats.ncs_badhits++;

--- 15 unchanged lines hidden (view full) ---

525 */
526 TAILQ_REMOVE(&ncneg, ncp, nc_dst);
527 TAILQ_INSERT_TAIL(&ncneg, ncp, nc_dst);
528 nchstats.ncs_neghits++;
529 if (ncp->nc_flag & NCF_WHITE)
530 cnp->cn_flags |= ISWHITEOUT;
531 SDT_PROBE(vfs, namecache, lookup, hit_negative, dvp, ncp->nc_name,
532 0, 0, 0);
517 goto success;
518 }
519
520negative_success:
521 /* We found a negative match, and want to create it, so purge */
522 if (cnp->cn_nameiop == CREATE) {
523 numnegzaps++;
524 nchstats.ncs_badhits++;

--- 15 unchanged lines hidden (view full) ---

540 */
541 TAILQ_REMOVE(&ncneg, ncp, nc_dst);
542 TAILQ_INSERT_TAIL(&ncneg, ncp, nc_dst);
543 nchstats.ncs_neghits++;
544 if (ncp->nc_flag & NCF_WHITE)
545 cnp->cn_flags |= ISWHITEOUT;
546 SDT_PROBE(vfs, namecache, lookup, hit_negative, dvp, ncp->nc_name,
547 0, 0, 0);
548 if (tsp != NULL)
549 *tsp = ncp->nc_time;
550 if (ticksp != NULL)
551 *ticksp = ncp->nc_ticks;
533 CACHE_WUNLOCK();
534 return (ENOENT);
535
536wlock:
537 /*
538 * We need to update the cache after our lookup, so upgrade to
539 * a write lock and retry the operation.
540 */

--- 70 unchanged lines hidden (view full) ---

611 CACHE_RUNLOCK();
612 return (0);
613}
614
615/*
616 * Add an entry to the cache.
617 */
618void
552 CACHE_WUNLOCK();
553 return (ENOENT);
554
555wlock:
556 /*
557 * We need to update the cache after our lookup, so upgrade to
558 * a write lock and retry the operation.
559 */

--- 70 unchanged lines hidden (view full) ---

630 CACHE_RUNLOCK();
631 return (0);
632}
633
634/*
635 * Add an entry to the cache.
636 */
637void
619cache_enter(dvp, vp, cnp)
638cache_enter_time(dvp, vp, cnp, tsp)
620 struct vnode *dvp;
621 struct vnode *vp;
622 struct componentname *cnp;
639 struct vnode *dvp;
640 struct vnode *vp;
641 struct componentname *cnp;
642 struct timespec *tsp;
623{
624 struct namecache *ncp, *n2;
625 struct nchashhead *ncpp;
626 uint32_t hash;
627 int flag;
628 int hold;
629 int zap;
630 int len;

--- 56 unchanged lines hidden (view full) ---

687 /*
688 * Calculate the hash key and setup as much of the new
689 * namecache entry as possible before acquiring the lock.
690 */
691 ncp = cache_alloc(cnp->cn_namelen);
692 ncp->nc_vp = vp;
693 ncp->nc_dvp = dvp;
694 ncp->nc_flag = flag;
643{
644 struct namecache *ncp, *n2;
645 struct nchashhead *ncpp;
646 uint32_t hash;
647 int flag;
648 int hold;
649 int zap;
650 int len;

--- 56 unchanged lines hidden (view full) ---

707 /*
708 * Calculate the hash key and setup as much of the new
709 * namecache entry as possible before acquiring the lock.
710 */
711 ncp = cache_alloc(cnp->cn_namelen);
712 ncp->nc_vp = vp;
713 ncp->nc_dvp = dvp;
714 ncp->nc_flag = flag;
715 if (tsp != NULL)
716 ncp->nc_time = *tsp;
717 else
718 timespecclear(&ncp->nc_time);
719 ncp->nc_ticks = ticks;
695 len = ncp->nc_nlen = cnp->cn_namelen;
696 hash = fnv_32_buf(cnp->cn_nameptr, len, FNV1_32_INIT);
697 strlcpy(ncp->nc_name, cnp->cn_nameptr, len + 1);
698 hash = fnv_32_buf(&dvp, sizeof(dvp), hash);
699 CACHE_WLOCK();
700
701 /*
702 * See if this vnode or negative entry is already in the cache
703 * with this name. This can happen with concurrent lookups of
704 * the same path name.
705 */
706 ncpp = NCHHASH(hash);
707 LIST_FOREACH(n2, ncpp, nc_hash) {
708 if (n2->nc_dvp == dvp &&
709 n2->nc_nlen == cnp->cn_namelen &&
710 !bcmp(n2->nc_name, cnp->cn_nameptr, n2->nc_nlen)) {
720 len = ncp->nc_nlen = cnp->cn_namelen;
721 hash = fnv_32_buf(cnp->cn_nameptr, len, FNV1_32_INIT);
722 strlcpy(ncp->nc_name, cnp->cn_nameptr, len + 1);
723 hash = fnv_32_buf(&dvp, sizeof(dvp), hash);
724 CACHE_WLOCK();
725
726 /*
727 * See if this vnode or negative entry is already in the cache
728 * with this name. This can happen with concurrent lookups of
729 * the same path name.
730 */
731 ncpp = NCHHASH(hash);
732 LIST_FOREACH(n2, ncpp, nc_hash) {
733 if (n2->nc_dvp == dvp &&
734 n2->nc_nlen == cnp->cn_namelen &&
735 !bcmp(n2->nc_name, cnp->cn_nameptr, n2->nc_nlen)) {
736 n2->nc_time = ncp->nc_time;
737 n2->nc_ticks = ncp->nc_ticks;
711 CACHE_WUNLOCK();
712 cache_free(ncp);
713 return;
714 }
715 }
716
717 if (flag == NCF_ISDOTDOT) {
718 /*

--- 556 unchanged lines hidden (view full) ---

1275 }
1276 l = min(ncp->nc_nlen, buflen - 1);
1277 memcpy(buf, ncp->nc_name, l);
1278 CACHE_RUNLOCK();
1279 buf[l] = '\0';
1280 return (0);
1281}
1282
738 CACHE_WUNLOCK();
739 cache_free(ncp);
740 return;
741 }
742 }
743
744 if (flag == NCF_ISDOTDOT) {
745 /*

--- 556 unchanged lines hidden (view full) ---

1302 }
1303 l = min(ncp->nc_nlen, buflen - 1);
1304 memcpy(buf, ncp->nc_name, l);
1305 CACHE_RUNLOCK();
1306 buf[l] = '\0';
1307 return (0);
1308}
1309
1310/* ABI compat shims for old kernel modules. */
1311#undef cache_enter
1312#undef cache_lookup
1313
1314void cache_enter(struct vnode *dvp, struct vnode *vp,
1315 struct componentname *cnp);
1316int cache_lookup(struct vnode *dvp, struct vnode **vpp,
1317 struct componentname *cnp);
1318
1319void
1320cache_enter(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
1321{
1322
1323 cache_enter_time(dvp, vp, cnp, NULL);
1324}
1325
1326int
1327cache_lookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp)
1328{
1329
1330 return (cache_lookup_times(dvp, vpp, cnp, NULL, NULL));
1331}
1332
1283/*
1284 * This function updates path string to vnode's full global path
1285 * and checks the size of the new path string against the pathlen argument.
1286 *
1287 * Requires a locked, referenced vnode and GIANT lock held.
1288 * Vnode is re-locked on success or ENODEV, otherwise unlocked.
1289 *
1290 * If sysctl debug.disablefullpath is set, ENODEV is returned,

--- 64 unchanged lines hidden ---
1333/*
1334 * This function updates path string to vnode's full global path
1335 * and checks the size of the new path string against the pathlen argument.
1336 *
1337 * Requires a locked, referenced vnode and GIANT lock held.
1338 * Vnode is re-locked on success or ENODEV, otherwise unlocked.
1339 *
1340 * If sysctl debug.disablefullpath is set, ENODEV is returned,

--- 64 unchanged lines hidden ---