Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

merge d_materialise_unique() into d_splice_alias()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Al Viro b5ae6b15 154e80e4

+37 -110
+36 -109
fs/dcache.c
··· 2575 2575 * Note: If ever the locking in lock_rename() changes, then please 2576 2576 * remember to update this too... 2577 2577 */ 2578 - static struct dentry *__d_unalias(struct inode *inode, 2578 + static int __d_unalias(struct inode *inode, 2579 2579 struct dentry *dentry, struct dentry *alias) 2580 2580 { 2581 2581 struct mutex *m1 = NULL, *m2 = NULL; 2582 - struct dentry *ret = ERR_PTR(-EBUSY); 2582 + int ret = -EBUSY; 2583 2583 2584 2584 /* If alias and dentry share a parent, then no extra locks required */ 2585 2585 if (alias->d_parent == dentry->d_parent) ··· 2594 2594 m2 = &alias->d_parent->d_inode->i_mutex; 2595 2595 out_unalias: 2596 2596 __d_move(alias, dentry, false); 2597 - ret = alias; 2597 + ret = 0; 2598 2598 out_err: 2599 2599 spin_unlock(&inode->i_lock); 2600 2600 if (m2) ··· 2629 2629 */ 2630 2630 struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry) 2631 2631 { 2632 - struct dentry *new = NULL; 2633 - 2634 2632 if (IS_ERR(inode)) 2635 2633 return ERR_CAST(inode); 2636 - 2637 - if (inode && S_ISDIR(inode->i_mode)) { 2638 - spin_lock(&inode->i_lock); 2639 - new = __d_find_any_alias(inode); 2640 - if (new) { 2641 - if (!IS_ROOT(new)) { 2642 - spin_unlock(&inode->i_lock); 2643 - dput(new); 2644 - iput(inode); 2645 - return ERR_PTR(-EIO); 2646 - } 2647 - if (d_ancestor(new, dentry)) { 2648 - spin_unlock(&inode->i_lock); 2649 - dput(new); 2650 - iput(inode); 2651 - return ERR_PTR(-EIO); 2652 - } 2653 - write_seqlock(&rename_lock); 2654 - __d_move(new, dentry, false); 2655 - write_sequnlock(&rename_lock); 2656 - spin_unlock(&inode->i_lock); 2657 - security_d_instantiate(new, inode); 2658 - iput(inode); 2659 - } else { 2660 - /* already taking inode->i_lock, so d_add() by hand */ 2661 - __d_instantiate(dentry, inode); 2662 - spin_unlock(&inode->i_lock); 2663 - security_d_instantiate(dentry, inode); 2664 - d_rehash(dentry); 2665 - } 2666 - } else { 2667 - d_instantiate(dentry, inode); 2668 - if (d_unhashed(dentry)) 2669 - d_rehash(dentry); 2670 - } 2671 - return new; 2672 - } 2673 - EXPORT_SYMBOL(d_splice_alias); 2674 - 2675 - /** 2676 - * d_materialise_unique - introduce an inode into the tree 2677 - * @dentry: candidate dentry 2678 - * @inode: inode to bind to the dentry, to which aliases may be attached 2679 - * 2680 - * Introduces an dentry into the tree, substituting an extant disconnected 2681 - * root directory alias in its place if there is one. Caller must hold the 2682 - * i_mutex of the parent directory. 2683 - */ 2684 - struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) 2685 - { 2686 - struct dentry *actual; 2687 2634 2688 2635 BUG_ON(!d_unhashed(dentry)); 2689 2636 2690 2637 if (!inode) { 2691 - actual = dentry; 2692 2638 __d_instantiate(dentry, NULL); 2693 - d_rehash(actual); 2694 - goto out_nolock; 2639 + goto out; 2695 2640 } 2696 - 2697 2641 spin_lock(&inode->i_lock); 2698 - 2699 2642 if (S_ISDIR(inode->i_mode)) { 2700 - struct dentry *alias; 2701 - 2702 - /* Does an aliased dentry already exist? */ 2703 - alias = __d_find_alias(inode); 2704 - if (alias) { 2705 - actual = alias; 2643 + struct dentry *new = __d_find_any_alias(inode); 2644 + if (unlikely(new)) { 2706 2645 write_seqlock(&rename_lock); 2707 - 2708 - if (d_ancestor(alias, dentry)) { 2709 - /* Check for loops */ 2710 - actual = ERR_PTR(-ELOOP); 2711 - spin_unlock(&inode->i_lock); 2712 - } else if (IS_ROOT(alias)) { 2713 - /* Is this an anonymous mountpoint that we 2714 - * could splice into our tree? */ 2715 - __d_move(alias, dentry, false); 2646 + if (unlikely(d_ancestor(new, dentry))) { 2716 2647 write_sequnlock(&rename_lock); 2717 - goto found; 2648 + spin_unlock(&inode->i_lock); 2649 + dput(new); 2650 + new = ERR_PTR(-ELOOP); 2651 + pr_warn_ratelimited( 2652 + "VFS: Lookup of '%s' in %s %s" 2653 + " would have caused loop\n", 2654 + dentry->d_name.name, 2655 + inode->i_sb->s_type->name, 2656 + inode->i_sb->s_id); 2657 + } else if (!IS_ROOT(new)) { 2658 + int err = __d_unalias(inode, dentry, new); 2659 + write_sequnlock(&rename_lock); 2660 + if (err) { 2661 + dput(new); 2662 + new = ERR_PTR(err); 2663 + } 2718 2664 } else { 2719 - /* Nope, but we must(!) avoid directory 2720 - * aliasing. This drops inode->i_lock */ 2721 - actual = __d_unalias(inode, dentry, alias); 2665 + __d_move(new, dentry, false); 2666 + write_sequnlock(&rename_lock); 2667 + spin_unlock(&inode->i_lock); 2668 + security_d_instantiate(new, inode); 2722 2669 } 2723 - write_sequnlock(&rename_lock); 2724 - if (IS_ERR(actual)) { 2725 - if (PTR_ERR(actual) == -ELOOP) 2726 - pr_warn_ratelimited( 2727 - "VFS: Lookup of '%s' in %s %s" 2728 - " would have caused loop\n", 2729 - dentry->d_name.name, 2730 - inode->i_sb->s_type->name, 2731 - inode->i_sb->s_id); 2732 - dput(alias); 2733 - } 2734 - goto out_nolock; 2670 + iput(inode); 2671 + return new; 2735 2672 } 2736 2673 } 2737 - 2738 - /* Add a unique reference */ 2739 - actual = __d_instantiate_unique(dentry, inode); 2740 - if (!actual) 2741 - actual = dentry; 2742 - 2743 - d_rehash(actual); 2744 - found: 2674 + /* already taking inode->i_lock, so d_add() by hand */ 2675 + __d_instantiate(dentry, inode); 2745 2676 spin_unlock(&inode->i_lock); 2746 - out_nolock: 2747 - if (actual == dentry) { 2748 - security_d_instantiate(dentry, inode); 2749 - return NULL; 2750 - } 2751 - 2752 - iput(inode); 2753 - return actual; 2677 + out: 2678 + security_d_instantiate(dentry, inode); 2679 + d_rehash(dentry); 2680 + return NULL; 2754 2681 } 2755 - EXPORT_SYMBOL_GPL(d_materialise_unique); 2682 + EXPORT_SYMBOL(d_splice_alias); 2756 2683 2757 2684 static int prepend(char **buffer, int *buflen, const char *str, int namelen) 2758 2685 {
+1 -1
include/linux/dcache.h
··· 230 230 */ 231 231 extern void d_instantiate(struct dentry *, struct inode *); 232 232 extern struct dentry * d_instantiate_unique(struct dentry *, struct inode *); 233 - extern struct dentry * d_materialise_unique(struct dentry *, struct inode *); 233 + #define d_materialise_unique(d, i) d_splice_alias(i, d) 234 234 extern int d_instantiate_no_diralias(struct dentry *, struct inode *); 235 235 extern void __d_drop(struct dentry *dentry); 236 236 extern void d_drop(struct dentry *dentry);