diff options
Diffstat (limited to 'fs/dcache.c')
-rw-r--r-- | fs/dcache.c | 111 |
1 files changed, 37 insertions, 74 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index d30ce699ae4b..cb25a1a5e307 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -106,8 +106,7 @@ static inline struct hlist_bl_head *d_hash(const struct dentry *parent, | |||
106 | unsigned int hash) | 106 | unsigned int hash) |
107 | { | 107 | { |
108 | hash += (unsigned long) parent / L1_CACHE_BYTES; | 108 | hash += (unsigned long) parent / L1_CACHE_BYTES; |
109 | hash = hash + (hash >> d_hash_shift); | 109 | return dentry_hashtable + hash_32(hash, d_hash_shift); |
110 | return dentry_hashtable + (hash & d_hash_mask); | ||
111 | } | 110 | } |
112 | 111 | ||
113 | /* Statistics gathering. */ | 112 | /* Statistics gathering. */ |
@@ -2373,7 +2372,8 @@ void dentry_update_name_case(struct dentry *dentry, struct qstr *name) | |||
2373 | } | 2372 | } |
2374 | EXPORT_SYMBOL(dentry_update_name_case); | 2373 | EXPORT_SYMBOL(dentry_update_name_case); |
2375 | 2374 | ||
2376 | static void switch_names(struct dentry *dentry, struct dentry *target) | 2375 | static void switch_names(struct dentry *dentry, struct dentry *target, |
2376 | bool exchange) | ||
2377 | { | 2377 | { |
2378 | if (dname_external(target)) { | 2378 | if (dname_external(target)) { |
2379 | if (dname_external(dentry)) { | 2379 | if (dname_external(dentry)) { |
@@ -2407,13 +2407,19 @@ static void switch_names(struct dentry *dentry, struct dentry *target) | |||
2407 | */ | 2407 | */ |
2408 | unsigned int i; | 2408 | unsigned int i; |
2409 | BUILD_BUG_ON(!IS_ALIGNED(DNAME_INLINE_LEN, sizeof(long))); | 2409 | BUILD_BUG_ON(!IS_ALIGNED(DNAME_INLINE_LEN, sizeof(long))); |
2410 | if (!exchange) { | ||
2411 | memcpy(dentry->d_iname, target->d_name.name, | ||
2412 | target->d_name.len + 1); | ||
2413 | dentry->d_name.hash_len = target->d_name.hash_len; | ||
2414 | return; | ||
2415 | } | ||
2410 | for (i = 0; i < DNAME_INLINE_LEN / sizeof(long); i++) { | 2416 | for (i = 0; i < DNAME_INLINE_LEN / sizeof(long); i++) { |
2411 | swap(((long *) &dentry->d_iname)[i], | 2417 | swap(((long *) &dentry->d_iname)[i], |
2412 | ((long *) &target->d_iname)[i]); | 2418 | ((long *) &target->d_iname)[i]); |
2413 | } | 2419 | } |
2414 | } | 2420 | } |
2415 | } | 2421 | } |
2416 | swap(dentry->d_name.len, target->d_name.len); | 2422 | swap(dentry->d_name.hash_len, target->d_name.hash_len); |
2417 | } | 2423 | } |
2418 | 2424 | ||
2419 | static void dentry_lock_for_move(struct dentry *dentry, struct dentry *target) | 2425 | static void dentry_lock_for_move(struct dentry *dentry, struct dentry *target) |
@@ -2443,25 +2449,29 @@ static void dentry_lock_for_move(struct dentry *dentry, struct dentry *target) | |||
2443 | } | 2449 | } |
2444 | } | 2450 | } |
2445 | 2451 | ||
2446 | static void dentry_unlock_parents_for_move(struct dentry *dentry, | 2452 | static void dentry_unlock_for_move(struct dentry *dentry, struct dentry *target) |
2447 | struct dentry *target) | ||
2448 | { | 2453 | { |
2449 | if (target->d_parent != dentry->d_parent) | 2454 | if (target->d_parent != dentry->d_parent) |
2450 | spin_unlock(&dentry->d_parent->d_lock); | 2455 | spin_unlock(&dentry->d_parent->d_lock); |
2451 | if (target->d_parent != target) | 2456 | if (target->d_parent != target) |
2452 | spin_unlock(&target->d_parent->d_lock); | 2457 | spin_unlock(&target->d_parent->d_lock); |
2458 | spin_unlock(&target->d_lock); | ||
2459 | spin_unlock(&dentry->d_lock); | ||
2453 | } | 2460 | } |
2454 | 2461 | ||
2455 | /* | 2462 | /* |
2456 | * When switching names, the actual string doesn't strictly have to | 2463 | * When switching names, the actual string doesn't strictly have to |
2457 | * be preserved in the target - because we're dropping the target | 2464 | * be preserved in the target - because we're dropping the target |
2458 | * anyway. As such, we can just do a simple memcpy() to copy over | 2465 | * anyway. As such, we can just do a simple memcpy() to copy over |
2459 | * the new name before we switch. | 2466 | * the new name before we switch, unless we are going to rehash |
2460 | * | 2467 | * it. Note that if we *do* unhash the target, we are not allowed |
2461 | * Note that we have to be a lot more careful about getting the hash | 2468 | * to rehash it without giving it a new name/hash key - whether |
2462 | * switched - we have to switch the hash value properly even if it | 2469 | * we swap or overwrite the names here, resulting name won't match |
2463 | * then no longer matches the actual (corrupted) string of the target. | 2470 | * the reality in filesystem; it's only there for d_path() purposes. |
2464 | * The hash value has to match the hash queue that the dentry is on.. | 2471 | * Note that all of this is happening under rename_lock, so the |
2472 | * any hash lookup seeing it in the middle of manipulations will | ||
2473 | * be discarded anyway. So we do not care what happens to the hash | ||
2474 | * key in that case. | ||
2465 | */ | 2475 | */ |
2466 | /* | 2476 | /* |
2467 | * __d_move - move a dentry | 2477 | * __d_move - move a dentry |
@@ -2507,36 +2517,30 @@ static void __d_move(struct dentry *dentry, struct dentry *target, | |||
2507 | d_hash(dentry->d_parent, dentry->d_name.hash)); | 2517 | d_hash(dentry->d_parent, dentry->d_name.hash)); |
2508 | } | 2518 | } |
2509 | 2519 | ||
2510 | list_del(&dentry->d_u.d_child); | ||
2511 | list_del(&target->d_u.d_child); | ||
2512 | |||
2513 | /* Switch the names.. */ | 2520 | /* Switch the names.. */ |
2514 | switch_names(dentry, target); | 2521 | switch_names(dentry, target, exchange); |
2515 | swap(dentry->d_name.hash, target->d_name.hash); | ||
2516 | 2522 | ||
2517 | /* ... and switch the parents */ | 2523 | /* ... and switch them in the tree */ |
2518 | if (IS_ROOT(dentry)) { | 2524 | if (IS_ROOT(dentry)) { |
2525 | /* splicing a tree */ | ||
2519 | dentry->d_parent = target->d_parent; | 2526 | dentry->d_parent = target->d_parent; |
2520 | target->d_parent = target; | 2527 | target->d_parent = target; |
2521 | INIT_LIST_HEAD(&target->d_u.d_child); | 2528 | list_del_init(&target->d_u.d_child); |
2529 | list_move(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs); | ||
2522 | } else { | 2530 | } else { |
2531 | /* swapping two dentries */ | ||
2523 | swap(dentry->d_parent, target->d_parent); | 2532 | swap(dentry->d_parent, target->d_parent); |
2524 | 2533 | list_move(&target->d_u.d_child, &target->d_parent->d_subdirs); | |
2525 | /* And add them back to the (new) parent lists */ | 2534 | list_move(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs); |
2526 | list_add(&target->d_u.d_child, &target->d_parent->d_subdirs); | 2535 | if (exchange) |
2536 | fsnotify_d_move(target); | ||
2537 | fsnotify_d_move(dentry); | ||
2527 | } | 2538 | } |
2528 | 2539 | ||
2529 | list_add(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs); | ||
2530 | |||
2531 | write_seqcount_end(&target->d_seq); | 2540 | write_seqcount_end(&target->d_seq); |
2532 | write_seqcount_end(&dentry->d_seq); | 2541 | write_seqcount_end(&dentry->d_seq); |
2533 | 2542 | ||
2534 | dentry_unlock_parents_for_move(dentry, target); | 2543 | dentry_unlock_for_move(dentry, target); |
2535 | if (exchange) | ||
2536 | fsnotify_d_move(target); | ||
2537 | spin_unlock(&target->d_lock); | ||
2538 | fsnotify_d_move(dentry); | ||
2539 | spin_unlock(&dentry->d_lock); | ||
2540 | } | 2544 | } |
2541 | 2545 | ||
2542 | /* | 2546 | /* |
@@ -2634,39 +2638,6 @@ out_err: | |||
2634 | return ret; | 2638 | return ret; |
2635 | } | 2639 | } |
2636 | 2640 | ||
2637 | /* | ||
2638 | * Prepare an anonymous dentry for life in the superblock's dentry tree as a | ||
2639 | * named dentry in place of the dentry to be replaced. | ||
2640 | * returns with anon->d_lock held! | ||
2641 | */ | ||
2642 | static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon) | ||
2643 | { | ||
2644 | struct dentry *dparent; | ||
2645 | |||
2646 | dentry_lock_for_move(anon, dentry); | ||
2647 | |||
2648 | write_seqcount_begin(&dentry->d_seq); | ||
2649 | write_seqcount_begin_nested(&anon->d_seq, DENTRY_D_LOCK_NESTED); | ||
2650 | |||
2651 | dparent = dentry->d_parent; | ||
2652 | |||
2653 | switch_names(dentry, anon); | ||
2654 | swap(dentry->d_name.hash, anon->d_name.hash); | ||
2655 | |||
2656 | dentry->d_parent = dentry; | ||
2657 | list_del_init(&dentry->d_u.d_child); | ||
2658 | anon->d_parent = dparent; | ||
2659 | list_move(&anon->d_u.d_child, &dparent->d_subdirs); | ||
2660 | |||
2661 | write_seqcount_end(&dentry->d_seq); | ||
2662 | write_seqcount_end(&anon->d_seq); | ||
2663 | |||
2664 | dentry_unlock_parents_for_move(anon, dentry); | ||
2665 | spin_unlock(&dentry->d_lock); | ||
2666 | |||
2667 | /* anon->d_lock still locked, returns locked */ | ||
2668 | } | ||
2669 | |||
2670 | /** | 2641 | /** |
2671 | * d_splice_alias - splice a disconnected dentry into the tree if one exists | 2642 | * d_splice_alias - splice a disconnected dentry into the tree if one exists |
2672 | * @inode: the inode which may have a disconnected dentry | 2643 | * @inode: the inode which may have a disconnected dentry |
@@ -2712,11 +2683,8 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry) | |||
2712 | return ERR_PTR(-EIO); | 2683 | return ERR_PTR(-EIO); |
2713 | } | 2684 | } |
2714 | write_seqlock(&rename_lock); | 2685 | write_seqlock(&rename_lock); |
2715 | __d_materialise_dentry(dentry, new); | 2686 | __d_move(new, dentry, false); |
2716 | write_sequnlock(&rename_lock); | 2687 | write_sequnlock(&rename_lock); |
2717 | __d_drop(new); | ||
2718 | _d_rehash(new); | ||
2719 | spin_unlock(&new->d_lock); | ||
2720 | spin_unlock(&inode->i_lock); | 2688 | spin_unlock(&inode->i_lock); |
2721 | security_d_instantiate(new, inode); | 2689 | security_d_instantiate(new, inode); |
2722 | iput(inode); | 2690 | iput(inode); |
@@ -2776,9 +2744,8 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) | |||
2776 | } else if (IS_ROOT(alias)) { | 2744 | } else if (IS_ROOT(alias)) { |
2777 | /* Is this an anonymous mountpoint that we | 2745 | /* Is this an anonymous mountpoint that we |
2778 | * could splice into our tree? */ | 2746 | * could splice into our tree? */ |
2779 | __d_materialise_dentry(dentry, alias); | 2747 | __d_move(alias, dentry, false); |
2780 | write_sequnlock(&rename_lock); | 2748 | write_sequnlock(&rename_lock); |
2781 | __d_drop(alias); | ||
2782 | goto found; | 2749 | goto found; |
2783 | } else { | 2750 | } else { |
2784 | /* Nope, but we must(!) avoid directory | 2751 | /* Nope, but we must(!) avoid directory |
@@ -2804,13 +2771,9 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) | |||
2804 | actual = __d_instantiate_unique(dentry, inode); | 2771 | actual = __d_instantiate_unique(dentry, inode); |
2805 | if (!actual) | 2772 | if (!actual) |
2806 | actual = dentry; | 2773 | actual = dentry; |
2807 | else | ||
2808 | BUG_ON(!d_unhashed(actual)); | ||
2809 | 2774 | ||
2810 | spin_lock(&actual->d_lock); | 2775 | d_rehash(actual); |
2811 | found: | 2776 | found: |
2812 | _d_rehash(actual); | ||
2813 | spin_unlock(&actual->d_lock); | ||
2814 | spin_unlock(&inode->i_lock); | 2777 | spin_unlock(&inode->i_lock); |
2815 | out_nolock: | 2778 | out_nolock: |
2816 | if (actual == dentry) { | 2779 | if (actual == dentry) { |