Skip to content

Commit f1ee616

Browse files
NeilBrownAl Viro
authored andcommitted
VFS: don't keep disconnected dentries on d_anon
The original purpose of the per-superblock d_anon list was to keep disconnected dentries in the cache between consecutive requests to the NFS server. Dentries can be disconnected if a client holds a file open and repeatedly performs IO on it, and if the server drops the dentry, whether due to memory pressure, server restart, or "echo 3 > /proc/sys/vm/drop_caches". This purpose was thwarted by commit 75a6f82 ("freeing unlinked file indefinitely delayed") which caused disconnected dentries to be freed as soon as their refcount reached zero. This means that, when a dentry being used by nfsd gets disconnected, a new one needs to be allocated for every request (unless requests overlap). As the dentry has no name, no parent, and no children, there is little of value to cache. As small memory allocations are typically fast (from per-cpu free lists) this likely has little cost. This means that the original purpose of s_anon is no longer relevant: there is no longer any need to keep disconnected dentries on a list so they appear to be hashed. However, s_anon now has a new use. When you mount an NFS filesystem, the dentry stored in s_root is just a placebo. The "real" root dentry is allocated using d_obtain_root() and so it kept on the s_anon list. I don't know the reason for this, but suspect it related to NFSv4 where a mount of "server:/some/path" require NFS to look up the root filehandle on the server, then walk down "/some" and "/path" to get the filehandle to mount. Whatever the reason, NFS depends on the s_anon list and on shrink_dcache_for_umount() pruning all dentries on this list. So we cannot simply remove s_anon. We could just leave the code unchanged, but apart from that being potentially confusing, the (unfair) bit-spin-lock which protects s_anon can become a bottle neck when lots of disconnected dentries are being created. So this patch renames s_anon to s_roots, and stops storing disconnected dentries on the list. Only dentries obtained with d_obtain_root() are now stored on this list. There are many fewer of these (only NFS and NILFS2 use the call, and only during filesystem mount) so contention on the bit-lock will not be a problem. Possibly an alternate solution should be found for NFS and NILFS2, but that would require understanding their needs first. Signed-off-by: NeilBrown <[email protected]> Signed-off-by: Al Viro <[email protected]>
1 parent 00b0c9b commit f1ee616

File tree

5 files changed

+34
-29
lines changed

5 files changed

+34
-29
lines changed

Documentation/filesystems/nfs/Exporting

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,25 @@ a/ A dentry flag DCACHE_DISCONNECTED which is set on
5656
any dentry that might not be part of the proper prefix.
5757
This is set when anonymous dentries are created, and cleared when a
5858
dentry is noticed to be a child of a dentry which is in the proper
59-
prefix.
60-
61-
b/ A per-superblock list "s_anon" of dentries which are the roots of
62-
subtrees that are not in the proper prefix. These dentries, as
63-
well as the proper prefix, need to be released at unmount time. As
64-
these dentries will not be hashed, they are linked together on the
65-
d_hash list_head.
59+
prefix. If the refcount on a dentry with this flag set
60+
becomes zero, the dentry is immediately discarded, rather than being
61+
kept in the dcache. If a dentry that is not already in the dcache
62+
is repeatedly accessed by filehandle (as NFSD might do), an new dentry
63+
will be a allocated for each access, and discarded at the end of
64+
the access.
65+
66+
Note that such a dentry can acquire children, name, ancestors, etc.
67+
without losing DCACHE_DISCONNECTED - that flag is only cleared when
68+
subtree is successfully reconnected to root. Until then dentries
69+
in such subtree are retained only as long as there are references;
70+
refcount reaching zero means immediate eviction, same as for unhashed
71+
dentries. That guarantees that we won't need to hunt them down upon
72+
umount.
73+
74+
b/ A primitive for creation of secondary roots - d_obtain_root(inode).
75+
Those do _not_ bear DCACHE_DISCONNECTED. They are placed on the
76+
per-superblock list (->s_roots), so they can be located at umount
77+
time for eviction purposes.
6678

6779
c/ Helper routines to allocate anonymous dentries, and to help attach
6880
loose directory dentries at lookup time. They are:
@@ -77,7 +89,6 @@ c/ Helper routines to allocate anonymous dentries, and to help attach
7789
(such as an anonymous one created by d_obtain_alias), if appropriate.
7890
It returns NULL when the passed-in dentry is used, following the calling
7991
convention of ->lookup.
80-
8192

8293
Filesystem Issues
8394
-----------------

