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 --- |