diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-09-27 20:05:14 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-09-27 20:05:14 -0400 |
commit | 1e3827bf8aebe29af2d6e49b89d85dfae4d0154f (patch) | |
tree | 7e61ad7bcac7ef4ea9ecd46640ec3729e383c819 /fs/dcache.c | |
parent | 6111da3432b10b2c56a21a5d8671aee46435326d (diff) | |
parent | d2fa4a8476b911782f7e5167db18770222ac40c3 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs fixes from Al Viro:
"Assorted fixes + unifying __d_move() and __d_materialise_dentry() +
minimal regression fix for d_path() of victims of overwriting rename()
ported on top of that"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
vfs: Don't exchange "short" filenames unconditionally.
fold swapping ->d_name.hash into switch_names()
fold unlocking the children into dentry_unlock_parents_for_move()
kill __d_materialise_dentry()
__d_materialise_dentry(): flip the order of arguments
__d_move(): fold manipulations with ->d_child/->d_subdirs
don't open-code d_rehash() in d_materialise_unique()
pull rehashing and unlocking the target dentry into __d_materialise_dentry()
ufs: deal with nfsd/iget races
fuse: honour max_read and max_write in direct_io mode
shmem: fix nlink for rename overwrite directory
Diffstat (limited to 'fs/dcache.c')
-rw-r--r-- | fs/dcache.c | 112 |
1 files changed, 36 insertions, 76 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index 7a5b51440afa..cb25a1a5e307 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -2372,7 +2372,8 @@ void dentry_update_name_case(struct dentry *dentry, struct qstr *name) | |||
2372 | } | 2372 | } |
2373 | EXPORT_SYMBOL(dentry_update_name_case); | 2373 | EXPORT_SYMBOL(dentry_update_name_case); |
2374 | 2374 | ||
2375 | static void switch_names(struct dentry *dentry, struct dentry *target) | 2375 | static void switch_names(struct dentry *dentry, struct dentry *target, |
2376 | bool exchange) | ||
2376 | { | 2377 | { |
2377 | if (dname_external(target)) { | 2378 | if (dname_external(target)) { |
2378 | if (dname_external(dentry)) { | 2379 | if (dname_external(dentry)) { |
@@ -2406,13 +2407,19 @@ static void switch_names(struct dentry *dentry, struct dentry *target) | |||
2406 | */ | 2407 | */ |
2407 | unsigned int i; | 2408 | unsigned int i; |
2408 | 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 | } | ||
2409 | for (i = 0; i < DNAME_INLINE_LEN / sizeof(long); i++) { | 2416 | for (i = 0; i < DNAME_INLINE_LEN / sizeof(long); i++) { |
2410 | swap(((long *) &dentry->d_iname)[i], | 2417 | swap(((long *) &dentry->d_iname)[i], |
2411 | ((long *) &target->d_iname)[i]); | 2418 | ((long *) &target->d_iname)[i]); |
2412 | } | 2419 | } |
2413 | } | 2420 | } |
2414 | } | 2421 | } |
2415 | swap(dentry->d_name.len, target->d_name.len); | 2422 | swap(dentry->d_name.hash_len, target->d_name.hash_len); |
2416 | } | 2423 | } |
2417 | 2424 | ||
2418 | 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) |
@@ -2442,25 +2449,29 @@ static void dentry_lock_for_move(struct dentry *dentry, struct dentry *target) | |||
2442 | } | 2449 | } |
2443 | } | 2450 | } |
2444 | 2451 | ||
2445 | static void dentry_unlock_parents_for_move(struct dentry *dentry, | 2452 | static void dentry_unlock_for_move(struct dentry *dentry, struct dentry *target) |
2446 | struct dentry *target) | ||
2447 | { | 2453 | { |
2448 | if (target->d_parent != dentry->d_parent) | 2454 | if (target->d_parent != dentry->d_parent) |
2449 | spin_unlock(&dentry->d_parent->d_lock); | 2455 | spin_unlock(&dentry->d_parent->d_lock); |
2450 | if (target->d_parent != target) | 2456 | if (target->d_parent != target) |
2451 | 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); | ||
2452 | } | 2460 | } |
2453 | 2461 | ||
2454 | /* | 2462 | /* |
2455 | * When switching names, the actual string doesn't strictly have to | 2463 | * When switching names, the actual string doesn't strictly have to |
2456 | * be preserved in the target - because we're dropping the target | 2464 | * be preserved in the target - because we're dropping the target |
2457 | * 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 |
2458 | * the new name before we switch. | 2466 | * the new name before we switch, unless we are going to rehash |
2459 | * | 2467 | * it. Note that if we *do* unhash the target, we are not allowed |
2460 | * 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 |
2461 | * 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 |
2462 | * then no longer matches the actual (corrupted) string of the target. | 2470 | * the reality in filesystem; it's only there for d_path() purposes. |
2463 | * 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. | ||
2464 | */ | 2475 | */ |
2465 | /* | 2476 | /* |
2466 | * __d_move - move a dentry | 2477 | * __d_move - move a dentry |
@@ -2506,36 +2517,30 @@ static void __d_move(struct dentry *dentry, struct dentry *target, | |||
2506 | d_hash(dentry->d_parent, dentry->d_name.hash)); | 2517 | d_hash(dentry->d_parent, dentry->d_name.hash)); |
2507 | } | 2518 | } |
2508 | 2519 | ||
2509 | list_del(&dentry->d_u.d_child); | ||
2510 | list_del(&target->d_u.d_child); | ||
2511 | |||
2512 | /* Switch the names.. */ | 2520 | /* Switch the names.. */ |
2513 | switch_names(dentry, target); | 2521 | switch_names(dentry, target, exchange); |
2514 | swap(dentry->d_name.hash, target->d_name.hash); | ||
2515 | 2522 | ||
2516 | /* ... and switch the parents */ | 2523 | /* ... and switch them in the tree */ |
2517 | if (IS_ROOT(dentry)) { | 2524 | if (IS_ROOT(dentry)) { |
2525 | /* splicing a tree */ | ||
2518 | dentry->d_parent = target->d_parent; | 2526 | dentry->d_parent = target->d_parent; |
2519 | target->d_parent = target; | 2527 | target->d_parent = target; |
2520 | 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); | ||
2521 | } else { | 2530 | } else { |
2531 | /* swapping two dentries */ | ||
2522 | swap(dentry->d_parent, target->d_parent); | 2532 | swap(dentry->d_parent, target->d_parent); |
2523 | 2533 | list_move(&target->d_u.d_child, &target->d_parent->d_subdirs); | |
2524 | /* And add them back to the (new) parent lists */ | 2534 | list_move(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs); |
2525 | 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); | ||
2526 | } | 2538 | } |
2527 | 2539 | ||
2528 | list_add(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs); | ||
2529 | |||
2530 | write_seqcount_end(&target->d_seq); | 2540 | write_seqcount_end(&target->d_seq); |
2531 | write_seqcount_end(&dentry->d_seq); | 2541 | write_seqcount_end(&dentry->d_seq); |
2532 | 2542 | ||
2533 | dentry_unlock_parents_for_move(dentry, target); | 2543 | dentry_unlock_for_move(dentry, target); |
2534 | if (exchange) | ||
2535 | fsnotify_d_move(target); | ||
2536 | spin_unlock(&target->d_lock); | ||
2537 | fsnotify_d_move(dentry); | ||
2538 | spin_unlock(&dentry->d_lock); | ||
2539 | } | 2544 | } |
2540 | 2545 | ||
2541 | /* | 2546 | /* |
@@ -2633,45 +2638,6 @@ out_err: | |||
2633 | return ret; | 2638 | return ret; |
2634 | } | 2639 | } |
2635 | 2640 | ||
2636 | /* | ||
2637 | * Prepare an anonymous dentry for life in the superblock's dentry tree as a | ||
2638 | * named dentry in place of the dentry to be replaced. | ||
2639 | * returns with anon->d_lock held! | ||
2640 | */ | ||
2641 | static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon) | ||
2642 | { | ||
2643 | struct dentry *dparent; | ||
2644 | |||
2645 | dentry_lock_for_move(anon, dentry); | ||
2646 | |||
2647 | write_seqcount_begin(&dentry->d_seq); | ||
2648 | write_seqcount_begin_nested(&anon->d_seq, DENTRY_D_LOCK_NESTED); | ||
2649 | |||
2650 | dparent = dentry->d_parent; | ||
2651 | |||
2652 | switch_names(dentry, anon); | ||
2653 | swap(dentry->d_name.hash, anon->d_name.hash); | ||
2654 | |||
2655 | dentry->d_parent = dentry; | ||
2656 | list_del_init(&dentry->d_u.d_child); | ||
2657 | anon->d_parent = dparent; | ||
2658 | if (likely(!d_unhashed(anon))) { | ||
2659 | hlist_bl_lock(&anon->d_sb->s_anon); | ||
2660 | __hlist_bl_del(&anon->d_hash); | ||
2661 | anon->d_hash.pprev = NULL; | ||
2662 | hlist_bl_unlock(&anon->d_sb->s_anon); | ||
2663 | } | ||
2664 | list_move(&anon->d_u.d_child, &dparent->d_subdirs); | ||
2665 | |||
2666 | write_seqcount_end(&dentry->d_seq); | ||
2667 | write_seqcount_end(&anon->d_seq); | ||
2668 | |||
2669 | dentry_unlock_parents_for_move(anon, dentry); | ||
2670 | spin_unlock(&dentry->d_lock); | ||
2671 | |||
2672 | /* anon->d_lock still locked, returns locked */ | ||
2673 | } | ||
2674 | |||
2675 | /** | 2641 | /** |
2676 | * 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 |
2677 | * @inode: the inode which may have a disconnected dentry | 2643 | * @inode: the inode which may have a disconnected dentry |
@@ -2717,10 +2683,8 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry) | |||
2717 | return ERR_PTR(-EIO); | 2683 | return ERR_PTR(-EIO); |
2718 | } | 2684 | } |
2719 | write_seqlock(&rename_lock); | 2685 | write_seqlock(&rename_lock); |
2720 | __d_materialise_dentry(dentry, new); | 2686 | __d_move(new, dentry, false); |
2721 | write_sequnlock(&rename_lock); | 2687 | write_sequnlock(&rename_lock); |
2722 | _d_rehash(new); | ||
2723 | spin_unlock(&new->d_lock); | ||
2724 | spin_unlock(&inode->i_lock); | 2688 | spin_unlock(&inode->i_lock); |
2725 | security_d_instantiate(new, inode); | 2689 | security_d_instantiate(new, inode); |
2726 | iput(inode); | 2690 | iput(inode); |
@@ -2780,7 +2744,7 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) | |||
2780 | } else if (IS_ROOT(alias)) { | 2744 | } else if (IS_ROOT(alias)) { |
2781 | /* Is this an anonymous mountpoint that we | 2745 | /* Is this an anonymous mountpoint that we |
2782 | * could splice into our tree? */ | 2746 | * could splice into our tree? */ |
2783 | __d_materialise_dentry(dentry, alias); | 2747 | __d_move(alias, dentry, false); |
2784 | write_sequnlock(&rename_lock); | 2748 | write_sequnlock(&rename_lock); |
2785 | goto found; | 2749 | goto found; |
2786 | } else { | 2750 | } else { |
@@ -2807,13 +2771,9 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) | |||
2807 | actual = __d_instantiate_unique(dentry, inode); | 2771 | actual = __d_instantiate_unique(dentry, inode); |
2808 | if (!actual) | 2772 | if (!actual) |
2809 | actual = dentry; | 2773 | actual = dentry; |
2810 | else | ||
2811 | BUG_ON(!d_unhashed(actual)); | ||
2812 | 2774 | ||
2813 | spin_lock(&actual->d_lock); | 2775 | d_rehash(actual); |
2814 | found: | 2776 | found: |
2815 | _d_rehash(actual); | ||
2816 | spin_unlock(&actual->d_lock); | ||
2817 | spin_unlock(&inode->i_lock); | 2777 | spin_unlock(&inode->i_lock); |
2818 | out_nolock: | 2778 | out_nolock: |
2819 | if (actual == dentry) { | 2779 | if (actual == dentry) { |