drivers/staging/lustre/lustre/llite/llite_internal.h

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1296,15 +1296,7 @@ static inline void d_lustre_invalidate(struct dentry *dentry, int nested)
12961296
spin_lock_nested(&dentry->d_lock,
12971297
nested ? DENTRY_D_LOCK_NESTED : DENTRY_D_LOCK_NORMAL);
12981298
ll_d2d(dentry)->lld_invalid = 1;
1299-
/*
1300-
* We should be careful about dentries created by d_obtain_alias().
1301-
* These dentries are not put in the dentry tree, instead they are
1302-
* linked to sb->s_anon through dentry->d_hash.
1303-
* shrink_dcache_for_umount() shrinks the tree and sb->s_anon list.
1304-
* If we unhashed such a dentry, unmount would not be able to find
1305-
* it and busy inodes would be reported.
1306-
*/
1307-
if (d_count(dentry) == 0 && !(dentry->d_flags & DCACHE_DISCONNECTED))
1299+
if (d_count(dentry) == 0)
13081300
__d_drop(dentry);
13091301
spin_unlock(&dentry->d_lock);
13101302
}

fs/dcache.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@
4848
* - i_dentry, d_u.d_alias, d_inode of aliases
4949
* dcache_hash_bucket lock protects:
5050
* - the dcache hash table
51-
* s_anon bl list spinlock protects:
52-
* - the s_anon list (see __d_drop)
51+
* s_roots bl list spinlock protects:
52+
* - the s_roots list (see __d_drop)
5353
* dentry->d_sb->s_dentry_lru_lock protects:
5454
* - the dcache lru lists and counters
5555
* d_lock protects:
@@ -67,7 +67,7 @@
6767
* dentry->d_lock
6868
* dentry->d_sb->s_dentry_lru_lock
6969
* dcache_hash_bucket lock
70-
* s_anon lock
70+
* s_roots lock
7171
*
7272
* If there is an ancestor relationship:
7373
* dentry->d_parent->...->d_parent->d_lock
@@ -476,10 +476,10 @@ void __d_drop(struct dentry *dentry)
476476
/*
477477
* Hashed dentries are normally on the dentry hashtable,
478478
* with the exception of those newly allocated by
479-
* d_obtain_alias, which are always IS_ROOT:
479+
* d_obtain_root, which are always IS_ROOT:
480480
*/
481481
if (unlikely(IS_ROOT(dentry)))
482-
b = &dentry->d_sb->s_anon;
482+
b = &dentry->d_sb->s_roots;
483483
else
484484
b = d_hash(dentry->d_name.hash);
485485

@@ -1499,8 +1499,8 @@ void shrink_dcache_for_umount(struct super_block *sb)
14991499
sb->s_root = NULL;
15001500
do_one_tree(dentry);
15011501

1502-
while (!hlist_bl_empty(&sb->s_anon)) {
1503-
dentry = dget(hlist_bl_entry(hlist_bl_first(&sb->s_anon), struct dentry, d_hash));
1502+
while (!hlist_bl_empty(&sb->s_roots)) {
1503+
dentry = dget(hlist_bl_entry(hlist_bl_first(&sb->s_roots), struct dentry, d_hash));
15041504
do_one_tree(dentry);
15051505
}
15061506
}
@@ -1964,9 +1964,11 @@ static struct dentry *__d_obtain_alias(struct inode *inode, int disconnected)
19641964
spin_lock(&tmp->d_lock);
19651965
__d_set_inode_and_type(tmp, inode, add_flags);
19661966
hlist_add_head(&tmp->d_u.d_alias, &inode->i_dentry);
1967-
hlist_bl_lock(&tmp->d_sb->s_anon);
1968-
hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon);
1969-
hlist_bl_unlock(&tmp->d_sb->s_anon);
1967+
if (!disconnected) {
1968+
hlist_bl_lock(&tmp->d_sb->s_roots);
1969+
hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_roots);
1970+
hlist_bl_unlock(&tmp->d_sb->s_roots);
1971+
}
19701972
spin_unlock(&tmp->d_lock);
19711973
spin_unlock(&inode->i_lock);
19721974

fs/super.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags,
207207
if (s->s_user_ns != &init_user_ns)
208208
s->s_iflags |= SB_I_NODEV;
209209
INIT_HLIST_NODE(&s->s_instances);
210-
INIT_HLIST_BL_HEAD(&s->s_anon);
210+
INIT_HLIST_BL_HEAD(&s->s_roots);
211211
mutex_init(&s->s_sync_lock);
212212
INIT_LIST_HEAD(&s->s_inodes);
213213
spin_lock_init(&s->s_inode_list_lock);

include/linux/fs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1359,7 +1359,7 @@ struct super_block {
13591359

13601360
const struct fscrypt_operations *s_cop;
13611361

1362-
struct hlist_bl_head s_anon; /* anonymous dentries for (nfs) exporting */
1362+
struct hlist_bl_head s_roots; /* alternate root dentries for NFS */
13631363
struct list_head s_mounts; /* list of mounts; _not_ for fs use */
13641364
struct block_device *s_bdev;
13651365
struct backing_dev_info *s_bdi;

0 commit comments

Comments
 (0)