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

Configure Feed

Select the types of activity you want to include in your feed.

primitives for maintaining persisitency

* d_make_persistent(dentry, inode) - bump refcount, mark persistent and
make hashed positive. Return value is a borrowed reference to dentry;
it can be used until something removes persistency (at the very least,
until the parent gets unlocked, but some filesystems may have stronger
exclusion).

* d_make_discardable() - remove persistency mark and drop reference.

d_make_persistent() is similar to combination of d_instantiate(), dget()
and setting flag. The only difference is that unlike d_instantiate()
it accepts hashed and unhashed negatives alike. It is always called in
strong locking environment (parent held exclusive, or, in some cases,
dentry coming from d_alloc_name()); if we ever start using it with parent
held only shared and dentry coming from d_alloc_parallel(), we'll need
to copy the in-lookup logics from __d_add().

d_make_discardable() is eqiuvalent to combination of removing flag and
dput(); since flag removal requires ->d_lock, there's no point trying
to avoid taking that for refcount decrement as fast_dput() does.
The slow path of dput() has been taken into a helper and reused in
d_make_discardable() instead.

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

Al Viro bacdf1d7 8a210cac

+61 -15
+59 -15
fs/dcache.c
··· 869 869 return false; 870 870 } 871 871 872 + static void finish_dput(struct dentry *dentry) 873 + __releases(dentry->d_lock) 874 + __releases(RCU) 875 + { 876 + while (lock_for_kill(dentry)) { 877 + rcu_read_unlock(); 878 + dentry = __dentry_kill(dentry); 879 + if (!dentry) 880 + return; 881 + if (retain_dentry(dentry, true)) { 882 + spin_unlock(&dentry->d_lock); 883 + return; 884 + } 885 + rcu_read_lock(); 886 + } 887 + rcu_read_unlock(); 888 + spin_unlock(&dentry->d_lock); 889 + } 872 890 873 891 /* 874 892 * This is dput ··· 924 906 rcu_read_unlock(); 925 907 return; 926 908 } 927 - while (lock_for_kill(dentry)) { 928 - rcu_read_unlock(); 929 - dentry = __dentry_kill(dentry); 930 - if (!dentry) 931 - return; 932 - if (retain_dentry(dentry, true)) { 933 - spin_unlock(&dentry->d_lock); 934 - return; 935 - } 936 - rcu_read_lock(); 937 - } 938 - rcu_read_unlock(); 939 - spin_unlock(&dentry->d_lock); 909 + finish_dput(dentry); 940 910 } 941 911 EXPORT_SYMBOL(dput); 912 + 913 + void d_make_discardable(struct dentry *dentry) 914 + { 915 + spin_lock(&dentry->d_lock); 916 + /* 917 + * By the end of the series we'll add 918 + * WARN_ON(!(dentry->d_flags & DCACHE_PERSISTENT); 919 + * here, but while object removal is done by a few common helpers, 920 + * object creation tends to be open-coded (if nothing else, new inode 921 + * needs to be set up), so adding a warning from the very beginning 922 + * would make for much messier patch series. 923 + */ 924 + dentry->d_flags &= ~DCACHE_PERSISTENT; 925 + dentry->d_lockref.count--; 926 + rcu_read_lock(); 927 + finish_dput(dentry); 928 + } 929 + EXPORT_SYMBOL(d_make_discardable); 942 930 943 931 static void to_shrink_list(struct dentry *dentry, struct list_head *list) 944 932 __must_hold(&dentry->d_lock) ··· 1963 1939 unsigned add_flags = d_flags_for_inode(inode); 1964 1940 WARN_ON(d_in_lookup(dentry)); 1965 1941 1966 - spin_lock(&dentry->d_lock); 1967 1942 /* 1968 1943 * The negative counter only tracks dentries on the LRU. Don't dec if 1969 1944 * d_lru is on another list. ··· 1975 1952 __d_set_inode_and_type(dentry, inode, add_flags); 1976 1953 raw_write_seqcount_end(&dentry->d_seq); 1977 1954 fsnotify_update_flags(dentry); 1978 - spin_unlock(&dentry->d_lock); 1979 1955 } 1980 1956 1981 1957 /** ··· 1998 1976 if (inode) { 1999 1977 security_d_instantiate(entry, inode); 2000 1978 spin_lock(&inode->i_lock); 1979 + spin_lock(&entry->d_lock); 2001 1980 __d_instantiate(entry, inode); 1981 + spin_unlock(&entry->d_lock); 2002 1982 spin_unlock(&inode->i_lock); 2003 1983 } 2004 1984 } ··· 2019 1995 lockdep_annotate_inode_mutex_key(inode); 2020 1996 security_d_instantiate(entry, inode); 2021 1997 spin_lock(&inode->i_lock); 1998 + spin_lock(&entry->d_lock); 2022 1999 __d_instantiate(entry, inode); 2000 + spin_unlock(&entry->d_lock); 2023 2001 WARN_ON(!(inode->i_state & I_NEW)); 2024 2002 inode->i_state &= ~I_NEW & ~I_CREATING; 2025 2003 /* ··· 2779 2753 __d_add(entry, inode, NULL); 2780 2754 } 2781 2755 EXPORT_SYMBOL(d_add); 2756 + 2757 + struct dentry *d_make_persistent(struct dentry *dentry, struct inode *inode) 2758 + { 2759 + WARN_ON(!hlist_unhashed(&dentry->d_u.d_alias)); 2760 + WARN_ON(!inode); 2761 + security_d_instantiate(dentry, inode); 2762 + spin_lock(&inode->i_lock); 2763 + spin_lock(&dentry->d_lock); 2764 + __d_instantiate(dentry, inode); 2765 + dentry->d_flags |= DCACHE_PERSISTENT; 2766 + dget_dlock(dentry); 2767 + if (d_unhashed(dentry)) 2768 + __d_rehash(dentry); 2769 + spin_unlock(&dentry->d_lock); 2770 + spin_unlock(&inode->i_lock); 2771 + return dentry; 2772 + } 2773 + EXPORT_SYMBOL(d_make_persistent); 2782 2774 2783 2775 static void swap_names(struct dentry *dentry, struct dentry *target) 2784 2776 {
+2
include/linux/dcache.h
··· 611 611 } 612 612 613 613 void set_default_d_op(struct super_block *, const struct dentry_operations *); 614 + struct dentry *d_make_persistent(struct dentry *, struct inode *); 615 + void d_make_discardable(struct dentry *dentry); 614 616 615 617 #endif /* __LINUX_DCACHE_H */