2019-05-19 12:08:55 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* fs/dcache.c
|
|
|
|
*
|
|
|
|
* Complete reimplementation
|
|
|
|
* (C) 1997 Thomas Schoebel-Theuer,
|
|
|
|
* with heavy changes by Linus Torvalds
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Notes on the allocation strategy:
|
|
|
|
*
|
|
|
|
* The dcache is a master of the icache - whenever a dcache entry
|
|
|
|
* exists, the inode will always exist. "iput()" is done either when
|
|
|
|
* the dcache entry is deleted or garbage collected.
|
|
|
|
*/
|
|
|
|
|
2018-03-06 00:15:50 +00:00
|
|
|
#include <linux/ratelimit.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
#include <linux/string.h>
|
|
|
|
#include <linux/mm.h>
|
|
|
|
#include <linux/fs.h>
|
2019-03-20 18:39:11 +00:00
|
|
|
#include <linux/fscrypt.h>
|
2005-08-08 17:52:16 +00:00
|
|
|
#include <linux/fsnotify.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
#include <linux/slab.h>
|
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/hash.h>
|
|
|
|
#include <linux/cache.h>
|
2011-11-17 04:57:37 +00:00
|
|
|
#include <linux/export.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
#include <linux/security.h>
|
|
|
|
#include <linux/seqlock.h>
|
2018-10-30 22:09:49 +00:00
|
|
|
#include <linux/memblock.h>
|
2011-01-07 06:50:05 +00:00
|
|
|
#include <linux/bit_spinlock.h>
|
|
|
|
#include <linux/rculist_bl.h>
|
2013-08-28 00:18:00 +00:00
|
|
|
#include <linux/list_lru.h>
|
2006-09-30 18:52:18 +00:00
|
|
|
#include "internal.h"
|
2011-11-24 00:26:23 +00:00
|
|
|
#include "mount.h"
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2024-06-04 19:30:02 +00:00
|
|
|
#include <asm/runtime-const.h>
|
|
|
|
|
2011-01-07 06:49:30 +00:00
|
|
|
/*
|
|
|
|
* Usage:
|
2011-01-07 06:50:06 +00:00
|
|
|
* dcache->d_inode->i_lock protects:
|
2014-10-26 23:19:16 +00:00
|
|
|
* - i_dentry, d_u.d_alias, d_inode of aliases
|
2011-01-07 06:50:05 +00:00
|
|
|
* dcache_hash_bucket lock protects:
|
|
|
|
* - the dcache hash table
|
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 75a6f82a0d10 ("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 <neilb@suse.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2017-12-20 22:45:40 +00:00
|
|
|
* s_roots bl list spinlock protects:
|
|
|
|
* - the s_roots list (see __d_drop)
|
2013-08-28 00:17:55 +00:00
|
|
|
* dentry->d_sb->s_dentry_lru_lock protects:
|
2011-01-07 06:49:31 +00:00
|
|
|
* - the dcache lru lists and counters
|
|
|
|
* d_lock protects:
|
|
|
|
* - d_flags
|
|
|
|
* - d_name
|
|
|
|
* - d_lru
|
2011-01-07 06:49:32 +00:00
|
|
|
* - d_count
|
2011-01-07 06:49:33 +00:00
|
|
|
* - d_unhashed()
|
2023-11-07 07:00:39 +00:00
|
|
|
* - d_parent and d_chilren
|
|
|
|
* - childrens' d_sib and d_parent
|
2014-10-26 23:19:16 +00:00
|
|
|
* - d_u.d_alias, d_inode
|
2011-01-07 06:49:30 +00:00
|
|
|
*
|
|
|
|
* Ordering:
|
2011-01-07 06:50:06 +00:00
|
|
|
* dentry->d_inode->i_lock
|
2011-01-07 06:49:38 +00:00
|
|
|
* dentry->d_lock
|
2013-08-28 00:17:55 +00:00
|
|
|
* dentry->d_sb->s_dentry_lru_lock
|
2011-01-07 06:50:05 +00:00
|
|
|
* dcache_hash_bucket lock
|
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 75a6f82a0d10 ("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 <neilb@suse.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2017-12-20 22:45:40 +00:00
|
|
|
* s_roots lock
|
2011-01-07 06:49:30 +00:00
|
|
|
*
|
2011-01-07 06:49:33 +00:00
|
|
|
* If there is an ancestor relationship:
|
|
|
|
* dentry->d_parent->...->d_parent->d_lock
|
|
|
|
* ...
|
|
|
|
* dentry->d_parent->d_lock
|
|
|
|
* dentry->d_lock
|
|
|
|
*
|
|
|
|
* If no ancestor relationship:
|
make non-exchanging __d_move() copy ->d_parent rather than swap them
Currently d_move(from, to) does the following:
* name/parent of from <- old name/parent of to, from hashed there
* to is unhashed
* name of to is preserved
* if from used to be detached, to gets detached
* if from used to be attached, parent of to <- old parent of from.
That's both user-visibly bogus and complicates reasoning a lot.
Much saner semantics would be
* name/parent of from <- name/parent of to, from hashed there.
* to is unhashed
* name/parent of to is unchanged.
The price, of course, is that old parent of from might lose a reference.
However,
* all potentially cross-directory callers of d_move() have both
parents pinned directly; typically, dentries themselves are grabbed
only after we have grabbed and locked both parents. IOW, the decrement
of old parent's refcount in case of d_move() won't reach zero.
* __d_move() from d_splice_alias() is done to detached alias.
No refcount decrements in that case
* __d_move() from __d_unalias() *can* get the refcount to zero.
So let's grab a reference to alias' old parent before calling __d_unalias()
and dput() it after we'd dropped rename_lock.
That does make d_splice_alias() potentially blocking. However, it has
no callers in non-sleepable contexts (and the case where we'd grown
that dget/dput pair is _very_ rare, so performance is not an issue).
Another thing that needs adjustment is unlocking in the end of __d_move();
folded it in. And cleaned the remnants of bogus ordering from the
"lock them in the beginning" counterpart - it's never been right and
now (well, for 7 years now) we have that thing always serialized on
rename_lock anyway.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2018-03-11 04:15:52 +00:00
|
|
|
* arbitrary, since it's serialized on rename_lock
|
2011-01-07 06:49:30 +00:00
|
|
|
*/
|
2006-03-26 09:37:24 +00:00
|
|
|
int sysctl_vfs_cache_pressure __read_mostly = 100;
|
2005-04-16 22:20:36 +00:00
|
|
|
EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure);
|
|
|
|
|
[PATCH] audit: watching subtrees
New kind of audit rule predicates: "object is visible in given subtree".
The part that can be sanely implemented, that is. Limitations:
* if you have hardlink from outside of tree, you'd better watch
it too (or just watch the object itself, obviously)
* if you mount something under a watched tree, tell audit
that new chunk should be added to watched subtrees
* if you umount something in a watched tree and it's still mounted
elsewhere, you will get matches on events happening there. New command
tells audit to recalculate the trees, trimming such sources of false
positives.
Note that it's _not_ about path - if something mounted in several places
(multiple mount, bindings, different namespaces, etc.), the match does
_not_ depend on which one we are using for access.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2007-07-22 12:04:18 +00:00
|
|
|
__cacheline_aligned_in_smp DEFINE_SEQLOCK(rename_lock);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2011-01-07 06:49:37 +00:00
|
|
|
EXPORT_SYMBOL(rename_lock);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2023-10-11 16:55:00 +00:00
|
|
|
static struct kmem_cache *dentry_cache __ro_after_init;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2017-07-04 16:25:22 +00:00
|
|
|
const struct qstr empty_name = QSTR_INIT("", 0);
|
|
|
|
EXPORT_SYMBOL(empty_name);
|
|
|
|
const struct qstr slash_name = QSTR_INIT("/", 1);
|
|
|
|
EXPORT_SYMBOL(slash_name);
|
2021-04-15 23:46:50 +00:00
|
|
|
const struct qstr dotdot_name = QSTR_INIT("..", 2);
|
|
|
|
EXPORT_SYMBOL(dotdot_name);
|
2017-07-04 16:25:22 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* This is the single most critical data structure when it comes
|
|
|
|
* to the dcache: the hashtable for lookups. Somebody should try
|
|
|
|
* to make this good - I've just made it work.
|
|
|
|
*
|
|
|
|
* This hash-function tries to avoid losing too many bits of hash
|
|
|
|
* information, yet avoid using a prime hash-size or similar.
|
2024-08-29 18:20:49 +00:00
|
|
|
*
|
|
|
|
* Marking the variables "used" ensures that the compiler doesn't
|
|
|
|
* optimize them away completely on architectures with runtime
|
|
|
|
* constant infrastructure, this allows debuggers to see their
|
|
|
|
* values. But updating these values has no effect on those arches.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
|
|
|
|
2024-08-29 18:20:49 +00:00
|
|
|
static unsigned int d_hash_shift __ro_after_init __used;
|
2011-01-07 06:50:05 +00:00
|
|
|
|
2024-08-29 18:20:49 +00:00
|
|
|
static struct hlist_bl_head *dentry_hashtable __ro_after_init __used;
|
2011-01-07 06:50:05 +00:00
|
|
|
|
vfs: dcache: move hashlen_hash() from callers into d_hash()
Both __d_lookup_rcu() and __d_lookup_rcu_op_compare() have the full
'name_hash' value of the qstr that they want to look up, and mask it off
to just the low 32-bit hash before calling down to d_hash().
Other callers just load the 32-bit hash and pass it as the argument.
If we move the masking into d_hash() itself, it simplifies the two
callers that currently do the masking, and is a no-op for the other
cases. It doesn't actually change the generated code since the compiler
will inline d_hash() and see that the end result is the same.
[ Technically, since the parse tree changes, the code generation may not
be 100% the same, and for me on x86-64, this does result in gcc
switching the operands around for one 'cmpl' instruction. So not
necessarily the exact same code generation, but equivalent ]
However, this does encapsulate the 'd_hash()' operation more, and makes
the shift operation in particular be a "shift 32 bits right, return full
word". Which matches the instruction semantics on both x86-64 and arm64
better, since a 32-bit shift will clear the upper bits.
That makes the next step of introducing a "shift by runtime constant"
more obvious and generates the shift with no extraneous type masking.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2024-06-10 18:47:06 +00:00
|
|
|
static inline struct hlist_bl_head *d_hash(unsigned long hashlen)
|
2011-01-07 06:50:05 +00:00
|
|
|
{
|
2024-06-04 19:30:02 +00:00
|
|
|
return runtime_const_ptr(dentry_hashtable) +
|
|
|
|
runtime_const_shift_right_32(hashlen, d_hash_shift);
|
2011-01-07 06:50:05 +00:00
|
|
|
}
|
|
|
|
|
2016-04-15 06:42:04 +00:00
|
|
|
#define IN_LOOKUP_SHIFT 10
|
|
|
|
static struct hlist_bl_head in_lookup_hashtable[1 << IN_LOOKUP_SHIFT];
|
|
|
|
|
|
|
|
static inline struct hlist_bl_head *in_lookup_hash(const struct dentry *parent,
|
|
|
|
unsigned int hash)
|
|
|
|
{
|
|
|
|
hash += (unsigned long) parent / L1_CACHE_BYTES;
|
|
|
|
return in_lookup_hashtable + hash_32(hash, IN_LOOKUP_SHIFT);
|
|
|
|
}
|
|
|
|
|
2022-01-22 06:12:59 +00:00
|
|
|
struct dentry_stat_t {
|
|
|
|
long nr_dentry;
|
|
|
|
long nr_unused;
|
|
|
|
long age_limit; /* age in seconds */
|
|
|
|
long want_pages; /* pages requested by system */
|
|
|
|
long nr_negative; /* # of unused negative dentries */
|
|
|
|
long dummy; /* Reserved for future use */
|
2005-04-16 22:20:36 +00:00
|
|
|
};
|
|
|
|
|
fs: bump inode and dentry counters to long
This series reworks our current object cache shrinking infrastructure in
two main ways:
* Noticing that a lot of users copy and paste their own version of LRU
lists for objects, we put some effort in providing a generic version.
It is modeled after the filesystem users: dentries, inodes, and xfs
(for various tasks), but we expect that other users could benefit in
the near future with little or no modification. Let us know if you
have any issues.
* The underlying list_lru being proposed automatically and
transparently keeps the elements in per-node lists, and is able to
manipulate the node lists individually. Given this infrastructure, we
are able to modify the up-to-now hammer called shrink_slab to proceed
with node-reclaim instead of always searching memory from all over like
it has been doing.
Per-node lru lists are also expected to lead to less contention in the lru
locks on multi-node scans, since we are now no longer fighting for a
global lock. The locks usually disappear from the profilers with this
change.
Although we have no official benchmarks for this version - be our guest to
independently evaluate this - earlier versions of this series were
performance tested (details at
http://permalink.gmane.org/gmane.linux.kernel.mm/100537) yielding no
visible performance regressions while yielding a better qualitative
behavior in NUMA machines.
With this infrastructure in place, we can use the list_lru entry point to
provide memcg isolation and per-memcg targeted reclaim. Historically,
those two pieces of work have been posted together. This version presents
only the infrastructure work, deferring the memcg work for a later time,
so we can focus on getting this part tested. You can see more about the
history of such work at http://lwn.net/Articles/552769/
Dave Chinner (18):
dcache: convert dentry_stat.nr_unused to per-cpu counters
dentry: move to per-sb LRU locks
dcache: remove dentries from LRU before putting on dispose list
mm: new shrinker API
shrinker: convert superblock shrinkers to new API
list: add a new LRU list type
inode: convert inode lru list to generic lru list code.
dcache: convert to use new lru list infrastructure
list_lru: per-node list infrastructure
shrinker: add node awareness
fs: convert inode and dentry shrinking to be node aware
xfs: convert buftarg LRU to generic code
xfs: rework buffer dispose list tracking
xfs: convert dquot cache lru to list_lru
fs: convert fs shrinkers to new scan/count API
drivers: convert shrinkers to new count/scan API
shrinker: convert remaining shrinkers to count/scan API
shrinker: Kill old ->shrink API.
Glauber Costa (7):
fs: bump inode and dentry counters to long
super: fix calculation of shrinkable objects for small numbers
list_lru: per-node API
vmscan: per-node deferred work
i915: bail out earlier when shrinker cannot acquire mutex
hugepage: convert huge zero page shrinker to new shrinker API
list_lru: dynamically adjust node arrays
This patch:
There are situations in very large machines in which we can have a large
quantity of dirty inodes, unused dentries, etc. This is particularly true
when umounting a filesystem, where eventually since every live object will
eventually be discarded.
Dave Chinner reported a problem with this while experimenting with the
shrinker revamp patchset. So we believe it is time for a change. This
patch just moves int to longs. Machines where it matters should have a
big long anyway.
Signed-off-by: Glauber Costa <glommer@openvz.org>
Cc: Dave Chinner <dchinner@redhat.com>
Cc: "Theodore Ts'o" <tytso@mit.edu>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Cc: Arve Hjønnevåg <arve@android.com>
Cc: Carlos Maiolino <cmaiolino@redhat.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Chuck Lever <chuck.lever@oracle.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Dave Chinner <dchinner@redhat.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Gleb Natapov <gleb@redhat.com>
Cc: Greg Thelen <gthelen@google.com>
Cc: J. Bruce Fields <bfields@redhat.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Jerome Glisse <jglisse@redhat.com>
Cc: John Stultz <john.stultz@linaro.org>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Kent Overstreet <koverstreet@google.com>
Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Steven Whitehouse <swhiteho@redhat.com>
Cc: Thomas Hellstrom <thellstrom@vmware.com>
Cc: Trond Myklebust <Trond.Myklebust@netapp.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2013-08-28 00:17:53 +00:00
|
|
|
static DEFINE_PER_CPU(long, nr_dentry);
|
2013-08-28 00:17:54 +00:00
|
|
|
static DEFINE_PER_CPU(long, nr_dentry_unused);
|
2019-01-30 18:52:38 +00:00
|
|
|
static DEFINE_PER_CPU(long, nr_dentry_negative);
|
2010-10-10 09:36:23 +00:00
|
|
|
|
|
|
|
#if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS)
|
2022-01-22 06:12:59 +00:00
|
|
|
/* Statistics gathering. */
|
|
|
|
static struct dentry_stat_t dentry_stat = {
|
|
|
|
.age_limit = 45,
|
|
|
|
};
|
2013-08-28 00:17:54 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Here we resort to our own counters instead of using generic per-cpu counters
|
|
|
|
* for consistency with what the vfs inode code does. We are expected to harvest
|
|
|
|
* better code and performance by having our own specialized counters.
|
|
|
|
*
|
|
|
|
* Please note that the loop is done over all possible CPUs, not over all online
|
|
|
|
* CPUs. The reason for this is that we don't want to play games with CPUs going
|
|
|
|
* on and off. If one of them goes off, we will just keep their counters.
|
|
|
|
*
|
|
|
|
* glommer: See cffbc8a for details, and if you ever intend to change this,
|
|
|
|
* please update all vfs counters to match.
|
|
|
|
*/
|
fs: bump inode and dentry counters to long
This series reworks our current object cache shrinking infrastructure in
two main ways:
* Noticing that a lot of users copy and paste their own version of LRU
lists for objects, we put some effort in providing a generic version.
It is modeled after the filesystem users: dentries, inodes, and xfs
(for various tasks), but we expect that other users could benefit in
the near future with little or no modification. Let us know if you
have any issues.
* The underlying list_lru being proposed automatically and
transparently keeps the elements in per-node lists, and is able to
manipulate the node lists individually. Given this infrastructure, we
are able to modify the up-to-now hammer called shrink_slab to proceed
with node-reclaim instead of always searching memory from all over like
it has been doing.
Per-node lru lists are also expected to lead to less contention in the lru
locks on multi-node scans, since we are now no longer fighting for a
global lock. The locks usually disappear from the profilers with this
change.
Although we have no official benchmarks for this version - be our guest to
independently evaluate this - earlier versions of this series were
performance tested (details at
http://permalink.gmane.org/gmane.linux.kernel.mm/100537) yielding no
visible performance regressions while yielding a better qualitative
behavior in NUMA machines.
With this infrastructure in place, we can use the list_lru entry point to
provide memcg isolation and per-memcg targeted reclaim. Historically,
those two pieces of work have been posted together. This version presents
only the infrastructure work, deferring the memcg work for a later time,
so we can focus on getting this part tested. You can see more about the
history of such work at http://lwn.net/Articles/552769/
Dave Chinner (18):
dcache: convert dentry_stat.nr_unused to per-cpu counters
dentry: move to per-sb LRU locks
dcache: remove dentries from LRU before putting on dispose list
mm: new shrinker API
shrinker: convert superblock shrinkers to new API
list: add a new LRU list type
inode: convert inode lru list to generic lru list code.
dcache: convert to use new lru list infrastructure
list_lru: per-node list infrastructure
shrinker: add node awareness
fs: convert inode and dentry shrinking to be node aware
xfs: convert buftarg LRU to generic code
xfs: rework buffer dispose list tracking
xfs: convert dquot cache lru to list_lru
fs: convert fs shrinkers to new scan/count API
drivers: convert shrinkers to new count/scan API
shrinker: convert remaining shrinkers to count/scan API
shrinker: Kill old ->shrink API.
Glauber Costa (7):
fs: bump inode and dentry counters to long
super: fix calculation of shrinkable objects for small numbers
list_lru: per-node API
vmscan: per-node deferred work
i915: bail out earlier when shrinker cannot acquire mutex
hugepage: convert huge zero page shrinker to new shrinker API
list_lru: dynamically adjust node arrays
This patch:
There are situations in very large machines in which we can have a large
quantity of dirty inodes, unused dentries, etc. This is particularly true
when umounting a filesystem, where eventually since every live object will
eventually be discarded.
Dave Chinner reported a problem with this while experimenting with the
shrinker revamp patchset. So we believe it is time for a change. This
patch just moves int to longs. Machines where it matters should have a
big long anyway.
Signed-off-by: Glauber Costa <glommer@openvz.org>
Cc: Dave Chinner <dchinner@redhat.com>
Cc: "Theodore Ts'o" <tytso@mit.edu>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Cc: Arve Hjønnevåg <arve@android.com>
Cc: Carlos Maiolino <cmaiolino@redhat.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Chuck Lever <chuck.lever@oracle.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Dave Chinner <dchinner@redhat.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Gleb Natapov <gleb@redhat.com>
Cc: Greg Thelen <gthelen@google.com>
Cc: J. Bruce Fields <bfields@redhat.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Jerome Glisse <jglisse@redhat.com>
Cc: John Stultz <john.stultz@linaro.org>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Kent Overstreet <koverstreet@google.com>
Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Steven Whitehouse <swhiteho@redhat.com>
Cc: Thomas Hellstrom <thellstrom@vmware.com>
Cc: Trond Myklebust <Trond.Myklebust@netapp.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2013-08-28 00:17:53 +00:00
|
|
|
static long get_nr_dentry(void)
|
fs: use fast counters for vfs caches
percpu_counter library generates quite nasty code, so unless you need
to dynamically allocate counters or take fast approximate value, a
simple per cpu set of counters is much better.
The percpu_counter can never be made to work as well, because it has an
indirection from pointer to percpu memory, and it can't use direct
this_cpu_inc interfaces because it doesn't use static PER_CPU data, so
code will always be worse.
In the fastpath, it is the difference between this:
incl %gs:nr_dentry # nr_dentry
and this:
movl percpu_counter_batch(%rip), %edx # percpu_counter_batch,
movl $1, %esi #,
movq $nr_dentry, %rdi #,
call __percpu_counter_add # (plus I clobber registers)
__percpu_counter_add:
pushq %rbp #
movq %rsp, %rbp #,
subq $32, %rsp #,
movq %rbx, -24(%rbp) #,
movq %r12, -16(%rbp) #,
movq %r13, -8(%rbp) #,
movq %rdi, %rbx # fbc, fbc
#APP
# 216 "/home/npiggin/usr/src/linux-2.6/arch/x86/include/asm/thread_info.h" 1
movq %gs:kernel_stack,%rax #, pfo_ret__
# 0 "" 2
#NO_APP
incl -8124(%rax) # <variable>.preempt_count
movq 32(%rdi), %r12 # <variable>.counters, tcp_ptr__
#APP
# 78 "lib/percpu_counter.c" 1
add %gs:this_cpu_off, %r12 # this_cpu_off, tcp_ptr__
# 0 "" 2
#NO_APP
movslq (%r12),%r13 #* tcp_ptr__, tmp73
movslq %edx,%rax # batch, batch
addq %rsi, %r13 # amount, count
cmpq %rax, %r13 # batch, count
jge .L27 #,
negl %edx # tmp76
movslq %edx,%rdx # tmp76, tmp77
cmpq %rdx, %r13 # tmp77, count
jg .L28 #,
.L27:
movq %rbx, %rdi # fbc,
call _raw_spin_lock #
addq %r13, 8(%rbx) # count, <variable>.count
movq %rbx, %rdi # fbc,
movl $0, (%r12) #,* tcp_ptr__
call _raw_spin_unlock #
.L29:
#APP
# 216 "/home/npiggin/usr/src/linux-2.6/arch/x86/include/asm/thread_info.h" 1
movq %gs:kernel_stack,%rax #, pfo_ret__
# 0 "" 2
#NO_APP
decl -8124(%rax) # <variable>.preempt_count
movq -8136(%rax), %rax #, D.14625
testb $8, %al #, D.14625
jne .L32 #,
.L31:
movq -24(%rbp), %rbx #,
movq -16(%rbp), %r12 #,
movq -8(%rbp), %r13 #,
leave
ret
.p2align 4,,10
.p2align 3
.L28:
movl %r13d, (%r12) # count,*
jmp .L29 #
.L32:
call preempt_schedule #
.p2align 4,,6
jmp .L31 #
.size __percpu_counter_add, .-__percpu_counter_add
.p2align 4,,15
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:19 +00:00
|
|
|
{
|
|
|
|
int i;
|
fs: bump inode and dentry counters to long
This series reworks our current object cache shrinking infrastructure in
two main ways:
* Noticing that a lot of users copy and paste their own version of LRU
lists for objects, we put some effort in providing a generic version.
It is modeled after the filesystem users: dentries, inodes, and xfs
(for various tasks), but we expect that other users could benefit in
the near future with little or no modification. Let us know if you
have any issues.
* The underlying list_lru being proposed automatically and
transparently keeps the elements in per-node lists, and is able to
manipulate the node lists individually. Given this infrastructure, we
are able to modify the up-to-now hammer called shrink_slab to proceed
with node-reclaim instead of always searching memory from all over like
it has been doing.
Per-node lru lists are also expected to lead to less contention in the lru
locks on multi-node scans, since we are now no longer fighting for a
global lock. The locks usually disappear from the profilers with this
change.
Although we have no official benchmarks for this version - be our guest to
independently evaluate this - earlier versions of this series were
performance tested (details at
http://permalink.gmane.org/gmane.linux.kernel.mm/100537) yielding no
visible performance regressions while yielding a better qualitative
behavior in NUMA machines.
With this infrastructure in place, we can use the list_lru entry point to
provide memcg isolation and per-memcg targeted reclaim. Historically,
those two pieces of work have been posted together. This version presents
only the infrastructure work, deferring the memcg work for a later time,
so we can focus on getting this part tested. You can see more about the
history of such work at http://lwn.net/Articles/552769/
Dave Chinner (18):
dcache: convert dentry_stat.nr_unused to per-cpu counters
dentry: move to per-sb LRU locks
dcache: remove dentries from LRU before putting on dispose list
mm: new shrinker API
shrinker: convert superblock shrinkers to new API
list: add a new LRU list type
inode: convert inode lru list to generic lru list code.
dcache: convert to use new lru list infrastructure
list_lru: per-node list infrastructure
shrinker: add node awareness
fs: convert inode and dentry shrinking to be node aware
xfs: convert buftarg LRU to generic code
xfs: rework buffer dispose list tracking
xfs: convert dquot cache lru to list_lru
fs: convert fs shrinkers to new scan/count API
drivers: convert shrinkers to new count/scan API
shrinker: convert remaining shrinkers to count/scan API
shrinker: Kill old ->shrink API.
Glauber Costa (7):
fs: bump inode and dentry counters to long
super: fix calculation of shrinkable objects for small numbers
list_lru: per-node API
vmscan: per-node deferred work
i915: bail out earlier when shrinker cannot acquire mutex
hugepage: convert huge zero page shrinker to new shrinker API
list_lru: dynamically adjust node arrays
This patch:
There are situations in very large machines in which we can have a large
quantity of dirty inodes, unused dentries, etc. This is particularly true
when umounting a filesystem, where eventually since every live object will
eventually be discarded.
Dave Chinner reported a problem with this while experimenting with the
shrinker revamp patchset. So we believe it is time for a change. This
patch just moves int to longs. Machines where it matters should have a
big long anyway.
Signed-off-by: Glauber Costa <glommer@openvz.org>
Cc: Dave Chinner <dchinner@redhat.com>
Cc: "Theodore Ts'o" <tytso@mit.edu>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Cc: Arve Hjønnevåg <arve@android.com>
Cc: Carlos Maiolino <cmaiolino@redhat.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Chuck Lever <chuck.lever@oracle.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Dave Chinner <dchinner@redhat.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Gleb Natapov <gleb@redhat.com>
Cc: Greg Thelen <gthelen@google.com>
Cc: J. Bruce Fields <bfields@redhat.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Jerome Glisse <jglisse@redhat.com>
Cc: John Stultz <john.stultz@linaro.org>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Kent Overstreet <koverstreet@google.com>
Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Steven Whitehouse <swhiteho@redhat.com>
Cc: Thomas Hellstrom <thellstrom@vmware.com>
Cc: Trond Myklebust <Trond.Myklebust@netapp.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2013-08-28 00:17:53 +00:00
|
|
|
long sum = 0;
|
fs: use fast counters for vfs caches
percpu_counter library generates quite nasty code, so unless you need
to dynamically allocate counters or take fast approximate value, a
simple per cpu set of counters is much better.
The percpu_counter can never be made to work as well, because it has an
indirection from pointer to percpu memory, and it can't use direct
this_cpu_inc interfaces because it doesn't use static PER_CPU data, so
code will always be worse.
In the fastpath, it is the difference between this:
incl %gs:nr_dentry # nr_dentry
and this:
movl percpu_counter_batch(%rip), %edx # percpu_counter_batch,
movl $1, %esi #,
movq $nr_dentry, %rdi #,
call __percpu_counter_add # (plus I clobber registers)
__percpu_counter_add:
pushq %rbp #
movq %rsp, %rbp #,
subq $32, %rsp #,
movq %rbx, -24(%rbp) #,
movq %r12, -16(%rbp) #,
movq %r13, -8(%rbp) #,
movq %rdi, %rbx # fbc, fbc
#APP
# 216 "/home/npiggin/usr/src/linux-2.6/arch/x86/include/asm/thread_info.h" 1
movq %gs:kernel_stack,%rax #, pfo_ret__
# 0 "" 2
#NO_APP
incl -8124(%rax) # <variable>.preempt_count
movq 32(%rdi), %r12 # <variable>.counters, tcp_ptr__
#APP
# 78 "lib/percpu_counter.c" 1
add %gs:this_cpu_off, %r12 # this_cpu_off, tcp_ptr__
# 0 "" 2
#NO_APP
movslq (%r12),%r13 #* tcp_ptr__, tmp73
movslq %edx,%rax # batch, batch
addq %rsi, %r13 # amount, count
cmpq %rax, %r13 # batch, count
jge .L27 #,
negl %edx # tmp76
movslq %edx,%rdx # tmp76, tmp77
cmpq %rdx, %r13 # tmp77, count
jg .L28 #,
.L27:
movq %rbx, %rdi # fbc,
call _raw_spin_lock #
addq %r13, 8(%rbx) # count, <variable>.count
movq %rbx, %rdi # fbc,
movl $0, (%r12) #,* tcp_ptr__
call _raw_spin_unlock #
.L29:
#APP
# 216 "/home/npiggin/usr/src/linux-2.6/arch/x86/include/asm/thread_info.h" 1
movq %gs:kernel_stack,%rax #, pfo_ret__
# 0 "" 2
#NO_APP
decl -8124(%rax) # <variable>.preempt_count
movq -8136(%rax), %rax #, D.14625
testb $8, %al #, D.14625
jne .L32 #,
.L31:
movq -24(%rbp), %rbx #,
movq -16(%rbp), %r12 #,
movq -8(%rbp), %r13 #,
leave
ret
.p2align 4,,10
.p2align 3
.L28:
movl %r13d, (%r12) # count,*
jmp .L29 #
.L32:
call preempt_schedule #
.p2align 4,,6
jmp .L31 #
.size __percpu_counter_add, .-__percpu_counter_add
.p2align 4,,15
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:19 +00:00
|
|
|
for_each_possible_cpu(i)
|
|
|
|
sum += per_cpu(nr_dentry, i);
|
|
|
|
return sum < 0 ? 0 : sum;
|
|
|
|
}
|
|
|
|
|
2013-08-28 00:17:54 +00:00
|
|
|
static long get_nr_dentry_unused(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
long sum = 0;
|
|
|
|
for_each_possible_cpu(i)
|
|
|
|
sum += per_cpu(nr_dentry_unused, i);
|
|
|
|
return sum < 0 ? 0 : sum;
|
|
|
|
}
|
|
|
|
|
2019-01-30 18:52:38 +00:00
|
|
|
static long get_nr_dentry_negative(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
long sum = 0;
|
|
|
|
|
|
|
|
for_each_possible_cpu(i)
|
|
|
|
sum += per_cpu(nr_dentry_negative, i);
|
|
|
|
return sum < 0 ? 0 : sum;
|
|
|
|
}
|
|
|
|
|
sysctl: treewide: constify the ctl_table argument of proc_handlers
const qualify the struct ctl_table argument in the proc_handler function
signatures. This is a prerequisite to moving the static ctl_table
structs into .rodata data which will ensure that proc_handler function
pointers cannot be modified.
This patch has been generated by the following coccinelle script:
```
virtual patch
@r1@
identifier ctl, write, buffer, lenp, ppos;
identifier func !~ "appldata_(timer|interval)_handler|sched_(rt|rr)_handler|rds_tcp_skbuf_handler|proc_sctp_do_(hmac_alg|rto_min|rto_max|udp_port|alpha_beta|auth|probe_interval)";
@@
int func(
- struct ctl_table *ctl
+ const struct ctl_table *ctl
,int write, void *buffer, size_t *lenp, loff_t *ppos);
@r2@
identifier func, ctl, write, buffer, lenp, ppos;
@@
int func(
- struct ctl_table *ctl
+ const struct ctl_table *ctl
,int write, void *buffer, size_t *lenp, loff_t *ppos)
{ ... }
@r3@
identifier func;
@@
int func(
- struct ctl_table *
+ const struct ctl_table *
,int , void *, size_t *, loff_t *);
@r4@
identifier func, ctl;
@@
int func(
- struct ctl_table *ctl
+ const struct ctl_table *ctl
,int , void *, size_t *, loff_t *);
@r5@
identifier func, write, buffer, lenp, ppos;
@@
int func(
- struct ctl_table *
+ const struct ctl_table *
,int write, void *buffer, size_t *lenp, loff_t *ppos);
```
* Code formatting was adjusted in xfs_sysctl.c to comply with code
conventions. The xfs_stats_clear_proc_handler,
xfs_panic_mask_proc_handler and xfs_deprecated_dointvec_minmax where
adjusted.
* The ctl_table argument in proc_watchdog_common was const qualified.
This is called from a proc_handler itself and is calling back into
another proc_handler, making it necessary to change it as part of the
proc_handler migration.
Co-developed-by: Thomas Weißschuh <linux@weissschuh.net>
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Co-developed-by: Joel Granados <j.granados@samsung.com>
Signed-off-by: Joel Granados <j.granados@samsung.com>
2024-07-24 18:59:29 +00:00
|
|
|
static int proc_nr_dentry(const struct ctl_table *table, int write, void *buffer,
|
2022-01-22 06:12:59 +00:00
|
|
|
size_t *lenp, loff_t *ppos)
|
2010-10-10 09:36:23 +00:00
|
|
|
{
|
fs: use fast counters for vfs caches
percpu_counter library generates quite nasty code, so unless you need
to dynamically allocate counters or take fast approximate value, a
simple per cpu set of counters is much better.
The percpu_counter can never be made to work as well, because it has an
indirection from pointer to percpu memory, and it can't use direct
this_cpu_inc interfaces because it doesn't use static PER_CPU data, so
code will always be worse.
In the fastpath, it is the difference between this:
incl %gs:nr_dentry # nr_dentry
and this:
movl percpu_counter_batch(%rip), %edx # percpu_counter_batch,
movl $1, %esi #,
movq $nr_dentry, %rdi #,
call __percpu_counter_add # (plus I clobber registers)
__percpu_counter_add:
pushq %rbp #
movq %rsp, %rbp #,
subq $32, %rsp #,
movq %rbx, -24(%rbp) #,
movq %r12, -16(%rbp) #,
movq %r13, -8(%rbp) #,
movq %rdi, %rbx # fbc, fbc
#APP
# 216 "/home/npiggin/usr/src/linux-2.6/arch/x86/include/asm/thread_info.h" 1
movq %gs:kernel_stack,%rax #, pfo_ret__
# 0 "" 2
#NO_APP
incl -8124(%rax) # <variable>.preempt_count
movq 32(%rdi), %r12 # <variable>.counters, tcp_ptr__
#APP
# 78 "lib/percpu_counter.c" 1
add %gs:this_cpu_off, %r12 # this_cpu_off, tcp_ptr__
# 0 "" 2
#NO_APP
movslq (%r12),%r13 #* tcp_ptr__, tmp73
movslq %edx,%rax # batch, batch
addq %rsi, %r13 # amount, count
cmpq %rax, %r13 # batch, count
jge .L27 #,
negl %edx # tmp76
movslq %edx,%rdx # tmp76, tmp77
cmpq %rdx, %r13 # tmp77, count
jg .L28 #,
.L27:
movq %rbx, %rdi # fbc,
call _raw_spin_lock #
addq %r13, 8(%rbx) # count, <variable>.count
movq %rbx, %rdi # fbc,
movl $0, (%r12) #,* tcp_ptr__
call _raw_spin_unlock #
.L29:
#APP
# 216 "/home/npiggin/usr/src/linux-2.6/arch/x86/include/asm/thread_info.h" 1
movq %gs:kernel_stack,%rax #, pfo_ret__
# 0 "" 2
#NO_APP
decl -8124(%rax) # <variable>.preempt_count
movq -8136(%rax), %rax #, D.14625
testb $8, %al #, D.14625
jne .L32 #,
.L31:
movq -24(%rbp), %rbx #,
movq -16(%rbp), %r12 #,
movq -8(%rbp), %r13 #,
leave
ret
.p2align 4,,10
.p2align 3
.L28:
movl %r13d, (%r12) # count,*
jmp .L29 #
.L32:
call preempt_schedule #
.p2align 4,,6
jmp .L31 #
.size __percpu_counter_add, .-__percpu_counter_add
.p2align 4,,15
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:19 +00:00
|
|
|
dentry_stat.nr_dentry = get_nr_dentry();
|
2013-08-28 00:17:54 +00:00
|
|
|
dentry_stat.nr_unused = get_nr_dentry_unused();
|
2019-01-30 18:52:38 +00:00
|
|
|
dentry_stat.nr_negative = get_nr_dentry_negative();
|
fs: bump inode and dentry counters to long
This series reworks our current object cache shrinking infrastructure in
two main ways:
* Noticing that a lot of users copy and paste their own version of LRU
lists for objects, we put some effort in providing a generic version.
It is modeled after the filesystem users: dentries, inodes, and xfs
(for various tasks), but we expect that other users could benefit in
the near future with little or no modification. Let us know if you
have any issues.
* The underlying list_lru being proposed automatically and
transparently keeps the elements in per-node lists, and is able to
manipulate the node lists individually. Given this infrastructure, we
are able to modify the up-to-now hammer called shrink_slab to proceed
with node-reclaim instead of always searching memory from all over like
it has been doing.
Per-node lru lists are also expected to lead to less contention in the lru
locks on multi-node scans, since we are now no longer fighting for a
global lock. The locks usually disappear from the profilers with this
change.
Although we have no official benchmarks for this version - be our guest to
independently evaluate this - earlier versions of this series were
performance tested (details at
http://permalink.gmane.org/gmane.linux.kernel.mm/100537) yielding no
visible performance regressions while yielding a better qualitative
behavior in NUMA machines.
With this infrastructure in place, we can use the list_lru entry point to
provide memcg isolation and per-memcg targeted reclaim. Historically,
those two pieces of work have been posted together. This version presents
only the infrastructure work, deferring the memcg work for a later time,
so we can focus on getting this part tested. You can see more about the
history of such work at http://lwn.net/Articles/552769/
Dave Chinner (18):
dcache: convert dentry_stat.nr_unused to per-cpu counters
dentry: move to per-sb LRU locks
dcache: remove dentries from LRU before putting on dispose list
mm: new shrinker API
shrinker: convert superblock shrinkers to new API
list: add a new LRU list type
inode: convert inode lru list to generic lru list code.
dcache: convert to use new lru list infrastructure
list_lru: per-node list infrastructure
shrinker: add node awareness
fs: convert inode and dentry shrinking to be node aware
xfs: convert buftarg LRU to generic code
xfs: rework buffer dispose list tracking
xfs: convert dquot cache lru to list_lru
fs: convert fs shrinkers to new scan/count API
drivers: convert shrinkers to new count/scan API
shrinker: convert remaining shrinkers to count/scan API
shrinker: Kill old ->shrink API.
Glauber Costa (7):
fs: bump inode and dentry counters to long
super: fix calculation of shrinkable objects for small numbers
list_lru: per-node API
vmscan: per-node deferred work
i915: bail out earlier when shrinker cannot acquire mutex
hugepage: convert huge zero page shrinker to new shrinker API
list_lru: dynamically adjust node arrays
This patch:
There are situations in very large machines in which we can have a large
quantity of dirty inodes, unused dentries, etc. This is particularly true
when umounting a filesystem, where eventually since every live object will
eventually be discarded.
Dave Chinner reported a problem with this while experimenting with the
shrinker revamp patchset. So we believe it is time for a change. This
patch just moves int to longs. Machines where it matters should have a
big long anyway.
Signed-off-by: Glauber Costa <glommer@openvz.org>
Cc: Dave Chinner <dchinner@redhat.com>
Cc: "Theodore Ts'o" <tytso@mit.edu>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Cc: Arve Hjønnevåg <arve@android.com>
Cc: Carlos Maiolino <cmaiolino@redhat.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Chuck Lever <chuck.lever@oracle.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Dave Chinner <dchinner@redhat.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Gleb Natapov <gleb@redhat.com>
Cc: Greg Thelen <gthelen@google.com>
Cc: J. Bruce Fields <bfields@redhat.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Jerome Glisse <jglisse@redhat.com>
Cc: John Stultz <john.stultz@linaro.org>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Kent Overstreet <koverstreet@google.com>
Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Steven Whitehouse <swhiteho@redhat.com>
Cc: Thomas Hellstrom <thellstrom@vmware.com>
Cc: Trond Myklebust <Trond.Myklebust@netapp.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2013-08-28 00:17:53 +00:00
|
|
|
return proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
|
2010-10-10 09:36:23 +00:00
|
|
|
}
|
2022-01-22 06:12:59 +00:00
|
|
|
|
|
|
|
static struct ctl_table fs_dcache_sysctls[] = {
|
|
|
|
{
|
|
|
|
.procname = "dentry-state",
|
|
|
|
.data = &dentry_stat,
|
|
|
|
.maxlen = 6*sizeof(long),
|
|
|
|
.mode = 0444,
|
|
|
|
.proc_handler = proc_nr_dentry,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
static int __init init_fs_dcache_sysctls(void)
|
|
|
|
{
|
|
|
|
register_sysctl_init("fs", fs_dcache_sysctls);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
fs_initcall(init_fs_dcache_sysctls);
|
2010-10-10 09:36:23 +00:00
|
|
|
#endif
|
|
|
|
|
2012-03-04 23:51:42 +00:00
|
|
|
/*
|
|
|
|
* Compare 2 name strings, return 0 if they match, otherwise non-zero.
|
|
|
|
* The strings are both count bytes long, and count is non-zero.
|
|
|
|
*/
|
2012-05-03 17:16:43 +00:00
|
|
|
#ifdef CONFIG_DCACHE_WORD_ACCESS
|
|
|
|
|
|
|
|
#include <asm/word-at-a-time.h>
|
|
|
|
/*
|
|
|
|
* NOTE! 'cs' and 'scount' come from a dentry, so it has a
|
|
|
|
* aligned allocation for this particular component. We don't
|
|
|
|
* strictly need the load_unaligned_zeropad() safety, but it
|
|
|
|
* doesn't hurt either.
|
|
|
|
*
|
|
|
|
* In contrast, 'ct' and 'tcount' can be from a pathname, and do
|
|
|
|
* need the careful unaligned handling.
|
|
|
|
*/
|
2012-05-10 19:19:19 +00:00
|
|
|
static inline int dentry_string_cmp(const unsigned char *cs, const unsigned char *ct, unsigned tcount)
|
2012-03-04 23:51:42 +00:00
|
|
|
{
|
2012-03-06 19:16:17 +00:00
|
|
|
unsigned long a,b,mask;
|
|
|
|
|
|
|
|
for (;;) {
|
2018-02-01 18:00:51 +00:00
|
|
|
a = read_word_at_a_time(cs);
|
2012-05-03 17:16:43 +00:00
|
|
|
b = load_unaligned_zeropad(ct);
|
2012-03-06 19:16:17 +00:00
|
|
|
if (tcount < sizeof(unsigned long))
|
|
|
|
break;
|
|
|
|
if (unlikely(a != b))
|
|
|
|
return 1;
|
|
|
|
cs += sizeof(unsigned long);
|
|
|
|
ct += sizeof(unsigned long);
|
|
|
|
tcount -= sizeof(unsigned long);
|
|
|
|
if (!tcount)
|
|
|
|
return 0;
|
|
|
|
}
|
2013-12-12 17:40:21 +00:00
|
|
|
mask = bytemask_from_count(tcount);
|
2012-03-06 19:16:17 +00:00
|
|
|
return unlikely(!!((a ^ b) & mask));
|
2012-05-03 17:16:43 +00:00
|
|
|
}
|
|
|
|
|
2012-03-06 19:16:17 +00:00
|
|
|
#else
|
2012-05-03 17:16:43 +00:00
|
|
|
|
2012-05-10 19:19:19 +00:00
|
|
|
static inline int dentry_string_cmp(const unsigned char *cs, const unsigned char *ct, unsigned tcount)
|
2012-05-03 17:16:43 +00:00
|
|
|
{
|
2012-03-04 23:51:42 +00:00
|
|
|
do {
|
|
|
|
if (*cs != *ct)
|
|
|
|
return 1;
|
|
|
|
cs++;
|
|
|
|
ct++;
|
|
|
|
tcount--;
|
|
|
|
} while (tcount);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-05-03 17:16:43 +00:00
|
|
|
#endif
|
|
|
|
|
2012-05-10 19:19:19 +00:00
|
|
|
static inline int dentry_cmp(const struct dentry *dentry, const unsigned char *ct, unsigned tcount)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Be careful about RCU walk racing with rename:
|
2017-10-24 10:22:48 +00:00
|
|
|
* use 'READ_ONCE' to fetch the name pointer.
|
2012-05-10 19:19:19 +00:00
|
|
|
*
|
|
|
|
* NOTE! Even if a rename will mean that the length
|
|
|
|
* was not loaded atomically, we don't care. The
|
|
|
|
* RCU walk will check the sequence count eventually,
|
|
|
|
* and catch it. And we won't overrun the buffer,
|
|
|
|
* because we're reading the name pointer atomically,
|
|
|
|
* and a dentry name is guaranteed to be properly
|
|
|
|
* terminated with a NUL byte.
|
|
|
|
*
|
|
|
|
* End result: even if 'len' is wrong, we'll exit
|
|
|
|
* early because the data cannot match (there can
|
|
|
|
* be no NUL in the ct/tcount data)
|
|
|
|
*/
|
2017-10-24 10:22:48 +00:00
|
|
|
const unsigned char *cs = READ_ONCE(dentry->d_name.name);
|
2016-03-26 09:12:10 +00:00
|
|
|
|
2012-05-21 23:14:04 +00:00
|
|
|
return dentry_string_cmp(cs, ct, tcount);
|
2012-05-10 19:19:19 +00:00
|
|
|
}
|
|
|
|
|
Allow sharing external names after __d_move()
* external dentry names get a small structure prepended to them
(struct external_name).
* it contains an atomic refcount, matching the number of struct dentry
instances that have ->d_name.name pointing to that external name. The
first thing free_dentry() does is decrementing refcount of external name,
so the instances that are between the call of free_dentry() and
RCU-delayed actual freeing do not contribute.
* __d_move(x, y, false) makes the name of x equal to the name of y,
external or not. If y has an external name, extra reference is grabbed
and put into x->d_name.name. If x used to have an external name, the
reference to the old name is dropped and, should it reach zero, freeing
is scheduled via kfree_rcu().
* free_dentry() in dentry with external name decrements the refcount of
that name and, should it reach zero, does RCU-delayed call that will
free both the dentry and external name. Otherwise it does what it
used to do, except that __d_free() doesn't even look at ->d_name.name;
it simply frees the dentry.
All non-RCU accesses to dentry external name are safe wrt freeing since they
all should happen before free_dentry() is called. RCU accesses might run
into a dentry seen by free_dentry() or into an old name that got already
dropped by __d_move(); however, in both cases dentry must have been
alive and refer to that name at some point after we'd done rcu_read_lock(),
which means that any freeing must be still pending.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2014-09-29 18:54:27 +00:00
|
|
|
struct external_name {
|
|
|
|
union {
|
|
|
|
atomic_t count;
|
|
|
|
struct rcu_head head;
|
|
|
|
} u;
|
|
|
|
unsigned char name[];
|
|
|
|
};
|
|
|
|
|
|
|
|
static inline struct external_name *external_name(struct dentry *dentry)
|
|
|
|
{
|
|
|
|
return container_of(dentry->d_name.name, struct external_name, name[0]);
|
|
|
|
}
|
|
|
|
|
2010-10-10 09:36:22 +00:00
|
|
|
static void __d_free(struct rcu_head *head)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2010-10-10 09:36:22 +00:00
|
|
|
struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu);
|
|
|
|
|
Allow sharing external names after __d_move()
* external dentry names get a small structure prepended to them
(struct external_name).
* it contains an atomic refcount, matching the number of struct dentry
instances that have ->d_name.name pointing to that external name. The
first thing free_dentry() does is decrementing refcount of external name,
so the instances that are between the call of free_dentry() and
RCU-delayed actual freeing do not contribute.
* __d_move(x, y, false) makes the name of x equal to the name of y,
external or not. If y has an external name, extra reference is grabbed
and put into x->d_name.name. If x used to have an external name, the
reference to the old name is dropped and, should it reach zero, freeing
is scheduled via kfree_rcu().
* free_dentry() in dentry with external name decrements the refcount of
that name and, should it reach zero, does RCU-delayed call that will
free both the dentry and external name. Otherwise it does what it
used to do, except that __d_free() doesn't even look at ->d_name.name;
it simply frees the dentry.
All non-RCU accesses to dentry external name are safe wrt freeing since they
all should happen before free_dentry() is called. RCU accesses might run
into a dentry seen by free_dentry() or into an old name that got already
dropped by __d_move(); however, in both cases dentry must have been
alive and refer to that name at some point after we'd done rcu_read_lock(),
which means that any freeing must be still pending.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2014-09-29 18:54:27 +00:00
|
|
|
kmem_cache_free(dentry_cache, dentry);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __d_free_external(struct rcu_head *head)
|
|
|
|
{
|
|
|
|
struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu);
|
2018-10-26 22:05:41 +00:00
|
|
|
kfree(external_name(dentry));
|
dcache: account external names as indirectly reclaimable memory
I received a report about suspicious growth of unreclaimable slabs on
some machines. I've found that it happens on machines with low memory
pressure, and these unreclaimable slabs are external names attached to
dentries.
External names are allocated using generic kmalloc() function, so they
are accounted as unreclaimable. But they are held by dentries, which
are reclaimable, and they will be reclaimed under the memory pressure.
In particular, this breaks MemAvailable calculation, as it doesn't take
unreclaimable slabs into account. This leads to a silly situation, when
a machine is almost idle, has no memory pressure and therefore has a big
dentry cache. And the resulting MemAvailable is too low to start a new
workload.
To address the issue, the NR_INDIRECTLY_RECLAIMABLE_BYTES counter is
used to track the amount of memory, consumed by external names. The
counter is increased in the dentry allocation path, if an external name
structure is allocated; and it's decreased in the dentry freeing path.
To reproduce the problem I've used the following Python script:
import os
for iter in range (0, 10000000):
try:
name = ("/some_long_name_%d" % iter) + "_" * 220
os.stat(name)
except Exception:
pass
Without this patch:
$ cat /proc/meminfo | grep MemAvailable
MemAvailable: 7811688 kB
$ python indirect.py
$ cat /proc/meminfo | grep MemAvailable
MemAvailable: 2753052 kB
With the patch:
$ cat /proc/meminfo | grep MemAvailable
MemAvailable: 7809516 kB
$ python indirect.py
$ cat /proc/meminfo | grep MemAvailable
MemAvailable: 7749144 kB
[guro@fb.com: fix indirectly reclaimable memory accounting for CONFIG_SLOB]
Link: http://lkml.kernel.org/r/20180312194140.19517-1-guro@fb.com
[guro@fb.com: fix indirectly reclaimable memory accounting]
Link: http://lkml.kernel.org/r/20180313125701.7955-1-guro@fb.com
Link: http://lkml.kernel.org/r/20180305133743.12746-5-guro@fb.com
Signed-off-by: Roman Gushchin <guro@fb.com>
Reviewed-by: Andrew Morton <akpm@linux-foundation.org>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Mel Gorman <mgorman@techsingularity.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2018-04-10 23:27:44 +00:00
|
|
|
kmem_cache_free(dentry_cache, dentry);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2014-10-12 16:45:37 +00:00
|
|
|
static inline int dname_external(const struct dentry *dentry)
|
|
|
|
{
|
|
|
|
return dentry->d_name.name != dentry->d_iname;
|
|
|
|
}
|
|
|
|
|
2017-07-07 18:51:19 +00:00
|
|
|
void take_dentry_name_snapshot(struct name_snapshot *name, struct dentry *dentry)
|
|
|
|
{
|
|
|
|
spin_lock(&dentry->d_lock);
|
2019-04-26 17:07:27 +00:00
|
|
|
name->name = dentry->d_name;
|
2017-07-07 18:51:19 +00:00
|
|
|
if (unlikely(dname_external(dentry))) {
|
2019-04-26 17:07:27 +00:00
|
|
|
atomic_inc(&external_name(dentry)->u.count);
|
2017-07-07 18:51:19 +00:00
|
|
|
} else {
|
2018-08-17 22:44:34 +00:00
|
|
|
memcpy(name->inline_name, dentry->d_iname,
|
|
|
|
dentry->d_name.len + 1);
|
2019-04-26 17:07:27 +00:00
|
|
|
name->name.name = name->inline_name;
|
2017-07-07 18:51:19 +00:00
|
|
|
}
|
2019-04-26 17:07:27 +00:00
|
|
|
spin_unlock(&dentry->d_lock);
|
2017-07-07 18:51:19 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(take_dentry_name_snapshot);
|
|
|
|
|
|
|
|
void release_dentry_name_snapshot(struct name_snapshot *name)
|
|
|
|
{
|
2019-04-26 17:07:27 +00:00
|
|
|
if (unlikely(name->name.name != name->inline_name)) {
|
2017-07-07 18:51:19 +00:00
|
|
|
struct external_name *p;
|
2019-04-26 17:07:27 +00:00
|
|
|
p = container_of(name->name.name, struct external_name, name[0]);
|
2017-07-07 18:51:19 +00:00
|
|
|
if (unlikely(atomic_dec_and_test(&p->u.count)))
|
2018-10-26 22:05:41 +00:00
|
|
|
kfree_rcu(p, u.head);
|
2017-07-07 18:51:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(release_dentry_name_snapshot);
|
|
|
|
|
2015-03-05 14:09:22 +00:00
|
|
|
static inline void __d_set_inode_and_type(struct dentry *dentry,
|
|
|
|
struct inode *inode,
|
|
|
|
unsigned type_flags)
|
|
|
|
{
|
|
|
|
unsigned flags;
|
|
|
|
|
|
|
|
dentry->d_inode = inode;
|
|
|
|
flags = READ_ONCE(dentry->d_flags);
|
2023-11-10 19:32:05 +00:00
|
|
|
flags &= ~DCACHE_ENTRY_TYPE;
|
2015-03-05 14:09:22 +00:00
|
|
|
flags |= type_flags;
|
fs/namei.c: fix missing barriers when checking positivity
Pinned negative dentries can, generally, be made positive
by another thread. Conditions that prevent that are
* ->d_lock on dentry in question
* parent directory held at least shared
* nobody else could have observed the address of dentry
Most of the places working with those fall into one of those
categories; however, d_lookup() and friends need to be used
with some care. Fortunately, there's not a lot of call sites,
and with few exceptions all of those fall under one of the
cases above.
Exceptions are all in fs/namei.c - in lookup_fast(), lookup_dcache()
and mountpoint_last(). Another one is lookup_slow() - there
dcache lookup is done with parent held shared, but the result
is used after we'd drop the lock. The same happens in do_last() -
the lookup (in lookup_one()) is done with parent locked, but
result is used after unlocking.
lookup_fast(), do_last() and mountpoint_last() flat-out reject
negatives.
Most of lookup_dcache() calls are made with parent locked at least
shared; the only exception is lookup_one_len_unlocked(). It might
return pinned negative, needs serious care from callers. Fortunately,
almost nobody calls it directly anymore; all but two callers have
converted to lookup_positive_unlocked(), which rejects negatives.
lookup_slow() is called by the same lookup_one_len_unlocked() (see
above), mountpoint_last() and walk_component(). In those two negatives
are rejected.
In other words, there is a small set of places where we need to
check carefully if a pinned potentially negative dentry is, in
fact, positive. After that check we want to be sure that both
->d_inode and type bits in ->d_flags are stable and observed.
The set consists of follow_managed() (where the rejection happens
for lookup_fast(), walk_component() and do_last()), last_mountpoint()
and lookup_positive_unlocked().
Solution:
1) transition from negative to positive (in __d_set_inode_and_type())
stores ->d_inode, then uses smp_store_release() to set ->d_flags type bits.
2) aforementioned 3 places in fs/namei.c fetch ->d_flags with
smp_load_acquire() and bugger off if it type bits say "negative".
That way anyone downstream of those checks has dentry know positive pinned,
with ->d_inode and type bits of ->d_flags stable and observed.
I considered splitting off d_lookup_positive(), so that the checks could
be done right there, under ->d_lock. However, that leads to massive
duplication of rather subtle code in fs/namei.c and fs/dcache.c. It's
worse than it might seem, thanks to autofs ->d_manage() getting involved ;-/
No matter what, autofs_d_manage()/autofs_d_automount() must live with
the possibility of pinned negative dentry passed their way, becoming
positive under them - that's the intended behaviour when lookup comes
in the middle of automount in progress, so we can't keep them out of
the area that has to deal with those, more's the pity...
Reported-by: Ritesh Harjani <riteshh@linux.ibm.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2019-11-12 21:13:06 +00:00
|
|
|
smp_store_release(&dentry->d_flags, flags);
|
2015-03-05 14:09:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void __d_clear_type_and_inode(struct dentry *dentry)
|
|
|
|
{
|
|
|
|
unsigned flags = READ_ONCE(dentry->d_flags);
|
|
|
|
|
2023-11-10 19:32:05 +00:00
|
|
|
flags &= ~DCACHE_ENTRY_TYPE;
|
2015-03-05 14:09:22 +00:00
|
|
|
WRITE_ONCE(dentry->d_flags, flags);
|
|
|
|
dentry->d_inode = NULL;
|
vfs: don't mod negative dentry count when on shrinker list
The nr_dentry_negative counter is intended to only account negative
dentries that are present on the superblock LRU. Therefore, the LRU
add, remove and isolate helpers modify the counter based on whether
the dentry is negative, but the shrinker list related helpers do not
modify the counter, and the paths that change a dentry between
positive and negative only do so if DCACHE_LRU_LIST is set.
The problem with this is that a dentry on a shrinker list still has
DCACHE_LRU_LIST set to indicate ->d_lru is in use. The additional
DCACHE_SHRINK_LIST flag denotes whether the dentry is on LRU or a
shrink related list. Therefore if a relevant operation (i.e. unlink)
occurs while a dentry is present on a shrinker list, and the
associated codepath only checks for DCACHE_LRU_LIST, then it is
technically possible to modify the negative dentry count for a
dentry that is off the LRU. Since the shrinker list related helpers
do not modify the negative dentry count (because non-LRU dentries
should not be included in the count) when the dentry is ultimately
removed from the shrinker list, this can cause the negative dentry
count to become permanently inaccurate.
This problem can be reproduced via a heavy file create/unlink vs.
drop_caches workload. On an 80xcpu system, I start 80 tasks each
running a 1k file create/delete loop, and one task spinning on
drop_caches. After 10 minutes or so of runtime, the idle/clean cache
negative dentry count increases from somewhere in the range of 5-10
entries to several hundred (and increasingly grows beyond
nr_dentry_unused).
Tweak the logic in the paths that turn a dentry negative or positive
to filter out the case where the dentry is present on a shrink
related list. This allows the above workload to maintain an accurate
negative dentry count.
Fixes: af0c9af1b3f6 ("fs/dcache: Track & report number of negative dentries")
Signed-off-by: Brian Foster <bfoster@redhat.com>
Link: https://lore.kernel.org/r/20240703121301.247680-1-bfoster@redhat.com
Acked-by: Ian Kent <ikent@redhat.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: Waiman Long <longman@redhat.com>
Signed-off-by: Christian Brauner <brauner@kernel.org>
2024-07-03 12:13:01 +00:00
|
|
|
/*
|
|
|
|
* The negative counter only tracks dentries on the LRU. Don't inc if
|
|
|
|
* d_lru is on another list.
|
|
|
|
*/
|
|
|
|
if ((flags & (DCACHE_LRU_LIST|DCACHE_SHRINK_LIST)) == DCACHE_LRU_LIST)
|
2019-01-30 18:52:38 +00:00
|
|
|
this_cpu_inc(nr_dentry_negative);
|
2015-03-05 14:09:22 +00:00
|
|
|
}
|
|
|
|
|
2014-04-30 03:40:14 +00:00
|
|
|
static void dentry_free(struct dentry *dentry)
|
|
|
|
{
|
2014-10-26 23:19:16 +00:00
|
|
|
WARN_ON(!hlist_unhashed(&dentry->d_u.d_alias));
|
Allow sharing external names after __d_move()
* external dentry names get a small structure prepended to them
(struct external_name).
* it contains an atomic refcount, matching the number of struct dentry
instances that have ->d_name.name pointing to that external name. The
first thing free_dentry() does is decrementing refcount of external name,
so the instances that are between the call of free_dentry() and
RCU-delayed actual freeing do not contribute.
* __d_move(x, y, false) makes the name of x equal to the name of y,
external or not. If y has an external name, extra reference is grabbed
and put into x->d_name.name. If x used to have an external name, the
reference to the old name is dropped and, should it reach zero, freeing
is scheduled via kfree_rcu().
* free_dentry() in dentry with external name decrements the refcount of
that name and, should it reach zero, does RCU-delayed call that will
free both the dentry and external name. Otherwise it does what it
used to do, except that __d_free() doesn't even look at ->d_name.name;
it simply frees the dentry.
All non-RCU accesses to dentry external name are safe wrt freeing since they
all should happen before free_dentry() is called. RCU accesses might run
into a dentry seen by free_dentry() or into an old name that got already
dropped by __d_move(); however, in both cases dentry must have been
alive and refer to that name at some point after we'd done rcu_read_lock(),
which means that any freeing must be still pending.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2014-09-29 18:54:27 +00:00
|
|
|
if (unlikely(dname_external(dentry))) {
|
|
|
|
struct external_name *p = external_name(dentry);
|
|
|
|
if (likely(atomic_dec_and_test(&p->u.count))) {
|
|
|
|
call_rcu(&dentry->d_u.d_rcu, __d_free_external);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2014-04-30 03:40:14 +00:00
|
|
|
/* if dentry was never visible to RCU, immediate free is OK */
|
dcache: sort the freeing-without-RCU-delay mess for good.
For lockless accesses to dentries we don't have pinned we rely
(among other things) upon having an RCU delay between dropping
the last reference and actually freeing the memory.
On the other hand, for things like pipes and sockets we neither
do that kind of lockless access, nor want to deal with the
overhead of an RCU delay every time a socket gets closed.
So delay was made optional - setting DCACHE_RCUACCESS in ->d_flags
made sure it would happen. We tried to avoid setting it unless
we knew we need it. Unfortunately, that had led to recurring
class of bugs, in which we missed the need to set it.
We only really need it for dentries that are created by
d_alloc_pseudo(), so let's not bother with trying to be smart -
just make having an RCU delay the default. The ones that do
*not* get it set the replacement flag (DCACHE_NORCU) and we'd
better use that sparingly. d_alloc_pseudo() is the only
such user right now.
FWIW, the race that finally prompted that switch had been
between __lock_parent() of immediate subdirectory of what's
currently the root of a disconnected tree (e.g. from
open-by-handle in progress) racing with d_splice_alias()
elsewhere picking another alias for the same inode, either
on outright corrupted fs image, or (in case of open-by-handle
on NFS) that subdirectory having been just moved on server.
It's not easy to hit, so the sky is not falling, but that's
not the first race on similar missed cases and the logics
for settinf DCACHE_RCUACCESS has gotten ridiculously
convoluted.
Cc: stable@vger.kernel.org
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2019-03-16 02:23:19 +00:00
|
|
|
if (dentry->d_flags & DCACHE_NORCU)
|
2014-04-30 03:40:14 +00:00
|
|
|
__d_free(&dentry->d_u.d_rcu);
|
|
|
|
else
|
|
|
|
call_rcu(&dentry->d_u.d_rcu, __d_free);
|
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* Release the dentry's inode, using the filesystem
|
2016-05-30 00:13:30 +00:00
|
|
|
* d_iput() operation if defined.
|
fs: rcu-walk for path lookup
Perform common cases of path lookups without any stores or locking in the
ancestor dentry elements. This is called rcu-walk, as opposed to the current
algorithm which is a refcount based walk, or ref-walk.
This results in far fewer atomic operations on every path element,
significantly improving path lookup performance. It also avoids cacheline
bouncing on common dentries, significantly improving scalability.
The overall design is like this:
* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
* Take the RCU lock for the entire path walk, starting with the acquiring
of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
not required for dentry persistence.
* synchronize_rcu is called when unregistering a filesystem, so we can
access d_ops and i_ops during rcu-walk.
* Similarly take the vfsmount lock for the entire path walk. So now mnt
refcounts are not required for persistence. Also we are free to perform mount
lookups, and to assume dentry mount points and mount roots are stable up and
down the path.
* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
so we can load this tuple atomically, and also check whether any of its
members have changed.
* Dentry lookups (based on parent, candidate string tuple) recheck the parent
sequence after the child is found in case anything changed in the parent
during the path walk.
* inode is also RCU protected so we can load d_inode and use the inode for
limited things.
* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
* i_op can be loaded.
When we reach the destination dentry, we lock it, recheck lookup sequence,
and increment its refcount and mountpoint refcount. RCU and vfsmount locks
are dropped. This is termed "dropping rcu-walk". If the dentry refcount does
not match, we can not drop rcu-walk gracefully at the current point in the
lokup, so instead return -ECHILD (for want of a better errno). This signals the
path walking code to re-do the entire lookup with a ref-walk.
Aside from the final dentry, there are other situations that may be encounted
where we cannot continue rcu-walk. In that case, we drop rcu-walk (ie. take
a reference on the last good dentry) and continue with a ref-walk. Again, if
we can drop rcu-walk gracefully, we return -ECHILD and do the whole lookup
using ref-walk. But it is very important that we can continue with ref-walk
for most cases, particularly to avoid the overhead of double lookups, and to
gain the scalability advantages on common path elements (like cwd and root).
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links
In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:52 +00:00
|
|
|
*/
|
|
|
|
static void dentry_unlink_inode(struct dentry * dentry)
|
|
|
|
__releases(dentry->d_lock)
|
2011-01-07 06:50:06 +00:00
|
|
|
__releases(dentry->d_inode->i_lock)
|
fs: rcu-walk for path lookup
Perform common cases of path lookups without any stores or locking in the
ancestor dentry elements. This is called rcu-walk, as opposed to the current
algorithm which is a refcount based walk, or ref-walk.
This results in far fewer atomic operations on every path element,
significantly improving path lookup performance. It also avoids cacheline
bouncing on common dentries, significantly improving scalability.
The overall design is like this:
* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
* Take the RCU lock for the entire path walk, starting with the acquiring
of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
not required for dentry persistence.
* synchronize_rcu is called when unregistering a filesystem, so we can
access d_ops and i_ops during rcu-walk.
* Similarly take the vfsmount lock for the entire path walk. So now mnt
refcounts are not required for persistence. Also we are free to perform mount
lookups, and to assume dentry mount points and mount roots are stable up and
down the path.
* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
so we can load this tuple atomically, and also check whether any of its
members have changed.
* Dentry lookups (based on parent, candidate string tuple) recheck the parent
sequence after the child is found in case anything changed in the parent
during the path walk.
* inode is also RCU protected so we can load d_inode and use the inode for
limited things.
* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
* i_op can be loaded.
When we reach the destination dentry, we lock it, recheck lookup sequence,
and increment its refcount and mountpoint refcount. RCU and vfsmount locks
are dropped. This is termed "dropping rcu-walk". If the dentry refcount does
not match, we can not drop rcu-walk gracefully at the current point in the
lokup, so instead return -ECHILD (for want of a better errno). This signals the
path walking code to re-do the entire lookup with a ref-walk.
Aside from the final dentry, there are other situations that may be encounted
where we cannot continue rcu-walk. In that case, we drop rcu-walk (ie. take
a reference on the last good dentry) and continue with a ref-walk. Again, if
we can drop rcu-walk gracefully, we return -ECHILD and do the whole lookup
using ref-walk. But it is very important that we can continue with ref-walk
for most cases, particularly to avoid the overhead of double lookups, and to
gain the scalability advantages on common path elements (like cwd and root).
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links
In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:52 +00:00
|
|
|
{
|
|
|
|
struct inode *inode = dentry->d_inode;
|
2016-02-29 17:12:46 +00:00
|
|
|
|
2018-08-09 14:15:54 +00:00
|
|
|
raw_write_seqcount_begin(&dentry->d_seq);
|
2015-03-05 14:09:22 +00:00
|
|
|
__d_clear_type_and_inode(dentry);
|
2014-10-26 23:19:16 +00:00
|
|
|
hlist_del_init(&dentry->d_u.d_alias);
|
2018-08-09 14:15:54 +00:00
|
|
|
raw_write_seqcount_end(&dentry->d_seq);
|
fs: rcu-walk for path lookup
Perform common cases of path lookups without any stores or locking in the
ancestor dentry elements. This is called rcu-walk, as opposed to the current
algorithm which is a refcount based walk, or ref-walk.
This results in far fewer atomic operations on every path element,
significantly improving path lookup performance. It also avoids cacheline
bouncing on common dentries, significantly improving scalability.
The overall design is like this:
* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
* Take the RCU lock for the entire path walk, starting with the acquiring
of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
not required for dentry persistence.
* synchronize_rcu is called when unregistering a filesystem, so we can
access d_ops and i_ops during rcu-walk.
* Similarly take the vfsmount lock for the entire path walk. So now mnt
refcounts are not required for persistence. Also we are free to perform mount
lookups, and to assume dentry mount points and mount roots are stable up and
down the path.
* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
so we can load this tuple atomically, and also check whether any of its
members have changed.
* Dentry lookups (based on parent, candidate string tuple) recheck the parent
sequence after the child is found in case anything changed in the parent
during the path walk.
* inode is also RCU protected so we can load d_inode and use the inode for
limited things.
* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
* i_op can be loaded.
When we reach the destination dentry, we lock it, recheck lookup sequence,
and increment its refcount and mountpoint refcount. RCU and vfsmount locks
are dropped. This is termed "dropping rcu-walk". If the dentry refcount does
not match, we can not drop rcu-walk gracefully at the current point in the
lokup, so instead return -ECHILD (for want of a better errno). This signals the
path walking code to re-do the entire lookup with a ref-walk.
Aside from the final dentry, there are other situations that may be encounted
where we cannot continue rcu-walk. In that case, we drop rcu-walk (ie. take
a reference on the last good dentry) and continue with a ref-walk. Again, if
we can drop rcu-walk gracefully, we return -ECHILD and do the whole lookup
using ref-walk. But it is very important that we can continue with ref-walk
for most cases, particularly to avoid the overhead of double lookups, and to
gain the scalability advantages on common path elements (like cwd and root).
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links
In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:52 +00:00
|
|
|
spin_unlock(&dentry->d_lock);
|
2011-01-07 06:50:06 +00:00
|
|
|
spin_unlock(&inode->i_lock);
|
fs: rcu-walk for path lookup
Perform common cases of path lookups without any stores or locking in the
ancestor dentry elements. This is called rcu-walk, as opposed to the current
algorithm which is a refcount based walk, or ref-walk.
This results in far fewer atomic operations on every path element,
significantly improving path lookup performance. It also avoids cacheline
bouncing on common dentries, significantly improving scalability.
The overall design is like this:
* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
* Take the RCU lock for the entire path walk, starting with the acquiring
of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
not required for dentry persistence.
* synchronize_rcu is called when unregistering a filesystem, so we can
access d_ops and i_ops during rcu-walk.
* Similarly take the vfsmount lock for the entire path walk. So now mnt
refcounts are not required for persistence. Also we are free to perform mount
lookups, and to assume dentry mount points and mount roots are stable up and
down the path.
* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
so we can load this tuple atomically, and also check whether any of its
members have changed.
* Dentry lookups (based on parent, candidate string tuple) recheck the parent
sequence after the child is found in case anything changed in the parent
during the path walk.
* inode is also RCU protected so we can load d_inode and use the inode for
limited things.
* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
* i_op can be loaded.
When we reach the destination dentry, we lock it, recheck lookup sequence,
and increment its refcount and mountpoint refcount. RCU and vfsmount locks
are dropped. This is termed "dropping rcu-walk". If the dentry refcount does
not match, we can not drop rcu-walk gracefully at the current point in the
lokup, so instead return -ECHILD (for want of a better errno). This signals the
path walking code to re-do the entire lookup with a ref-walk.
Aside from the final dentry, there are other situations that may be encounted
where we cannot continue rcu-walk. In that case, we drop rcu-walk (ie. take
a reference on the last good dentry) and continue with a ref-walk. Again, if
we can drop rcu-walk gracefully, we return -ECHILD and do the whole lookup
using ref-walk. But it is very important that we can continue with ref-walk
for most cases, particularly to avoid the overhead of double lookups, and to
gain the scalability advantages on common path elements (like cwd and root).
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links
In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:52 +00:00
|
|
|
if (!inode->i_nlink)
|
|
|
|
fsnotify_inoderemove(inode);
|
|
|
|
if (dentry->d_op && dentry->d_op->d_iput)
|
|
|
|
dentry->d_op->d_iput(dentry, inode);
|
|
|
|
else
|
|
|
|
iput(inode);
|
|
|
|
}
|
|
|
|
|
2013-09-14 02:55:10 +00:00
|
|
|
/*
|
|
|
|
* The DCACHE_LRU_LIST bit is set whenever the 'd_lru' entry
|
|
|
|
* is in use - which includes both the "real" per-superblock
|
|
|
|
* LRU list _and_ the DCACHE_SHRINK_LIST use.
|
|
|
|
*
|
|
|
|
* The DCACHE_SHRINK_LIST bit is set whenever the dentry is
|
|
|
|
* on the shrink list (ie not on the superblock LRU list).
|
|
|
|
*
|
|
|
|
* The per-cpu "nr_dentry_unused" counters are updated with
|
|
|
|
* the DCACHE_LRU_LIST bit.
|
|
|
|
*
|
2019-01-30 18:52:38 +00:00
|
|
|
* The per-cpu "nr_dentry_negative" counters are only updated
|
|
|
|
* when deleted from or added to the per-superblock LRU list, not
|
|
|
|
* from/to the shrink list. That is to avoid an unneeded dec/inc
|
|
|
|
* pair when moving from LRU to shrink list in select_collect().
|
|
|
|
*
|
2013-09-14 02:55:10 +00:00
|
|
|
* These helper functions make sure we always follow the
|
|
|
|
* rules. d_lock must be held by the caller.
|
|
|
|
*/
|
|
|
|
#define D_FLAG_VERIFY(dentry,x) WARN_ON_ONCE(((dentry)->d_flags & (DCACHE_LRU_LIST | DCACHE_SHRINK_LIST)) != (x))
|
|
|
|
static void d_lru_add(struct dentry *dentry)
|
|
|
|
{
|
|
|
|
D_FLAG_VERIFY(dentry, 0);
|
|
|
|
dentry->d_flags |= DCACHE_LRU_LIST;
|
|
|
|
this_cpu_inc(nr_dentry_unused);
|
2019-01-30 18:52:38 +00:00
|
|
|
if (d_is_negative(dentry))
|
|
|
|
this_cpu_inc(nr_dentry_negative);
|
list_lru: allow explicit memcg and NUMA node selection
Patch series "workload-specific and memory pressure-driven zswap
writeback", v8.
There are currently several issues with zswap writeback:
1. There is only a single global LRU for zswap, making it impossible to
perform worload-specific shrinking - an memcg under memory pressure
cannot determine which pages in the pool it owns, and often ends up
writing pages from other memcgs. This issue has been previously
observed in practice and mitigated by simply disabling
memcg-initiated shrinking:
https://lore.kernel.org/all/20230530232435.3097106-1-nphamcs@gmail.com/T/#u
But this solution leaves a lot to be desired, as we still do not
have an avenue for an memcg to free up its own memory locked up in
the zswap pool.
2. We only shrink the zswap pool when the user-defined limit is hit.
This means that if we set the limit too high, cold data that are
unlikely to be used again will reside in the pool, wasting precious
memory. It is hard to predict how much zswap space will be needed
ahead of time, as this depends on the workload (specifically, on
factors such as memory access patterns and compressibility of the
memory pages).
This patch series solves these issues by separating the global zswap LRU
into per-memcg and per-NUMA LRUs, and performs workload-specific (i.e
memcg- and NUMA-aware) zswap writeback under memory pressure. The new
shrinker does not have any parameter that must be tuned by the user, and
can be opted in or out on a per-memcg basis.
As a proof of concept, we ran the following synthetic benchmark: build the
linux kernel in a memory-limited cgroup, and allocate some cold data in
tmpfs to see if the shrinker could write them out and improved the overall
performance. Depending on the amount of cold data generated, we observe
from 14% to 35% reduction in kernel CPU time used in the kernel builds.
This patch (of 6):
The interface of list_lru is based on the assumption that the list node
and the data it represents belong to the same allocated on the correct
node/memcg. While this assumption is valid for existing slab objects LRU
such as dentries and inodes, it is undocumented, and rather inflexible for
certain potential list_lru users (such as the upcoming zswap shrinker and
the THP shrinker). It has caused us a lot of issues during our
development.
This patch changes list_lru interface so that the caller must explicitly
specify numa node and memcg when adding and removing objects. The old
list_lru_add() and list_lru_del() are renamed to list_lru_add_obj() and
list_lru_del_obj(), respectively.
It also extends the list_lru API with a new function, list_lru_putback,
which undoes a previous list_lru_isolate call. Unlike list_lru_add, it
does not increment the LRU node count (as list_lru_isolate does not
decrement the node count). list_lru_putback also allows for explicit
memcg and NUMA node selection.
Link: https://lkml.kernel.org/r/20231130194023.4102148-1-nphamcs@gmail.com
Link: https://lkml.kernel.org/r/20231130194023.4102148-2-nphamcs@gmail.com
Signed-off-by: Nhat Pham <nphamcs@gmail.com>
Suggested-by: Johannes Weiner <hannes@cmpxchg.org>
Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Tested-by: Bagas Sanjaya <bagasdotme@gmail.com>
Cc: Chris Li <chrisl@kernel.org>
Cc: Dan Streetman <ddstreet@ieee.org>
Cc: Domenico Cerasuolo <cerasuolodomenico@gmail.com>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Seth Jennings <sjenning@redhat.com>
Cc: Shakeel Butt <shakeelb@google.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Vitaly Wool <vitaly.wool@konsulko.com>
Cc: Yosry Ahmed <yosryahmed@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
2023-11-30 19:40:18 +00:00
|
|
|
WARN_ON_ONCE(!list_lru_add_obj(
|
|
|
|
&dentry->d_sb->s_dentry_lru, &dentry->d_lru));
|
2013-09-14 02:55:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void d_lru_del(struct dentry *dentry)
|
|
|
|
{
|
|
|
|
D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST);
|
|
|
|
dentry->d_flags &= ~DCACHE_LRU_LIST;
|
|
|
|
this_cpu_dec(nr_dentry_unused);
|
2019-01-30 18:52:38 +00:00
|
|
|
if (d_is_negative(dentry))
|
|
|
|
this_cpu_dec(nr_dentry_negative);
|
list_lru: allow explicit memcg and NUMA node selection
Patch series "workload-specific and memory pressure-driven zswap
writeback", v8.
There are currently several issues with zswap writeback:
1. There is only a single global LRU for zswap, making it impossible to
perform worload-specific shrinking - an memcg under memory pressure
cannot determine which pages in the pool it owns, and often ends up
writing pages from other memcgs. This issue has been previously
observed in practice and mitigated by simply disabling
memcg-initiated shrinking:
https://lore.kernel.org/all/20230530232435.3097106-1-nphamcs@gmail.com/T/#u
But this solution leaves a lot to be desired, as we still do not
have an avenue for an memcg to free up its own memory locked up in
the zswap pool.
2. We only shrink the zswap pool when the user-defined limit is hit.
This means that if we set the limit too high, cold data that are
unlikely to be used again will reside in the pool, wasting precious
memory. It is hard to predict how much zswap space will be needed
ahead of time, as this depends on the workload (specifically, on
factors such as memory access patterns and compressibility of the
memory pages).
This patch series solves these issues by separating the global zswap LRU
into per-memcg and per-NUMA LRUs, and performs workload-specific (i.e
memcg- and NUMA-aware) zswap writeback under memory pressure. The new
shrinker does not have any parameter that must be tuned by the user, and
can be opted in or out on a per-memcg basis.
As a proof of concept, we ran the following synthetic benchmark: build the
linux kernel in a memory-limited cgroup, and allocate some cold data in
tmpfs to see if the shrinker could write them out and improved the overall
performance. Depending on the amount of cold data generated, we observe
from 14% to 35% reduction in kernel CPU time used in the kernel builds.
This patch (of 6):
The interface of list_lru is based on the assumption that the list node
and the data it represents belong to the same allocated on the correct
node/memcg. While this assumption is valid for existing slab objects LRU
such as dentries and inodes, it is undocumented, and rather inflexible for
certain potential list_lru users (such as the upcoming zswap shrinker and
the THP shrinker). It has caused us a lot of issues during our
development.
This patch changes list_lru interface so that the caller must explicitly
specify numa node and memcg when adding and removing objects. The old
list_lru_add() and list_lru_del() are renamed to list_lru_add_obj() and
list_lru_del_obj(), respectively.
It also extends the list_lru API with a new function, list_lru_putback,
which undoes a previous list_lru_isolate call. Unlike list_lru_add, it
does not increment the LRU node count (as list_lru_isolate does not
decrement the node count). list_lru_putback also allows for explicit
memcg and NUMA node selection.
Link: https://lkml.kernel.org/r/20231130194023.4102148-1-nphamcs@gmail.com
Link: https://lkml.kernel.org/r/20231130194023.4102148-2-nphamcs@gmail.com
Signed-off-by: Nhat Pham <nphamcs@gmail.com>
Suggested-by: Johannes Weiner <hannes@cmpxchg.org>
Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Tested-by: Bagas Sanjaya <bagasdotme@gmail.com>
Cc: Chris Li <chrisl@kernel.org>
Cc: Dan Streetman <ddstreet@ieee.org>
Cc: Domenico Cerasuolo <cerasuolodomenico@gmail.com>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Seth Jennings <sjenning@redhat.com>
Cc: Shakeel Butt <shakeelb@google.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Vitaly Wool <vitaly.wool@konsulko.com>
Cc: Yosry Ahmed <yosryahmed@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
2023-11-30 19:40:18 +00:00
|
|
|
WARN_ON_ONCE(!list_lru_del_obj(
|
|
|
|
&dentry->d_sb->s_dentry_lru, &dentry->d_lru));
|
2013-09-14 02:55:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void d_shrink_del(struct dentry *dentry)
|
|
|
|
{
|
|
|
|
D_FLAG_VERIFY(dentry, DCACHE_SHRINK_LIST | DCACHE_LRU_LIST);
|
|
|
|
list_del_init(&dentry->d_lru);
|
|
|
|
dentry->d_flags &= ~(DCACHE_SHRINK_LIST | DCACHE_LRU_LIST);
|
|
|
|
this_cpu_dec(nr_dentry_unused);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void d_shrink_add(struct dentry *dentry, struct list_head *list)
|
|
|
|
{
|
|
|
|
D_FLAG_VERIFY(dentry, 0);
|
|
|
|
list_add(&dentry->d_lru, list);
|
|
|
|
dentry->d_flags |= DCACHE_SHRINK_LIST | DCACHE_LRU_LIST;
|
|
|
|
this_cpu_inc(nr_dentry_unused);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* These can only be called under the global LRU lock, ie during the
|
|
|
|
* callback for freeing the LRU list. "isolate" removes it from the
|
|
|
|
* LRU lists entirely, while shrink_move moves it to the indicated
|
|
|
|
* private list.
|
|
|
|
*/
|
2015-02-12 22:59:35 +00:00
|
|
|
static void d_lru_isolate(struct list_lru_one *lru, struct dentry *dentry)
|
2013-09-14 02:55:10 +00:00
|
|
|
{
|
|
|
|
D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST);
|
|
|
|
dentry->d_flags &= ~DCACHE_LRU_LIST;
|
|
|
|
this_cpu_dec(nr_dentry_unused);
|
2019-01-30 18:52:38 +00:00
|
|
|
if (d_is_negative(dentry))
|
|
|
|
this_cpu_dec(nr_dentry_negative);
|
2015-02-12 22:59:35 +00:00
|
|
|
list_lru_isolate(lru, &dentry->d_lru);
|
2013-09-14 02:55:10 +00:00
|
|
|
}
|
|
|
|
|
2015-02-12 22:59:35 +00:00
|
|
|
static void d_lru_shrink_move(struct list_lru_one *lru, struct dentry *dentry,
|
|
|
|
struct list_head *list)
|
2013-09-14 02:55:10 +00:00
|
|
|
{
|
|
|
|
D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST);
|
|
|
|
dentry->d_flags |= DCACHE_SHRINK_LIST;
|
2019-01-30 18:52:38 +00:00
|
|
|
if (d_is_negative(dentry))
|
|
|
|
this_cpu_dec(nr_dentry_negative);
|
2015-02-12 22:59:35 +00:00
|
|
|
list_lru_isolate_move(lru, &dentry->d_lru, list);
|
2013-09-14 02:55:10 +00:00
|
|
|
}
|
|
|
|
|
2017-11-10 04:45:41 +00:00
|
|
|
static void ___d_drop(struct dentry *dentry)
|
2011-01-07 06:49:30 +00:00
|
|
|
{
|
2018-03-07 05:49:10 +00:00
|
|
|
struct hlist_bl_head *b;
|
|
|
|
/*
|
|
|
|
* Hashed dentries are normally on the dentry hashtable,
|
|
|
|
* with the exception of those newly allocated by
|
|
|
|
* d_obtain_root, which are always IS_ROOT:
|
|
|
|
*/
|
|
|
|
if (unlikely(IS_ROOT(dentry)))
|
|
|
|
b = &dentry->d_sb->s_roots;
|
|
|
|
else
|
|
|
|
b = d_hash(dentry->d_name.hash);
|
2013-10-04 15:09:01 +00:00
|
|
|
|
2018-03-07 05:49:10 +00:00
|
|
|
hlist_bl_lock(b);
|
|
|
|
__hlist_bl_del(&dentry->d_hash);
|
|
|
|
hlist_bl_unlock(b);
|
2011-01-07 06:49:30 +00:00
|
|
|
}
|
2017-11-10 04:45:41 +00:00
|
|
|
|
|
|
|
void __d_drop(struct dentry *dentry)
|
|
|
|
{
|
2018-03-07 05:49:10 +00:00
|
|
|
if (!d_unhashed(dentry)) {
|
|
|
|
___d_drop(dentry);
|
|
|
|
dentry->d_hash.pprev = NULL;
|
|
|
|
write_seqcount_invalidate(&dentry->d_seq);
|
|
|
|
}
|
2017-11-10 04:45:41 +00:00
|
|
|
}
|
2011-01-07 06:49:30 +00:00
|
|
|
EXPORT_SYMBOL(__d_drop);
|
|
|
|
|
2021-01-14 08:04:39 +00:00
|
|
|
/**
|
|
|
|
* d_drop - drop a dentry
|
|
|
|
* @dentry: dentry to drop
|
|
|
|
*
|
|
|
|
* d_drop() unhashes the entry from the parent dentry hashes, so that it won't
|
|
|
|
* be found through a VFS lookup any more. Note that this is different from
|
|
|
|
* deleting the dentry - d_delete will try to mark the dentry negative if
|
|
|
|
* possible, giving a successful _negative_ lookup, while d_drop will
|
|
|
|
* just make the cache lookup fail.
|
|
|
|
*
|
|
|
|
* d_drop() is used mainly for stuff that wants to invalidate a dentry for some
|
|
|
|
* reason (NFS timeouts or autofs deletes).
|
|
|
|
*
|
|
|
|
* __d_drop requires dentry->d_lock
|
|
|
|
*
|
|
|
|
* ___d_drop doesn't mark dentry as "unhashed"
|
|
|
|
* (dentry->d_hash.pprev will be LIST_POISON2, not NULL).
|
|
|
|
*/
|
2011-01-07 06:49:30 +00:00
|
|
|
void d_drop(struct dentry *dentry)
|
|
|
|
{
|
|
|
|
spin_lock(&dentry->d_lock);
|
|
|
|
__d_drop(dentry);
|
|
|
|
spin_unlock(&dentry->d_lock);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(d_drop);
|
|
|
|
|
2023-11-07 07:00:39 +00:00
|
|
|
static inline void dentry_unlist(struct dentry *dentry)
|
2016-06-10 15:32:47 +00:00
|
|
|
{
|
|
|
|
struct dentry *next;
|
|
|
|
/*
|
|
|
|
* Inform d_walk() and shrink_dentry_list() that we are no longer
|
|
|
|
* attached to the dentry tree
|
|
|
|
*/
|
|
|
|
dentry->d_flags |= DCACHE_DENTRY_KILLED;
|
2023-11-07 07:00:39 +00:00
|
|
|
if (unlikely(hlist_unhashed(&dentry->d_sib)))
|
2016-06-10 15:32:47 +00:00
|
|
|
return;
|
2023-11-07 07:00:39 +00:00
|
|
|
__hlist_del(&dentry->d_sib);
|
2016-06-10 15:32:47 +00:00
|
|
|
/*
|
|
|
|
* Cursors can move around the list of children. While we'd been
|
2023-11-07 07:00:39 +00:00
|
|
|
* a normal list member, it didn't matter - ->d_sib.next would've
|
2016-06-10 15:32:47 +00:00
|
|
|
* been updated. However, from now on it won't be and for the
|
|
|
|
* things like d_walk() it might end up with a nasty surprise.
|
|
|
|
* Normally d_walk() doesn't care about cursors moving around -
|
|
|
|
* ->d_lock on parent prevents that and since a cursor has no children
|
|
|
|
* of its own, we get through it without ever unlocking the parent.
|
|
|
|
* There is one exception, though - if we ascend from a child that
|
|
|
|
* gets killed as soon as we unlock it, the next sibling is found
|
2023-11-07 07:00:39 +00:00
|
|
|
* using the value left in its ->d_sib.next. And if _that_
|
2016-06-10 15:32:47 +00:00
|
|
|
* pointed to a cursor, and cursor got moved (e.g. by lseek())
|
|
|
|
* before d_walk() regains parent->d_lock, we'll end up skipping
|
|
|
|
* everything the cursor had been moved past.
|
|
|
|
*
|
2023-11-07 07:00:39 +00:00
|
|
|
* Solution: make sure that the pointer left behind in ->d_sib.next
|
2016-06-10 15:32:47 +00:00
|
|
|
* points to something that won't be moving around. I.e. skip the
|
|
|
|
* cursors.
|
|
|
|
*/
|
2023-11-07 07:00:39 +00:00
|
|
|
while (dentry->d_sib.next) {
|
|
|
|
next = hlist_entry(dentry->d_sib.next, struct dentry, d_sib);
|
2016-06-10 15:32:47 +00:00
|
|
|
if (likely(!(next->d_flags & DCACHE_DENTRY_CURSOR)))
|
|
|
|
break;
|
2023-11-07 07:00:39 +00:00
|
|
|
dentry->d_sib.next = next->d_sib.next;
|
2016-06-10 15:32:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
__dentry_kill(): new locking scheme
Currently we enter __dentry_kill() with parent (along with the victim
dentry and victim's inode) held locked. Then we
mark dentry refcount as dead
call ->d_prune()
remove dentry from hash
remove it from the parent's list of children
unlock the parent, don't need it from that point on
detach dentry from inode, unlock dentry and drop the inode
(via ->d_iput())
call ->d_release()
regain the lock on dentry
check if it's on a shrink list (in which case freeing its empty husk
has to be left to shrink_dentry_list()) or not (in which case we can free it
ourselves). In the former case, mark it as an empty husk, so that
shrink_dentry_list() would know it can free the sucker.
drop the lock on dentry
... and usually the caller proceeds to drop a reference on the parent,
possibly retaking the lock on it.
That is painful for a bunch of reasons, starting with the need to take locks
out of order, but not limited to that - the parent of positive dentry can
change if we drop its ->d_lock, so getting these locks has to be done with
care. Moreover, as soon as dentry is out of the parent's list of children,
shrink_dcache_for_umount() won't see it anymore, making it appear as if
the parent is inexplicably busy. We do work around that by having
shrink_dentry_list() decrement the parent's refcount first and put it on
shrink list to be evicted once we are done with __dentry_kill() of child,
but that may in some cases lead to ->d_iput() on child called after the
parent got killed. That doesn't happen in cases where in-tree ->d_iput()
instances might want to look at the parent, but that's brittle as hell.
Solution: do removal from the parent's list of children in the very
end of __dentry_kill(). As the result, the callers do not need to
lock the parent and by the time we really need the parent locked,
dentry is negative and is guaranteed not to be moved around.
It does mean that ->d_prune() will be called with parent not locked.
It also means that we might see dentries in process of being torn
down while going through the parent's list of children; those dentries
will be unhashed, negative and with refcount marked dead. In practice,
that's enough for in-tree code that looks through the list of children
to do the right thing as-is. Out-of-tree code might need to be adjusted.
Calling conventions: __dentry_kill(dentry) is called with dentry->d_lock
held, along with ->i_lock of its inode (if any). It either returns
the parent (locked, with refcount decremented to 0) or NULL (if there'd
been no parent or if refcount decrement for parent hadn't reached 0).
lock_for_kill() is adjusted for new requirements - it doesn't touch
the parent's ->d_lock at all.
Callers adjusted. Note that for dput() we don't need to bother with
fast_dput() for the parent - we just need to check retain_dentry()
for it, since its ->d_lock is still held since the moment when
__dentry_kill() had taken it to remove the victim from the list of
children.
The kludge with early decrement of parent's refcount in
shrink_dentry_list() is no longer needed - shrink_dcache_for_umount()
sees the half-killed dentries in the list of children for as long
as they are pinning the parent. They are easily recognized and
accounted for by select_collect(), so we know we are not done yet.
As the result, we always have the expected ordering for ->d_iput()/->d_release()
vs. __dentry_kill() of the parent, no exceptions. Moreover, the current
rules for shrink lists (one must make sure that shrink_dcache_for_umount()
won't happen while any dentries from the superblock in question are on
any shrink lists) are gone - shrink_dcache_for_umount() will do the
right thing in all cases, taking such dentries out. Their empty
husks (memory occupied by struct dentry itself + its external name,
if any) will remain on the shrink lists, but they are no obstacles
to filesystem shutdown. And such husks will get freed as soon as
shrink_dentry_list() of the list they are on gets to them.
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-11-07 21:14:08 +00:00
|
|
|
static struct dentry *__dentry_kill(struct dentry *dentry)
|
2011-01-07 06:49:48 +00:00
|
|
|
{
|
dentry_kill(): don't try to remove from shrink list
If the victim in on the shrink list, don't remove it from there.
If shrink_dentry_list() manages to remove it from the list before
we are done - fine, we'll just free it as usual. If not - mark
it with new flag (DCACHE_MAY_FREE) and leave it there.
Eventually, shrink_dentry_list() will get to it, remove the sucker
from shrink list and call dentry_kill(dentry, 0). Which is where
we'll deal with freeing.
Since now dentry_kill(dentry, 0) may happen after or during
dentry_kill(dentry, 1), we need to recognize that (by seeing
DCACHE_DENTRY_KILLED already set), unlock everything
and either free the sucker (in case DCACHE_MAY_FREE has been
set) or leave it for ongoing dentry_kill(dentry, 1) to deal with.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2014-05-01 14:30:00 +00:00
|
|
|
struct dentry *parent = NULL;
|
|
|
|
bool can_free = true;
|
fs: rcu-walk for path lookup
Perform common cases of path lookups without any stores or locking in the
ancestor dentry elements. This is called rcu-walk, as opposed to the current
algorithm which is a refcount based walk, or ref-walk.
This results in far fewer atomic operations on every path element,
significantly improving path lookup performance. It also avoids cacheline
bouncing on common dentries, significantly improving scalability.
The overall design is like this:
* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
* Take the RCU lock for the entire path walk, starting with the acquiring
of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
not required for dentry persistence.
* synchronize_rcu is called when unregistering a filesystem, so we can
access d_ops and i_ops during rcu-walk.
* Similarly take the vfsmount lock for the entire path walk. So now mnt
refcounts are not required for persistence. Also we are free to perform mount
lookups, and to assume dentry mount points and mount roots are stable up and
down the path.
* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
so we can load this tuple atomically, and also check whether any of its
members have changed.
* Dentry lookups (based on parent, candidate string tuple) recheck the parent
sequence after the child is found in case anything changed in the parent
during the path walk.
* inode is also RCU protected so we can load d_inode and use the inode for
limited things.
* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
* i_op can be loaded.
When we reach the destination dentry, we lock it, recheck lookup sequence,
and increment its refcount and mountpoint refcount. RCU and vfsmount locks
are dropped. This is termed "dropping rcu-walk". If the dentry refcount does
not match, we can not drop rcu-walk gracefully at the current point in the
lokup, so instead return -ECHILD (for want of a better errno). This signals the
path walking code to re-do the entire lookup with a ref-walk.
Aside from the final dentry, there are other situations that may be encounted
where we cannot continue rcu-walk. In that case, we drop rcu-walk (ie. take
a reference on the last good dentry) and continue with a ref-walk. Again, if
we can drop rcu-walk gracefully, we return -ECHILD and do the whole lookup
using ref-walk. But it is very important that we can continue with ref-walk
for most cases, particularly to avoid the overhead of double lookups, and to
gain the scalability advantages on common path elements (like cwd and root).
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links
In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:52 +00:00
|
|
|
|
vfs: use lockred "dead" flag to mark unrecoverably dead dentries
This simplifies the RCU to refcounting code in particular.
I was originally intending to leave this for later, but walking through
all the dput() logic (see previous commit), I realized that the dput()
"might_sleep()" check was misleadingly weak. And I removed it as
misleading, both for performance profiling and for debugging.
However, the might_sleep() debugging case is actually true: the final
dput() can indeed sleep, if the inode of the dentry that you are
releasing ends up sleeping at iput time (see dentry_iput()). So the
problem with the might_sleep() in dput() wasn't that it wasn't true, it
was that it wasn't actually testing and triggering on the interesting
case.
In particular, just about *any* dput() can indeed sleep, if you happen
to race with another thread deleting the file in question, and you then
lose the race to the be the last dput() for that file. But because it's
a very rare race, the debugging code would never trigger it in practice.
Why is this problematic? The new d_rcu_to_refcount() (see commit
15570086b590: "vfs: reimplement d_rcu_to_refcount() using
lockref_get_or_lock()") does a dput() for the failure case, and it does
it under the RCU lock. So potentially sleeping really is a bug.
But there's no way I'm going to fix this with the previous complicated
"lockref_get_or_lock()" interface. And rather than revert to the old
and crufty nested dentry locking code (which did get this right by
delaying the reference count updates until they were verified to be
safe), let's make forward progress.
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2013-09-08 20:46:52 +00:00
|
|
|
/*
|
|
|
|
* The dentry is now unrecoverably dead to the world.
|
|
|
|
*/
|
|
|
|
lockref_mark_dead(&dentry->d_lockref);
|
|
|
|
|
2011-10-28 17:02:42 +00:00
|
|
|
/*
|
|
|
|
* inform the fs via d_prune that this dentry is about to be
|
|
|
|
* unhashed and destroyed.
|
|
|
|
*/
|
2014-05-30 15:39:02 +00:00
|
|
|
if (dentry->d_flags & DCACHE_OP_PRUNE)
|
2013-04-15 06:13:21 +00:00
|
|
|
dentry->d_op->d_prune(dentry);
|
|
|
|
|
2014-04-30 03:42:52 +00:00
|
|
|
if (dentry->d_flags & DCACHE_LRU_LIST) {
|
|
|
|
if (!(dentry->d_flags & DCACHE_SHRINK_LIST))
|
|
|
|
d_lru_del(dentry);
|
|
|
|
}
|
2011-01-07 06:49:48 +00:00
|
|
|
/* if it was on the hash then remove it */
|
|
|
|
__d_drop(dentry);
|
2016-05-30 00:13:30 +00:00
|
|
|
if (dentry->d_inode)
|
|
|
|
dentry_unlink_inode(dentry);
|
|
|
|
else
|
|
|
|
spin_unlock(&dentry->d_lock);
|
2014-04-29 19:45:28 +00:00
|
|
|
this_cpu_dec(nr_dentry);
|
|
|
|
if (dentry->d_op && dentry->d_op->d_release)
|
|
|
|
dentry->d_op->d_release(dentry);
|
|
|
|
|
__dentry_kill(): new locking scheme
Currently we enter __dentry_kill() with parent (along with the victim
dentry and victim's inode) held locked. Then we
mark dentry refcount as dead
call ->d_prune()
remove dentry from hash
remove it from the parent's list of children
unlock the parent, don't need it from that point on
detach dentry from inode, unlock dentry and drop the inode
(via ->d_iput())
call ->d_release()
regain the lock on dentry
check if it's on a shrink list (in which case freeing its empty husk
has to be left to shrink_dentry_list()) or not (in which case we can free it
ourselves). In the former case, mark it as an empty husk, so that
shrink_dentry_list() would know it can free the sucker.
drop the lock on dentry
... and usually the caller proceeds to drop a reference on the parent,
possibly retaking the lock on it.
That is painful for a bunch of reasons, starting with the need to take locks
out of order, but not limited to that - the parent of positive dentry can
change if we drop its ->d_lock, so getting these locks has to be done with
care. Moreover, as soon as dentry is out of the parent's list of children,
shrink_dcache_for_umount() won't see it anymore, making it appear as if
the parent is inexplicably busy. We do work around that by having
shrink_dentry_list() decrement the parent's refcount first and put it on
shrink list to be evicted once we are done with __dentry_kill() of child,
but that may in some cases lead to ->d_iput() on child called after the
parent got killed. That doesn't happen in cases where in-tree ->d_iput()
instances might want to look at the parent, but that's brittle as hell.
Solution: do removal from the parent's list of children in the very
end of __dentry_kill(). As the result, the callers do not need to
lock the parent and by the time we really need the parent locked,
dentry is negative and is guaranteed not to be moved around.
It does mean that ->d_prune() will be called with parent not locked.
It also means that we might see dentries in process of being torn
down while going through the parent's list of children; those dentries
will be unhashed, negative and with refcount marked dead. In practice,
that's enough for in-tree code that looks through the list of children
to do the right thing as-is. Out-of-tree code might need to be adjusted.
Calling conventions: __dentry_kill(dentry) is called with dentry->d_lock
held, along with ->i_lock of its inode (if any). It either returns
the parent (locked, with refcount decremented to 0) or NULL (if there'd
been no parent or if refcount decrement for parent hadn't reached 0).
lock_for_kill() is adjusted for new requirements - it doesn't touch
the parent's ->d_lock at all.
Callers adjusted. Note that for dput() we don't need to bother with
fast_dput() for the parent - we just need to check retain_dentry()
for it, since its ->d_lock is still held since the moment when
__dentry_kill() had taken it to remove the victim from the list of
children.
The kludge with early decrement of parent's refcount in
shrink_dentry_list() is no longer needed - shrink_dcache_for_umount()
sees the half-killed dentries in the list of children for as long
as they are pinning the parent. They are easily recognized and
accounted for by select_collect(), so we know we are not done yet.
As the result, we always have the expected ordering for ->d_iput()/->d_release()
vs. __dentry_kill() of the parent, no exceptions. Moreover, the current
rules for shrink lists (one must make sure that shrink_dcache_for_umount()
won't happen while any dentries from the superblock in question are on
any shrink lists) are gone - shrink_dcache_for_umount() will do the
right thing in all cases, taking such dentries out. Their empty
husks (memory occupied by struct dentry itself + its external name,
if any) will remain on the shrink lists, but they are no obstacles
to filesystem shutdown. And such husks will get freed as soon as
shrink_dentry_list() of the list they are on gets to them.
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-11-07 21:14:08 +00:00
|
|
|
cond_resched();
|
|
|
|
/* now that it's negative, ->d_parent is stable */
|
|
|
|
if (!IS_ROOT(dentry)) {
|
|
|
|
parent = dentry->d_parent;
|
|
|
|
spin_lock(&parent->d_lock);
|
dentry_kill(): don't try to remove from shrink list
If the victim in on the shrink list, don't remove it from there.
If shrink_dentry_list() manages to remove it from the list before
we are done - fine, we'll just free it as usual. If not - mark
it with new flag (DCACHE_MAY_FREE) and leave it there.
Eventually, shrink_dentry_list() will get to it, remove the sucker
from shrink list and call dentry_kill(dentry, 0). Which is where
we'll deal with freeing.
Since now dentry_kill(dentry, 0) may happen after or during
dentry_kill(dentry, 1), we need to recognize that (by seeing
DCACHE_DENTRY_KILLED already set), unlock everything
and either free the sucker (in case DCACHE_MAY_FREE has been
set) or leave it for ongoing dentry_kill(dentry, 1) to deal with.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2014-05-01 14:30:00 +00:00
|
|
|
}
|
__dentry_kill(): new locking scheme
Currently we enter __dentry_kill() with parent (along with the victim
dentry and victim's inode) held locked. Then we
mark dentry refcount as dead
call ->d_prune()
remove dentry from hash
remove it from the parent's list of children
unlock the parent, don't need it from that point on
detach dentry from inode, unlock dentry and drop the inode
(via ->d_iput())
call ->d_release()
regain the lock on dentry
check if it's on a shrink list (in which case freeing its empty husk
has to be left to shrink_dentry_list()) or not (in which case we can free it
ourselves). In the former case, mark it as an empty husk, so that
shrink_dentry_list() would know it can free the sucker.
drop the lock on dentry
... and usually the caller proceeds to drop a reference on the parent,
possibly retaking the lock on it.
That is painful for a bunch of reasons, starting with the need to take locks
out of order, but not limited to that - the parent of positive dentry can
change if we drop its ->d_lock, so getting these locks has to be done with
care. Moreover, as soon as dentry is out of the parent's list of children,
shrink_dcache_for_umount() won't see it anymore, making it appear as if
the parent is inexplicably busy. We do work around that by having
shrink_dentry_list() decrement the parent's refcount first and put it on
shrink list to be evicted once we are done with __dentry_kill() of child,
but that may in some cases lead to ->d_iput() on child called after the
parent got killed. That doesn't happen in cases where in-tree ->d_iput()
instances might want to look at the parent, but that's brittle as hell.
Solution: do removal from the parent's list of children in the very
end of __dentry_kill(). As the result, the callers do not need to
lock the parent and by the time we really need the parent locked,
dentry is negative and is guaranteed not to be moved around.
It does mean that ->d_prune() will be called with parent not locked.
It also means that we might see dentries in process of being torn
down while going through the parent's list of children; those dentries
will be unhashed, negative and with refcount marked dead. In practice,
that's enough for in-tree code that looks through the list of children
to do the right thing as-is. Out-of-tree code might need to be adjusted.
Calling conventions: __dentry_kill(dentry) is called with dentry->d_lock
held, along with ->i_lock of its inode (if any). It either returns
the parent (locked, with refcount decremented to 0) or NULL (if there'd
been no parent or if refcount decrement for parent hadn't reached 0).
lock_for_kill() is adjusted for new requirements - it doesn't touch
the parent's ->d_lock at all.
Callers adjusted. Note that for dput() we don't need to bother with
fast_dput() for the parent - we just need to check retain_dentry()
for it, since its ->d_lock is still held since the moment when
__dentry_kill() had taken it to remove the victim from the list of
children.
The kludge with early decrement of parent's refcount in
shrink_dentry_list() is no longer needed - shrink_dcache_for_umount()
sees the half-killed dentries in the list of children for as long
as they are pinning the parent. They are easily recognized and
accounted for by select_collect(), so we know we are not done yet.
As the result, we always have the expected ordering for ->d_iput()/->d_release()
vs. __dentry_kill() of the parent, no exceptions. Moreover, the current
rules for shrink lists (one must make sure that shrink_dcache_for_umount()
won't happen while any dentries from the superblock in question are on
any shrink lists) are gone - shrink_dcache_for_umount() will do the
right thing in all cases, taking such dentries out. Their empty
husks (memory occupied by struct dentry itself + its external name,
if any) will remain on the shrink lists, but they are no obstacles
to filesystem shutdown. And such husks will get freed as soon as
shrink_dentry_list() of the list they are on gets to them.
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-11-07 21:14:08 +00:00
|
|
|
spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
|
|
|
|
dentry_unlist(dentry);
|
2023-11-10 19:07:43 +00:00
|
|
|
if (dentry->d_flags & DCACHE_SHRINK_LIST)
|
dentry_kill(): don't try to remove from shrink list
If the victim in on the shrink list, don't remove it from there.
If shrink_dentry_list() manages to remove it from the list before
we are done - fine, we'll just free it as usual. If not - mark
it with new flag (DCACHE_MAY_FREE) and leave it there.
Eventually, shrink_dentry_list() will get to it, remove the sucker
from shrink list and call dentry_kill(dentry, 0). Which is where
we'll deal with freeing.
Since now dentry_kill(dentry, 0) may happen after or during
dentry_kill(dentry, 1), we need to recognize that (by seeing
DCACHE_DENTRY_KILLED already set), unlock everything
and either free the sucker (in case DCACHE_MAY_FREE has been
set) or leave it for ongoing dentry_kill(dentry, 1) to deal with.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2014-05-01 14:30:00 +00:00
|
|
|
can_free = false;
|
|
|
|
spin_unlock(&dentry->d_lock);
|
|
|
|
if (likely(can_free))
|
|
|
|
dentry_free(dentry);
|
__dentry_kill(): new locking scheme
Currently we enter __dentry_kill() with parent (along with the victim
dentry and victim's inode) held locked. Then we
mark dentry refcount as dead
call ->d_prune()
remove dentry from hash
remove it from the parent's list of children
unlock the parent, don't need it from that point on
detach dentry from inode, unlock dentry and drop the inode
(via ->d_iput())
call ->d_release()
regain the lock on dentry
check if it's on a shrink list (in which case freeing its empty husk
has to be left to shrink_dentry_list()) or not (in which case we can free it
ourselves). In the former case, mark it as an empty husk, so that
shrink_dentry_list() would know it can free the sucker.
drop the lock on dentry
... and usually the caller proceeds to drop a reference on the parent,
possibly retaking the lock on it.
That is painful for a bunch of reasons, starting with the need to take locks
out of order, but not limited to that - the parent of positive dentry can
change if we drop its ->d_lock, so getting these locks has to be done with
care. Moreover, as soon as dentry is out of the parent's list of children,
shrink_dcache_for_umount() won't see it anymore, making it appear as if
the parent is inexplicably busy. We do work around that by having
shrink_dentry_list() decrement the parent's refcount first and put it on
shrink list to be evicted once we are done with __dentry_kill() of child,
but that may in some cases lead to ->d_iput() on child called after the
parent got killed. That doesn't happen in cases where in-tree ->d_iput()
instances might want to look at the parent, but that's brittle as hell.
Solution: do removal from the parent's list of children in the very
end of __dentry_kill(). As the result, the callers do not need to
lock the parent and by the time we really need the parent locked,
dentry is negative and is guaranteed not to be moved around.
It does mean that ->d_prune() will be called with parent not locked.
It also means that we might see dentries in process of being torn
down while going through the parent's list of children; those dentries
will be unhashed, negative and with refcount marked dead. In practice,
that's enough for in-tree code that looks through the list of children
to do the right thing as-is. Out-of-tree code might need to be adjusted.
Calling conventions: __dentry_kill(dentry) is called with dentry->d_lock
held, along with ->i_lock of its inode (if any). It either returns
the parent (locked, with refcount decremented to 0) or NULL (if there'd
been no parent or if refcount decrement for parent hadn't reached 0).
lock_for_kill() is adjusted for new requirements - it doesn't touch
the parent's ->d_lock at all.
Callers adjusted. Note that for dput() we don't need to bother with
fast_dput() for the parent - we just need to check retain_dentry()
for it, since its ->d_lock is still held since the moment when
__dentry_kill() had taken it to remove the victim from the list of
children.
The kludge with early decrement of parent's refcount in
shrink_dentry_list() is no longer needed - shrink_dcache_for_umount()
sees the half-killed dentries in the list of children for as long
as they are pinning the parent. They are easily recognized and
accounted for by select_collect(), so we know we are not done yet.
As the result, we always have the expected ordering for ->d_iput()/->d_release()
vs. __dentry_kill() of the parent, no exceptions. Moreover, the current
rules for shrink lists (one must make sure that shrink_dcache_for_umount()
won't happen while any dentries from the superblock in question are on
any shrink lists) are gone - shrink_dcache_for_umount() will do the
right thing in all cases, taking such dentries out. Their empty
husks (memory occupied by struct dentry itself + its external name,
if any) will remain on the shrink lists, but they are no obstacles
to filesystem shutdown. And such husks will get freed as soon as
shrink_dentry_list() of the list they are on gets to them.
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-11-07 21:14:08 +00:00
|
|
|
if (parent && --parent->d_lockref.count) {
|
shrink_dentry_list(): take parent's ->d_lock earlier
The cause of livelocks there is that we are taking ->d_lock on
dentry and its parent in the wrong order, forcing us to use
trylock on the parent's one. d_walk() takes them in the right
order, and unfortunately it's not hard to create a situation
when shrink_dentry_list() can't make progress since trylock
keeps failing, and shrink_dcache_parent() or check_submounts_and_drop()
keeps calling d_walk() disrupting the very shrink_dentry_list() it's
waiting for.
Solution is straightforward - if that trylock fails, let's unlock
the dentry itself and take locks in the right order. We need to
stabilize ->d_parent without holding ->d_lock, but that's doable
using RCU. And we'd better do that in the very beginning of the
loop in shrink_dentry_list(), since the checks on refcount, etc.
would need to be redone anyway.
That deals with a half of the problem - killing dentries on the
shrink list itself. Another one (dropping their parents) is
in the next commit.
locking parent is interesting - it would be easy to do rcu_read_lock(),
lock whatever we think is a parent, lock dentry itself and check
if the parent is still the right one. Except that we need to check
that *before* locking the dentry, or we are risking taking ->d_lock
out of order. Fortunately, once the D1 is locked, we can check if
D2->d_parent is equal to D1 without the need to lock D2; D2->d_parent
can start or stop pointing to D1 only under D1->d_lock, so taking
D1->d_lock is enough. In other words, the right solution is
rcu_read_lock/lock what looks like parent right now/check if it's
still our parent/rcu_read_unlock/lock the child.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2014-05-29 12:54:52 +00:00
|
|
|
spin_unlock(&parent->d_lock);
|
__dentry_kill(): new locking scheme
Currently we enter __dentry_kill() with parent (along with the victim
dentry and victim's inode) held locked. Then we
mark dentry refcount as dead
call ->d_prune()
remove dentry from hash
remove it from the parent's list of children
unlock the parent, don't need it from that point on
detach dentry from inode, unlock dentry and drop the inode
(via ->d_iput())
call ->d_release()
regain the lock on dentry
check if it's on a shrink list (in which case freeing its empty husk
has to be left to shrink_dentry_list()) or not (in which case we can free it
ourselves). In the former case, mark it as an empty husk, so that
shrink_dentry_list() would know it can free the sucker.
drop the lock on dentry
... and usually the caller proceeds to drop a reference on the parent,
possibly retaking the lock on it.
That is painful for a bunch of reasons, starting with the need to take locks
out of order, but not limited to that - the parent of positive dentry can
change if we drop its ->d_lock, so getting these locks has to be done with
care. Moreover, as soon as dentry is out of the parent's list of children,
shrink_dcache_for_umount() won't see it anymore, making it appear as if
the parent is inexplicably busy. We do work around that by having
shrink_dentry_list() decrement the parent's refcount first and put it on
shrink list to be evicted once we are done with __dentry_kill() of child,
but that may in some cases lead to ->d_iput() on child called after the
parent got killed. That doesn't happen in cases where in-tree ->d_iput()
instances might want to look at the parent, but that's brittle as hell.
Solution: do removal from the parent's list of children in the very
end of __dentry_kill(). As the result, the callers do not need to
lock the parent and by the time we really need the parent locked,
dentry is negative and is guaranteed not to be moved around.
It does mean that ->d_prune() will be called with parent not locked.
It also means that we might see dentries in process of being torn
down while going through the parent's list of children; those dentries
will be unhashed, negative and with refcount marked dead. In practice,
that's enough for in-tree code that looks through the list of children
to do the right thing as-is. Out-of-tree code might need to be adjusted.
Calling conventions: __dentry_kill(dentry) is called with dentry->d_lock
held, along with ->i_lock of its inode (if any). It either returns
the parent (locked, with refcount decremented to 0) or NULL (if there'd
been no parent or if refcount decrement for parent hadn't reached 0).
lock_for_kill() is adjusted for new requirements - it doesn't touch
the parent's ->d_lock at all.
Callers adjusted. Note that for dput() we don't need to bother with
fast_dput() for the parent - we just need to check retain_dentry()
for it, since its ->d_lock is still held since the moment when
__dentry_kill() had taken it to remove the victim from the list of
children.
The kludge with early decrement of parent's refcount in
shrink_dentry_list() is no longer needed - shrink_dcache_for_umount()
sees the half-killed dentries in the list of children for as long
as they are pinning the parent. They are easily recognized and
accounted for by select_collect(), so we know we are not done yet.
As the result, we always have the expected ordering for ->d_iput()/->d_release()
vs. __dentry_kill() of the parent, no exceptions. Moreover, the current
rules for shrink lists (one must make sure that shrink_dcache_for_umount()
won't happen while any dentries from the superblock in question are on
any shrink lists) are gone - shrink_dcache_for_umount() will do the
right thing in all cases, taking such dentries out. Their empty
husks (memory occupied by struct dentry itself + its external name,
if any) will remain on the shrink lists, but they are no obstacles
to filesystem shutdown. And such husks will get freed as soon as
shrink_dentry_list() of the list they are on gets to them.
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-11-07 21:14:08 +00:00
|
|
|
return NULL;
|
shrink_dentry_list(): take parent's ->d_lock earlier
The cause of livelocks there is that we are taking ->d_lock on
dentry and its parent in the wrong order, forcing us to use
trylock on the parent's one. d_walk() takes them in the right
order, and unfortunately it's not hard to create a situation
when shrink_dentry_list() can't make progress since trylock
keeps failing, and shrink_dcache_parent() or check_submounts_and_drop()
keeps calling d_walk() disrupting the very shrink_dentry_list() it's
waiting for.
Solution is straightforward - if that trylock fails, let's unlock
the dentry itself and take locks in the right order. We need to
stabilize ->d_parent without holding ->d_lock, but that's doable
using RCU. And we'd better do that in the very beginning of the
loop in shrink_dentry_list(), since the checks on refcount, etc.
would need to be redone anyway.
That deals with a half of the problem - killing dentries on the
shrink list itself. Another one (dropping their parents) is
in the next commit.
locking parent is interesting - it would be easy to do rcu_read_lock(),
lock whatever we think is a parent, lock dentry itself and check
if the parent is still the right one. Except that we need to check
that *before* locking the dentry, or we are risking taking ->d_lock
out of order. Fortunately, once the D1 is locked, we can check if
D2->d_parent is equal to D1 without the need to lock D2; D2->d_parent
can start or stop pointing to D1 only under D1->d_lock, so taking
D1->d_lock is enough. In other words, the right solution is
rcu_read_lock/lock what looks like parent right now/check if it's
still our parent/rcu_read_unlock/lock the child.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2014-05-29 12:54:52 +00:00
|
|
|
}
|
|
|
|
return parent;
|
|
|
|
}
|
|
|
|
|
don't try to cut corners in shrink_lock_dentry()
That is to say, do *not* treat the ->d_inode or ->d_parent changes
as "it's hard, return false; somebody must have grabbed it, so
even if has zero refcount, we don't need to bother killing it -
final dput() from whoever grabbed it would've done everything".
First of all, that is not guaranteed. It might have been dropped
by shrink_kill() handling of victim's parent, which would've found
it already on a shrink list (ours) and decided that they don't need
to put it on their shrink list.
What's more, dentry_kill() is doing pretty much the same thing,
cutting its own set of corners (it assumes that dentry can't
go from positive to negative, so its inode can change but only once
and only in one direction).
Doing that right allows to get rid of that not-quite-duplication
and removes the only reason for re-incrementing refcount before
the call of dentry_kill().
Replacement is called lock_for_kill(); called under rcu_read_lock
and with ->d_lock held. If it returns false, dentry has non-zero
refcount and the same locks are held. If it returns true,
dentry has zero refcount and all locks required by __dentry_kill()
are taken.
Part of __lock_parent() had been lifted into lock_parent() to
allow its reuse. Now it's called with rcu_read_lock already
held and dentry already unlocked.
Note that this is not the final change - locking requirements for
__dentry_kill() are going to change later in the series and the
set of locks taken by lock_for_kill() will be adjusted. Both
lock_parent() and __lock_parent() will be gone once that happens.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-10-31 05:23:47 +00:00
|
|
|
/*
|
|
|
|
* Lock a dentry for feeding it to __dentry_kill().
|
|
|
|
* Called under rcu_read_lock() and dentry->d_lock; the former
|
|
|
|
* guarantees that nothing we access will be freed under us.
|
|
|
|
* Note that dentry is *not* protected from concurrent dentry_kill(),
|
|
|
|
* d_delete(), etc.
|
|
|
|
*
|
|
|
|
* Return false if dentry is busy. Otherwise, return true and have
|
__dentry_kill(): new locking scheme
Currently we enter __dentry_kill() with parent (along with the victim
dentry and victim's inode) held locked. Then we
mark dentry refcount as dead
call ->d_prune()
remove dentry from hash
remove it from the parent's list of children
unlock the parent, don't need it from that point on
detach dentry from inode, unlock dentry and drop the inode
(via ->d_iput())
call ->d_release()
regain the lock on dentry
check if it's on a shrink list (in which case freeing its empty husk
has to be left to shrink_dentry_list()) or not (in which case we can free it
ourselves). In the former case, mark it as an empty husk, so that
shrink_dentry_list() would know it can free the sucker.
drop the lock on dentry
... and usually the caller proceeds to drop a reference on the parent,
possibly retaking the lock on it.
That is painful for a bunch of reasons, starting with the need to take locks
out of order, but not limited to that - the parent of positive dentry can
change if we drop its ->d_lock, so getting these locks has to be done with
care. Moreover, as soon as dentry is out of the parent's list of children,
shrink_dcache_for_umount() won't see it anymore, making it appear as if
the parent is inexplicably busy. We do work around that by having
shrink_dentry_list() decrement the parent's refcount first and put it on
shrink list to be evicted once we are done with __dentry_kill() of child,
but that may in some cases lead to ->d_iput() on child called after the
parent got killed. That doesn't happen in cases where in-tree ->d_iput()
instances might want to look at the parent, but that's brittle as hell.
Solution: do removal from the parent's list of children in the very
end of __dentry_kill(). As the result, the callers do not need to
lock the parent and by the time we really need the parent locked,
dentry is negative and is guaranteed not to be moved around.
It does mean that ->d_prune() will be called with parent not locked.
It also means that we might see dentries in process of being torn
down while going through the parent's list of children; those dentries
will be unhashed, negative and with refcount marked dead. In practice,
that's enough for in-tree code that looks through the list of children
to do the right thing as-is. Out-of-tree code might need to be adjusted.
Calling conventions: __dentry_kill(dentry) is called with dentry->d_lock
held, along with ->i_lock of its inode (if any). It either returns
the parent (locked, with refcount decremented to 0) or NULL (if there'd
been no parent or if refcount decrement for parent hadn't reached 0).
lock_for_kill() is adjusted for new requirements - it doesn't touch
the parent's ->d_lock at all.
Callers adjusted. Note that for dput() we don't need to bother with
fast_dput() for the parent - we just need to check retain_dentry()
for it, since its ->d_lock is still held since the moment when
__dentry_kill() had taken it to remove the victim from the list of
children.
The kludge with early decrement of parent's refcount in
shrink_dentry_list() is no longer needed - shrink_dcache_for_umount()
sees the half-killed dentries in the list of children for as long
as they are pinning the parent. They are easily recognized and
accounted for by select_collect(), so we know we are not done yet.
As the result, we always have the expected ordering for ->d_iput()/->d_release()
vs. __dentry_kill() of the parent, no exceptions. Moreover, the current
rules for shrink lists (one must make sure that shrink_dcache_for_umount()
won't happen while any dentries from the superblock in question are on
any shrink lists) are gone - shrink_dcache_for_umount() will do the
right thing in all cases, taking such dentries out. Their empty
husks (memory occupied by struct dentry itself + its external name,
if any) will remain on the shrink lists, but they are no obstacles
to filesystem shutdown. And such husks will get freed as soon as
shrink_dentry_list() of the list they are on gets to them.
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-11-07 21:14:08 +00:00
|
|
|
* that dentry's inode locked.
|
don't try to cut corners in shrink_lock_dentry()
That is to say, do *not* treat the ->d_inode or ->d_parent changes
as "it's hard, return false; somebody must have grabbed it, so
even if has zero refcount, we don't need to bother killing it -
final dput() from whoever grabbed it would've done everything".
First of all, that is not guaranteed. It might have been dropped
by shrink_kill() handling of victim's parent, which would've found
it already on a shrink list (ours) and decided that they don't need
to put it on their shrink list.
What's more, dentry_kill() is doing pretty much the same thing,
cutting its own set of corners (it assumes that dentry can't
go from positive to negative, so its inode can change but only once
and only in one direction).
Doing that right allows to get rid of that not-quite-duplication
and removes the only reason for re-incrementing refcount before
the call of dentry_kill().
Replacement is called lock_for_kill(); called under rcu_read_lock
and with ->d_lock held. If it returns false, dentry has non-zero
refcount and the same locks are held. If it returns true,
dentry has zero refcount and all locks required by __dentry_kill()
are taken.
Part of __lock_parent() had been lifted into lock_parent() to
allow its reuse. Now it's called with rcu_read_lock already
held and dentry already unlocked.
Note that this is not the final change - locking requirements for
__dentry_kill() are going to change later in the series and the
set of locks taken by lock_for_kill() will be adjusted. Both
lock_parent() and __lock_parent() will be gone once that happens.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-10-31 05:23:47 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
static bool lock_for_kill(struct dentry *dentry)
|
2018-02-24 03:11:34 +00:00
|
|
|
{
|
don't try to cut corners in shrink_lock_dentry()
That is to say, do *not* treat the ->d_inode or ->d_parent changes
as "it's hard, return false; somebody must have grabbed it, so
even if has zero refcount, we don't need to bother killing it -
final dput() from whoever grabbed it would've done everything".
First of all, that is not guaranteed. It might have been dropped
by shrink_kill() handling of victim's parent, which would've found
it already on a shrink list (ours) and decided that they don't need
to put it on their shrink list.
What's more, dentry_kill() is doing pretty much the same thing,
cutting its own set of corners (it assumes that dentry can't
go from positive to negative, so its inode can change but only once
and only in one direction).
Doing that right allows to get rid of that not-quite-duplication
and removes the only reason for re-incrementing refcount before
the call of dentry_kill().
Replacement is called lock_for_kill(); called under rcu_read_lock
and with ->d_lock held. If it returns false, dentry has non-zero
refcount and the same locks are held. If it returns true,
dentry has zero refcount and all locks required by __dentry_kill()
are taken.
Part of __lock_parent() had been lifted into lock_parent() to
allow its reuse. Now it's called with rcu_read_lock already
held and dentry already unlocked.
Note that this is not the final change - locking requirements for
__dentry_kill() are going to change later in the series and the
set of locks taken by lock_for_kill() will be adjusted. Both
lock_parent() and __lock_parent() will be gone once that happens.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-10-31 05:23:47 +00:00
|
|
|
struct inode *inode = dentry->d_inode;
|
|
|
|
|
|
|
|
if (unlikely(dentry->d_lockref.count))
|
|
|
|
return false;
|
|
|
|
|
__dentry_kill(): new locking scheme
Currently we enter __dentry_kill() with parent (along with the victim
dentry and victim's inode) held locked. Then we
mark dentry refcount as dead
call ->d_prune()
remove dentry from hash
remove it from the parent's list of children
unlock the parent, don't need it from that point on
detach dentry from inode, unlock dentry and drop the inode
(via ->d_iput())
call ->d_release()
regain the lock on dentry
check if it's on a shrink list (in which case freeing its empty husk
has to be left to shrink_dentry_list()) or not (in which case we can free it
ourselves). In the former case, mark it as an empty husk, so that
shrink_dentry_list() would know it can free the sucker.
drop the lock on dentry
... and usually the caller proceeds to drop a reference on the parent,
possibly retaking the lock on it.
That is painful for a bunch of reasons, starting with the need to take locks
out of order, but not limited to that - the parent of positive dentry can
change if we drop its ->d_lock, so getting these locks has to be done with
care. Moreover, as soon as dentry is out of the parent's list of children,
shrink_dcache_for_umount() won't see it anymore, making it appear as if
the parent is inexplicably busy. We do work around that by having
shrink_dentry_list() decrement the parent's refcount first and put it on
shrink list to be evicted once we are done with __dentry_kill() of child,
but that may in some cases lead to ->d_iput() on child called after the
parent got killed. That doesn't happen in cases where in-tree ->d_iput()
instances might want to look at the parent, but that's brittle as hell.
Solution: do removal from the parent's list of children in the very
end of __dentry_kill(). As the result, the callers do not need to
lock the parent and by the time we really need the parent locked,
dentry is negative and is guaranteed not to be moved around.
It does mean that ->d_prune() will be called with parent not locked.
It also means that we might see dentries in process of being torn
down while going through the parent's list of children; those dentries
will be unhashed, negative and with refcount marked dead. In practice,
that's enough for in-tree code that looks through the list of children
to do the right thing as-is. Out-of-tree code might need to be adjusted.
Calling conventions: __dentry_kill(dentry) is called with dentry->d_lock
held, along with ->i_lock of its inode (if any). It either returns
the parent (locked, with refcount decremented to 0) or NULL (if there'd
been no parent or if refcount decrement for parent hadn't reached 0).
lock_for_kill() is adjusted for new requirements - it doesn't touch
the parent's ->d_lock at all.
Callers adjusted. Note that for dput() we don't need to bother with
fast_dput() for the parent - we just need to check retain_dentry()
for it, since its ->d_lock is still held since the moment when
__dentry_kill() had taken it to remove the victim from the list of
children.
The kludge with early decrement of parent's refcount in
shrink_dentry_list() is no longer needed - shrink_dcache_for_umount()
sees the half-killed dentries in the list of children for as long
as they are pinning the parent. They are easily recognized and
accounted for by select_collect(), so we know we are not done yet.
As the result, we always have the expected ordering for ->d_iput()/->d_release()
vs. __dentry_kill() of the parent, no exceptions. Moreover, the current
rules for shrink lists (one must make sure that shrink_dcache_for_umount()
won't happen while any dentries from the superblock in question are on
any shrink lists) are gone - shrink_dcache_for_umount() will do the
right thing in all cases, taking such dentries out. Their empty
husks (memory occupied by struct dentry itself + its external name,
if any) will remain on the shrink lists, but they are no obstacles
to filesystem shutdown. And such husks will get freed as soon as
shrink_dentry_list() of the list they are on gets to them.
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-11-07 21:14:08 +00:00
|
|
|
if (!inode || likely(spin_trylock(&inode->i_lock)))
|
don't try to cut corners in shrink_lock_dentry()
That is to say, do *not* treat the ->d_inode or ->d_parent changes
as "it's hard, return false; somebody must have grabbed it, so
even if has zero refcount, we don't need to bother killing it -
final dput() from whoever grabbed it would've done everything".
First of all, that is not guaranteed. It might have been dropped
by shrink_kill() handling of victim's parent, which would've found
it already on a shrink list (ours) and decided that they don't need
to put it on their shrink list.
What's more, dentry_kill() is doing pretty much the same thing,
cutting its own set of corners (it assumes that dentry can't
go from positive to negative, so its inode can change but only once
and only in one direction).
Doing that right allows to get rid of that not-quite-duplication
and removes the only reason for re-incrementing refcount before
the call of dentry_kill().
Replacement is called lock_for_kill(); called under rcu_read_lock
and with ->d_lock held. If it returns false, dentry has non-zero
refcount and the same locks are held. If it returns true,
dentry has zero refcount and all locks required by __dentry_kill()
are taken.
Part of __lock_parent() had been lifted into lock_parent() to
allow its reuse. Now it's called with rcu_read_lock already
held and dentry already unlocked.
Note that this is not the final change - locking requirements for
__dentry_kill() are going to change later in the series and the
set of locks taken by lock_for_kill() will be adjusted. Both
lock_parent() and __lock_parent() will be gone once that happens.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-10-31 05:23:47 +00:00
|
|
|
return true;
|
|
|
|
|
__dentry_kill(): new locking scheme
Currently we enter __dentry_kill() with parent (along with the victim
dentry and victim's inode) held locked. Then we
mark dentry refcount as dead
call ->d_prune()
remove dentry from hash
remove it from the parent's list of children
unlock the parent, don't need it from that point on
detach dentry from inode, unlock dentry and drop the inode
(via ->d_iput())
call ->d_release()
regain the lock on dentry
check if it's on a shrink list (in which case freeing its empty husk
has to be left to shrink_dentry_list()) or not (in which case we can free it
ourselves). In the former case, mark it as an empty husk, so that
shrink_dentry_list() would know it can free the sucker.
drop the lock on dentry
... and usually the caller proceeds to drop a reference on the parent,
possibly retaking the lock on it.
That is painful for a bunch of reasons, starting with the need to take locks
out of order, but not limited to that - the parent of positive dentry can
change if we drop its ->d_lock, so getting these locks has to be done with
care. Moreover, as soon as dentry is out of the parent's list of children,
shrink_dcache_for_umount() won't see it anymore, making it appear as if
the parent is inexplicably busy. We do work around that by having
shrink_dentry_list() decrement the parent's refcount first and put it on
shrink list to be evicted once we are done with __dentry_kill() of child,
but that may in some cases lead to ->d_iput() on child called after the
parent got killed. That doesn't happen in cases where in-tree ->d_iput()
instances might want to look at the parent, but that's brittle as hell.
Solution: do removal from the parent's list of children in the very
end of __dentry_kill(). As the result, the callers do not need to
lock the parent and by the time we really need the parent locked,
dentry is negative and is guaranteed not to be moved around.
It does mean that ->d_prune() will be called with parent not locked.
It also means that we might see dentries in process of being torn
down while going through the parent's list of children; those dentries
will be unhashed, negative and with refcount marked dead. In practice,
that's enough for in-tree code that looks through the list of children
to do the right thing as-is. Out-of-tree code might need to be adjusted.
Calling conventions: __dentry_kill(dentry) is called with dentry->d_lock
held, along with ->i_lock of its inode (if any). It either returns
the parent (locked, with refcount decremented to 0) or NULL (if there'd
been no parent or if refcount decrement for parent hadn't reached 0).
lock_for_kill() is adjusted for new requirements - it doesn't touch
the parent's ->d_lock at all.
Callers adjusted. Note that for dput() we don't need to bother with
fast_dput() for the parent - we just need to check retain_dentry()
for it, since its ->d_lock is still held since the moment when
__dentry_kill() had taken it to remove the victim from the list of
children.
The kludge with early decrement of parent's refcount in
shrink_dentry_list() is no longer needed - shrink_dcache_for_umount()
sees the half-killed dentries in the list of children for as long
as they are pinning the parent. They are easily recognized and
accounted for by select_collect(), so we know we are not done yet.
As the result, we always have the expected ordering for ->d_iput()/->d_release()
vs. __dentry_kill() of the parent, no exceptions. Moreover, the current
rules for shrink lists (one must make sure that shrink_dcache_for_umount()
won't happen while any dentries from the superblock in question are on
any shrink lists) are gone - shrink_dcache_for_umount() will do the
right thing in all cases, taking such dentries out. Their empty
husks (memory occupied by struct dentry itself + its external name,
if any) will remain on the shrink lists, but they are no obstacles
to filesystem shutdown. And such husks will get freed as soon as
shrink_dentry_list() of the list they are on gets to them.
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-11-07 21:14:08 +00:00
|
|
|
do {
|
|
|
|
spin_unlock(&dentry->d_lock);
|
|
|
|
spin_lock(&inode->i_lock);
|
|
|
|
spin_lock(&dentry->d_lock);
|
don't try to cut corners in shrink_lock_dentry()
That is to say, do *not* treat the ->d_inode or ->d_parent changes
as "it's hard, return false; somebody must have grabbed it, so
even if has zero refcount, we don't need to bother killing it -
final dput() from whoever grabbed it would've done everything".
First of all, that is not guaranteed. It might have been dropped
by shrink_kill() handling of victim's parent, which would've found
it already on a shrink list (ours) and decided that they don't need
to put it on their shrink list.
What's more, dentry_kill() is doing pretty much the same thing,
cutting its own set of corners (it assumes that dentry can't
go from positive to negative, so its inode can change but only once
and only in one direction).
Doing that right allows to get rid of that not-quite-duplication
and removes the only reason for re-incrementing refcount before
the call of dentry_kill().
Replacement is called lock_for_kill(); called under rcu_read_lock
and with ->d_lock held. If it returns false, dentry has non-zero
refcount and the same locks are held. If it returns true,
dentry has zero refcount and all locks required by __dentry_kill()
are taken.
Part of __lock_parent() had been lifted into lock_parent() to
allow its reuse. Now it's called with rcu_read_lock already
held and dentry already unlocked.
Note that this is not the final change - locking requirements for
__dentry_kill() are going to change later in the series and the
set of locks taken by lock_for_kill() will be adjusted. Both
lock_parent() and __lock_parent() will be gone once that happens.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-10-31 05:23:47 +00:00
|
|
|
if (likely(inode == dentry->d_inode))
|
|
|
|
break;
|
__dentry_kill(): new locking scheme
Currently we enter __dentry_kill() with parent (along with the victim
dentry and victim's inode) held locked. Then we
mark dentry refcount as dead
call ->d_prune()
remove dentry from hash
remove it from the parent's list of children
unlock the parent, don't need it from that point on
detach dentry from inode, unlock dentry and drop the inode
(via ->d_iput())
call ->d_release()
regain the lock on dentry
check if it's on a shrink list (in which case freeing its empty husk
has to be left to shrink_dentry_list()) or not (in which case we can free it
ourselves). In the former case, mark it as an empty husk, so that
shrink_dentry_list() would know it can free the sucker.
drop the lock on dentry
... and usually the caller proceeds to drop a reference on the parent,
possibly retaking the lock on it.
That is painful for a bunch of reasons, starting with the need to take locks
out of order, but not limited to that - the parent of positive dentry can
change if we drop its ->d_lock, so getting these locks has to be done with
care. Moreover, as soon as dentry is out of the parent's list of children,
shrink_dcache_for_umount() won't see it anymore, making it appear as if
the parent is inexplicably busy. We do work around that by having
shrink_dentry_list() decrement the parent's refcount first and put it on
shrink list to be evicted once we are done with __dentry_kill() of child,
but that may in some cases lead to ->d_iput() on child called after the
parent got killed. That doesn't happen in cases where in-tree ->d_iput()
instances might want to look at the parent, but that's brittle as hell.
Solution: do removal from the parent's list of children in the very
end of __dentry_kill(). As the result, the callers do not need to
lock the parent and by the time we really need the parent locked,
dentry is negative and is guaranteed not to be moved around.
It does mean that ->d_prune() will be called with parent not locked.
It also means that we might see dentries in process of being torn
down while going through the parent's list of children; those dentries
will be unhashed, negative and with refcount marked dead. In practice,
that's enough for in-tree code that looks through the list of children
to do the right thing as-is. Out-of-tree code might need to be adjusted.
Calling conventions: __dentry_kill(dentry) is called with dentry->d_lock
held, along with ->i_lock of its inode (if any). It either returns
the parent (locked, with refcount decremented to 0) or NULL (if there'd
been no parent or if refcount decrement for parent hadn't reached 0).
lock_for_kill() is adjusted for new requirements - it doesn't touch
the parent's ->d_lock at all.
Callers adjusted. Note that for dput() we don't need to bother with
fast_dput() for the parent - we just need to check retain_dentry()
for it, since its ->d_lock is still held since the moment when
__dentry_kill() had taken it to remove the victim from the list of
children.
The kludge with early decrement of parent's refcount in
shrink_dentry_list() is no longer needed - shrink_dcache_for_umount()
sees the half-killed dentries in the list of children for as long
as they are pinning the parent. They are easily recognized and
accounted for by select_collect(), so we know we are not done yet.
As the result, we always have the expected ordering for ->d_iput()/->d_release()
vs. __dentry_kill() of the parent, no exceptions. Moreover, the current
rules for shrink lists (one must make sure that shrink_dcache_for_umount()
won't happen while any dentries from the superblock in question are on
any shrink lists) are gone - shrink_dcache_for_umount() will do the
right thing in all cases, taking such dentries out. Their empty
husks (memory occupied by struct dentry itself + its external name,
if any) will remain on the shrink lists, but they are no obstacles
to filesystem shutdown. And such husks will get freed as soon as
shrink_dentry_list() of the list they are on gets to them.
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-11-07 21:14:08 +00:00
|
|
|
spin_unlock(&inode->i_lock);
|
don't try to cut corners in shrink_lock_dentry()
That is to say, do *not* treat the ->d_inode or ->d_parent changes
as "it's hard, return false; somebody must have grabbed it, so
even if has zero refcount, we don't need to bother killing it -
final dput() from whoever grabbed it would've done everything".
First of all, that is not guaranteed. It might have been dropped
by shrink_kill() handling of victim's parent, which would've found
it already on a shrink list (ours) and decided that they don't need
to put it on their shrink list.
What's more, dentry_kill() is doing pretty much the same thing,
cutting its own set of corners (it assumes that dentry can't
go from positive to negative, so its inode can change but only once
and only in one direction).
Doing that right allows to get rid of that not-quite-duplication
and removes the only reason for re-incrementing refcount before
the call of dentry_kill().
Replacement is called lock_for_kill(); called under rcu_read_lock
and with ->d_lock held. If it returns false, dentry has non-zero
refcount and the same locks are held. If it returns true,
dentry has zero refcount and all locks required by __dentry_kill()
are taken.
Part of __lock_parent() had been lifted into lock_parent() to
allow its reuse. Now it's called with rcu_read_lock already
held and dentry already unlocked.
Note that this is not the final change - locking requirements for
__dentry_kill() are going to change later in the series and the
set of locks taken by lock_for_kill() will be adjusted. Both
lock_parent() and __lock_parent() will be gone once that happens.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-10-31 05:23:47 +00:00
|
|
|
inode = dentry->d_inode;
|
__dentry_kill(): new locking scheme
Currently we enter __dentry_kill() with parent (along with the victim
dentry and victim's inode) held locked. Then we
mark dentry refcount as dead
call ->d_prune()
remove dentry from hash
remove it from the parent's list of children
unlock the parent, don't need it from that point on
detach dentry from inode, unlock dentry and drop the inode
(via ->d_iput())
call ->d_release()
regain the lock on dentry
check if it's on a shrink list (in which case freeing its empty husk
has to be left to shrink_dentry_list()) or not (in which case we can free it
ourselves). In the former case, mark it as an empty husk, so that
shrink_dentry_list() would know it can free the sucker.
drop the lock on dentry
... and usually the caller proceeds to drop a reference on the parent,
possibly retaking the lock on it.
That is painful for a bunch of reasons, starting with the need to take locks
out of order, but not limited to that - the parent of positive dentry can
change if we drop its ->d_lock, so getting these locks has to be done with
care. Moreover, as soon as dentry is out of the parent's list of children,
shrink_dcache_for_umount() won't see it anymore, making it appear as if
the parent is inexplicably busy. We do work around that by having
shrink_dentry_list() decrement the parent's refcount first and put it on
shrink list to be evicted once we are done with __dentry_kill() of child,
but that may in some cases lead to ->d_iput() on child called after the
parent got killed. That doesn't happen in cases where in-tree ->d_iput()
instances might want to look at the parent, but that's brittle as hell.
Solution: do removal from the parent's list of children in the very
end of __dentry_kill(). As the result, the callers do not need to
lock the parent and by the time we really need the parent locked,
dentry is negative and is guaranteed not to be moved around.
It does mean that ->d_prune() will be called with parent not locked.
It also means that we might see dentries in process of being torn
down while going through the parent's list of children; those dentries
will be unhashed, negative and with refcount marked dead. In practice,
that's enough for in-tree code that looks through the list of children
to do the right thing as-is. Out-of-tree code might need to be adjusted.
Calling conventions: __dentry_kill(dentry) is called with dentry->d_lock
held, along with ->i_lock of its inode (if any). It either returns
the parent (locked, with refcount decremented to 0) or NULL (if there'd
been no parent or if refcount decrement for parent hadn't reached 0).
lock_for_kill() is adjusted for new requirements - it doesn't touch
the parent's ->d_lock at all.
Callers adjusted. Note that for dput() we don't need to bother with
fast_dput() for the parent - we just need to check retain_dentry()
for it, since its ->d_lock is still held since the moment when
__dentry_kill() had taken it to remove the victim from the list of
children.
The kludge with early decrement of parent's refcount in
shrink_dentry_list() is no longer needed - shrink_dcache_for_umount()
sees the half-killed dentries in the list of children for as long
as they are pinning the parent. They are easily recognized and
accounted for by select_collect(), so we know we are not done yet.
As the result, we always have the expected ordering for ->d_iput()/->d_release()
vs. __dentry_kill() of the parent, no exceptions. Moreover, the current
rules for shrink lists (one must make sure that shrink_dcache_for_umount()
won't happen while any dentries from the superblock in question are on
any shrink lists) are gone - shrink_dcache_for_umount() will do the
right thing in all cases, taking such dentries out. Their empty
husks (memory occupied by struct dentry itself + its external name,
if any) will remain on the shrink lists, but they are no obstacles
to filesystem shutdown. And such husks will get freed as soon as
shrink_dentry_list() of the list they are on gets to them.
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-11-07 21:14:08 +00:00
|
|
|
} while (inode);
|
don't try to cut corners in shrink_lock_dentry()
That is to say, do *not* treat the ->d_inode or ->d_parent changes
as "it's hard, return false; somebody must have grabbed it, so
even if has zero refcount, we don't need to bother killing it -
final dput() from whoever grabbed it would've done everything".
First of all, that is not guaranteed. It might have been dropped
by shrink_kill() handling of victim's parent, which would've found
it already on a shrink list (ours) and decided that they don't need
to put it on their shrink list.
What's more, dentry_kill() is doing pretty much the same thing,
cutting its own set of corners (it assumes that dentry can't
go from positive to negative, so its inode can change but only once
and only in one direction).
Doing that right allows to get rid of that not-quite-duplication
and removes the only reason for re-incrementing refcount before
the call of dentry_kill().
Replacement is called lock_for_kill(); called under rcu_read_lock
and with ->d_lock held. If it returns false, dentry has non-zero
refcount and the same locks are held. If it returns true,
dentry has zero refcount and all locks required by __dentry_kill()
are taken.
Part of __lock_parent() had been lifted into lock_parent() to
allow its reuse. Now it's called with rcu_read_lock already
held and dentry already unlocked.
Note that this is not the final change - locking requirements for
__dentry_kill() are going to change later in the series and the
set of locks taken by lock_for_kill() will be adjusted. Both
lock_parent() and __lock_parent() will be gone once that happens.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-10-31 05:23:47 +00:00
|
|
|
if (likely(!dentry->d_lockref.count))
|
|
|
|
return true;
|
|
|
|
if (inode)
|
|
|
|
spin_unlock(&inode->i_lock);
|
|
|
|
return false;
|
2018-02-24 03:11:34 +00:00
|
|
|
}
|
|
|
|
|
2023-11-23 22:33:21 +00:00
|
|
|
/*
|
|
|
|
* Decide if dentry is worth retaining. Usually this is called with dentry
|
|
|
|
* locked; if not locked, we are more limited and might not be able to tell
|
|
|
|
* without a lock. False in this case means "punt to locked path and recheck".
|
|
|
|
*
|
|
|
|
* In case we aren't locked, these predicates are not "stable". However, it is
|
|
|
|
* sufficient that at some point after we dropped the reference the dentry was
|
|
|
|
* hashed and the flags had the proper value. Other dentry users may have
|
|
|
|
* re-gotten a reference to the dentry and change that, but our work is done -
|
|
|
|
* we can leave the dentry around with a zero refcount.
|
|
|
|
*/
|
|
|
|
static inline bool retain_dentry(struct dentry *dentry, bool locked)
|
2018-02-24 02:07:24 +00:00
|
|
|
{
|
2023-11-23 22:33:21 +00:00
|
|
|
unsigned int d_flags;
|
2018-02-24 02:07:24 +00:00
|
|
|
|
2023-11-23 22:33:21 +00:00
|
|
|
smp_rmb();
|
|
|
|
d_flags = READ_ONCE(dentry->d_flags);
|
2018-02-24 02:07:24 +00:00
|
|
|
|
2023-11-23 22:33:21 +00:00
|
|
|
// Unreachable? Nobody would be able to look it up, no point retaining
|
2018-02-24 02:07:24 +00:00
|
|
|
if (unlikely(d_unhashed(dentry)))
|
|
|
|
return false;
|
|
|
|
|
2023-11-23 22:33:21 +00:00
|
|
|
// Same if it's disconnected
|
|
|
|
if (unlikely(d_flags & DCACHE_DISCONNECTED))
|
2018-02-24 02:07:24 +00:00
|
|
|
return false;
|
|
|
|
|
2023-11-23 22:33:21 +00:00
|
|
|
// ->d_delete() might tell us not to bother, but that requires
|
|
|
|
// ->d_lock; can't decide without it
|
|
|
|
if (unlikely(d_flags & DCACHE_OP_DELETE)) {
|
|
|
|
if (!locked || dentry->d_op->d_delete(dentry))
|
2018-02-24 02:07:24 +00:00
|
|
|
return false;
|
|
|
|
}
|
2020-04-30 14:41:37 +00:00
|
|
|
|
2023-11-23 22:33:21 +00:00
|
|
|
// Explicitly told not to bother
|
|
|
|
if (unlikely(d_flags & DCACHE_DONTCACHE))
|
2020-04-30 14:41:37 +00:00
|
|
|
return false;
|
|
|
|
|
2023-11-23 22:33:21 +00:00
|
|
|
// At this point it looks like we ought to keep it. We also might
|
|
|
|
// need to do something - put it on LRU if it wasn't there already
|
|
|
|
// and mark it referenced if it was on LRU, but not marked yet.
|
|
|
|
// Unfortunately, both actions require ->d_lock, so in lockless
|
|
|
|
// case we'd have to punt rather than doing those.
|
|
|
|
if (unlikely(!(d_flags & DCACHE_LRU_LIST))) {
|
|
|
|
if (!locked)
|
|
|
|
return false;
|
2018-03-07 02:37:31 +00:00
|
|
|
d_lru_add(dentry);
|
2023-11-23 22:33:21 +00:00
|
|
|
} else if (unlikely(!(d_flags & DCACHE_REFERENCED))) {
|
|
|
|
if (!locked)
|
|
|
|
return false;
|
2018-03-07 02:37:31 +00:00
|
|
|
dentry->d_flags |= DCACHE_REFERENCED;
|
2023-11-23 22:33:21 +00:00
|
|
|
}
|
2018-02-24 02:07:24 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-04-30 14:41:37 +00:00
|
|
|
void d_mark_dontcache(struct inode *inode)
|
|
|
|
{
|
|
|
|
struct dentry *de;
|
|
|
|
|
|
|
|
spin_lock(&inode->i_lock);
|
|
|
|
hlist_for_each_entry(de, &inode->i_dentry, d_u.d_alias) {
|
|
|
|
spin_lock(&de->d_lock);
|
|
|
|
de->d_flags |= DCACHE_DONTCACHE;
|
|
|
|
spin_unlock(&de->d_lock);
|
|
|
|
}
|
|
|
|
inode->i_state |= I_DONTCACHE;
|
|
|
|
spin_unlock(&inode->i_lock);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(d_mark_dontcache);
|
|
|
|
|
2015-01-09 23:19:03 +00:00
|
|
|
/*
|
|
|
|
* Try to do a lockless dput(), and return whether that was successful.
|
|
|
|
*
|
|
|
|
* If unsuccessful, we return false, having already taken the dentry lock.
|
2023-10-31 04:45:40 +00:00
|
|
|
* In that case refcount is guaranteed to be zero and we have already
|
|
|
|
* decided that it's not worth keeping around.
|
2015-01-09 23:19:03 +00:00
|
|
|
*
|
|
|
|
* The caller needs to hold the RCU read lock, so that the dentry is
|
|
|
|
* guaranteed to stay around even if the refcount goes down to zero!
|
|
|
|
*/
|
|
|
|
static inline bool fast_dput(struct dentry *dentry)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/*
|
2023-10-30 04:02:14 +00:00
|
|
|
* try to decrement the lockref optimistically.
|
2015-01-09 23:19:03 +00:00
|
|
|
*/
|
|
|
|
ret = lockref_put_return(&dentry->d_lockref);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the lockref_put_return() failed due to the lock being held
|
|
|
|
* by somebody else, the fast path has failed. We will need to
|
|
|
|
* get the lock, and then check the count again.
|
|
|
|
*/
|
|
|
|
if (unlikely(ret < 0)) {
|
|
|
|
spin_lock(&dentry->d_lock);
|
fast_dput(): handle underflows gracefully
If refcount is less than 1, we should just warn, unlock dentry and
return true, so that the caller doesn't try to do anything else.
Taking care of that leaves the rest of "lockref_put_return() has
failed" case equivalent to "decrement refcount and rejoin the
normal slow path after the point where we grab ->d_lock".
NOTE: lockref_put_return() is strictly a fastpath thing - unlike
the rest of lockref primitives, it does not contain a fallback.
Caller (and it looks like fast_dput() is the only legitimate one
in the entire kernel) has to do that itself. Reasons for
lockref_put_return() failures:
* ->d_lock held by somebody
* refcount <= 0
* ... or an architecture not supporting lockref use of
cmpxchg - sparc, anything non-SMP, config with spinlock debugging...
We could add a fallback, but it would be a clumsy API - we'd have
to distinguish between:
(1) refcount > 1 - decremented, lock not held on return
(2) refcount < 1 - left alone, probably no sense to hold the lock
(3) refcount is 1, no cmphxcg - decremented, lock held on return
(4) refcount is 1, cmphxcg supported - decremented, lock *NOT* held
on return.
We want to return with no lock held in case (4); that's the whole point of that
thing. We very much do not want to have the fallback in case (3) return without
a lock, since the caller might have to retake it in that case.
So it wouldn't be more convenient than doing the fallback in the caller and
it would be very easy to screw up, especially since the test coverage would
suck - no way to test (3) and (4) on the same kernel build.
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-11-01 05:08:54 +00:00
|
|
|
if (WARN_ON_ONCE(dentry->d_lockref.count <= 0)) {
|
2015-01-09 23:19:03 +00:00
|
|
|
spin_unlock(&dentry->d_lock);
|
2018-08-02 00:39:05 +00:00
|
|
|
return true;
|
2015-01-09 23:19:03 +00:00
|
|
|
}
|
fast_dput(): handle underflows gracefully
If refcount is less than 1, we should just warn, unlock dentry and
return true, so that the caller doesn't try to do anything else.
Taking care of that leaves the rest of "lockref_put_return() has
failed" case equivalent to "decrement refcount and rejoin the
normal slow path after the point where we grab ->d_lock".
NOTE: lockref_put_return() is strictly a fastpath thing - unlike
the rest of lockref primitives, it does not contain a fallback.
Caller (and it looks like fast_dput() is the only legitimate one
in the entire kernel) has to do that itself. Reasons for
lockref_put_return() failures:
* ->d_lock held by somebody
* refcount <= 0
* ... or an architecture not supporting lockref use of
cmpxchg - sparc, anything non-SMP, config with spinlock debugging...
We could add a fallback, but it would be a clumsy API - we'd have
to distinguish between:
(1) refcount > 1 - decremented, lock not held on return
(2) refcount < 1 - left alone, probably no sense to hold the lock
(3) refcount is 1, no cmphxcg - decremented, lock held on return
(4) refcount is 1, cmphxcg supported - decremented, lock *NOT* held
on return.
We want to return with no lock held in case (4); that's the whole point of that
thing. We very much do not want to have the fallback in case (3) return without
a lock, since the caller might have to retake it in that case.
So it wouldn't be more convenient than doing the fallback in the caller and
it would be very easy to screw up, especially since the test coverage would
suck - no way to test (3) and (4) on the same kernel build.
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-11-01 05:08:54 +00:00
|
|
|
dentry->d_lockref.count--;
|
|
|
|
goto locked;
|
2015-01-09 23:19:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we weren't the last ref, we're done.
|
|
|
|
*/
|
|
|
|
if (ret)
|
2018-08-02 00:39:05 +00:00
|
|
|
return true;
|
2015-01-09 23:19:03 +00:00
|
|
|
|
|
|
|
/*
|
2023-11-23 22:33:21 +00:00
|
|
|
* Can we decide that decrement of refcount is all we needed without
|
|
|
|
* taking the lock? There's a very common case when it's all we need -
|
|
|
|
* dentry looks like it ought to be retained and there's nothing else
|
|
|
|
* to do.
|
2015-01-09 23:19:03 +00:00
|
|
|
*/
|
2023-11-23 22:33:21 +00:00
|
|
|
if (retain_dentry(dentry, false))
|
2018-08-02 00:39:05 +00:00
|
|
|
return true;
|
2015-01-09 23:19:03 +00:00
|
|
|
|
|
|
|
/*
|
2023-11-23 22:33:21 +00:00
|
|
|
* Either not worth retaining or we can't tell without the lock.
|
|
|
|
* Get the lock, then. We've already decremented the refcount to 0,
|
|
|
|
* but we'll need to re-check the situation after getting the lock.
|
2015-01-09 23:19:03 +00:00
|
|
|
*/
|
|
|
|
spin_lock(&dentry->d_lock);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Did somebody else grab a reference to it in the meantime, and
|
|
|
|
* we're no longer the last user after all? Alternatively, somebody
|
|
|
|
* else could have killed it and marked it dead. Either way, we
|
|
|
|
* don't need to do anything else.
|
|
|
|
*/
|
fast_dput(): handle underflows gracefully
If refcount is less than 1, we should just warn, unlock dentry and
return true, so that the caller doesn't try to do anything else.
Taking care of that leaves the rest of "lockref_put_return() has
failed" case equivalent to "decrement refcount and rejoin the
normal slow path after the point where we grab ->d_lock".
NOTE: lockref_put_return() is strictly a fastpath thing - unlike
the rest of lockref primitives, it does not contain a fallback.
Caller (and it looks like fast_dput() is the only legitimate one
in the entire kernel) has to do that itself. Reasons for
lockref_put_return() failures:
* ->d_lock held by somebody
* refcount <= 0
* ... or an architecture not supporting lockref use of
cmpxchg - sparc, anything non-SMP, config with spinlock debugging...
We could add a fallback, but it would be a clumsy API - we'd have
to distinguish between:
(1) refcount > 1 - decremented, lock not held on return
(2) refcount < 1 - left alone, probably no sense to hold the lock
(3) refcount is 1, no cmphxcg - decremented, lock held on return
(4) refcount is 1, cmphxcg supported - decremented, lock *NOT* held
on return.
We want to return with no lock held in case (4); that's the whole point of that
thing. We very much do not want to have the fallback in case (3) return without
a lock, since the caller might have to retake it in that case.
So it wouldn't be more convenient than doing the fallback in the caller and
it would be very easy to screw up, especially since the test coverage would
suck - no way to test (3) and (4) on the same kernel build.
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-11-01 05:08:54 +00:00
|
|
|
locked:
|
2023-11-23 22:33:21 +00:00
|
|
|
if (dentry->d_lockref.count || retain_dentry(dentry, true)) {
|
2015-01-09 23:19:03 +00:00
|
|
|
spin_unlock(&dentry->d_lock);
|
2018-08-02 00:39:05 +00:00
|
|
|
return true;
|
2015-01-09 23:19:03 +00:00
|
|
|
}
|
2018-08-02 00:39:05 +00:00
|
|
|
return false;
|
2015-01-09 23:19:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* This is dput
|
|
|
|
*
|
|
|
|
* This is complicated by the fact that we do not want to put
|
|
|
|
* dentries that are no longer on any hash chain on the unused
|
|
|
|
* list: we'd much rather just get rid of them immediately.
|
|
|
|
*
|
|
|
|
* However, that implies that we have to traverse the dentry
|
|
|
|
* tree upwards to the parents which might _also_ now be
|
|
|
|
* scheduled for deletion (it may have been only waiting for
|
|
|
|
* its last child to go away).
|
|
|
|
*
|
|
|
|
* This tail recursion is done by hand as we don't want to depend
|
|
|
|
* on the compiler to always get this right (gcc generally doesn't).
|
|
|
|
* Real recursion would eat up our stack space.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* dput - release a dentry
|
|
|
|
* @dentry: dentry to release
|
|
|
|
*
|
|
|
|
* Release a dentry. This will drop the usage count and if appropriate
|
|
|
|
* call the dentry unlink method as well as removing it from the queues and
|
|
|
|
* releasing its resources. If the parent dentries were scheduled for release
|
|
|
|
* they too may now get deleted.
|
|
|
|
*/
|
|
|
|
void dput(struct dentry *dentry)
|
|
|
|
{
|
__dentry_kill(): new locking scheme
Currently we enter __dentry_kill() with parent (along with the victim
dentry and victim's inode) held locked. Then we
mark dentry refcount as dead
call ->d_prune()
remove dentry from hash
remove it from the parent's list of children
unlock the parent, don't need it from that point on
detach dentry from inode, unlock dentry and drop the inode
(via ->d_iput())
call ->d_release()
regain the lock on dentry
check if it's on a shrink list (in which case freeing its empty husk
has to be left to shrink_dentry_list()) or not (in which case we can free it
ourselves). In the former case, mark it as an empty husk, so that
shrink_dentry_list() would know it can free the sucker.
drop the lock on dentry
... and usually the caller proceeds to drop a reference on the parent,
possibly retaking the lock on it.
That is painful for a bunch of reasons, starting with the need to take locks
out of order, but not limited to that - the parent of positive dentry can
change if we drop its ->d_lock, so getting these locks has to be done with
care. Moreover, as soon as dentry is out of the parent's list of children,
shrink_dcache_for_umount() won't see it anymore, making it appear as if
the parent is inexplicably busy. We do work around that by having
shrink_dentry_list() decrement the parent's refcount first and put it on
shrink list to be evicted once we are done with __dentry_kill() of child,
but that may in some cases lead to ->d_iput() on child called after the
parent got killed. That doesn't happen in cases where in-tree ->d_iput()
instances might want to look at the parent, but that's brittle as hell.
Solution: do removal from the parent's list of children in the very
end of __dentry_kill(). As the result, the callers do not need to
lock the parent and by the time we really need the parent locked,
dentry is negative and is guaranteed not to be moved around.
It does mean that ->d_prune() will be called with parent not locked.
It also means that we might see dentries in process of being torn
down while going through the parent's list of children; those dentries
will be unhashed, negative and with refcount marked dead. In practice,
that's enough for in-tree code that looks through the list of children
to do the right thing as-is. Out-of-tree code might need to be adjusted.
Calling conventions: __dentry_kill(dentry) is called with dentry->d_lock
held, along with ->i_lock of its inode (if any). It either returns
the parent (locked, with refcount decremented to 0) or NULL (if there'd
been no parent or if refcount decrement for parent hadn't reached 0).
lock_for_kill() is adjusted for new requirements - it doesn't touch
the parent's ->d_lock at all.
Callers adjusted. Note that for dput() we don't need to bother with
fast_dput() for the parent - we just need to check retain_dentry()
for it, since its ->d_lock is still held since the moment when
__dentry_kill() had taken it to remove the victim from the list of
children.
The kludge with early decrement of parent's refcount in
shrink_dentry_list() is no longer needed - shrink_dcache_for_umount()
sees the half-killed dentries in the list of children for as long
as they are pinning the parent. They are easily recognized and
accounted for by select_collect(), so we know we are not done yet.
As the result, we always have the expected ordering for ->d_iput()/->d_release()
vs. __dentry_kill() of the parent, no exceptions. Moreover, the current
rules for shrink lists (one must make sure that shrink_dcache_for_umount()
won't happen while any dentries from the superblock in question are on
any shrink lists) are gone - shrink_dcache_for_umount() will do the
right thing in all cases, taking such dentries out. Their empty
husks (memory occupied by struct dentry itself + its external name,
if any) will remain on the shrink lists, but they are no obstacles
to filesystem shutdown. And such husks will get freed as soon as
shrink_dentry_list() of the list they are on gets to them.
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-11-07 21:14:08 +00:00
|
|
|
if (!dentry)
|
|
|
|
return;
|
|
|
|
might_sleep();
|
|
|
|
rcu_read_lock();
|
|
|
|
if (likely(fast_dput(dentry))) {
|
2015-01-09 23:19:03 +00:00
|
|
|
rcu_read_unlock();
|
__dentry_kill(): new locking scheme
Currently we enter __dentry_kill() with parent (along with the victim
dentry and victim's inode) held locked. Then we
mark dentry refcount as dead
call ->d_prune()
remove dentry from hash
remove it from the parent's list of children
unlock the parent, don't need it from that point on
detach dentry from inode, unlock dentry and drop the inode
(via ->d_iput())
call ->d_release()
regain the lock on dentry
check if it's on a shrink list (in which case freeing its empty husk
has to be left to shrink_dentry_list()) or not (in which case we can free it
ourselves). In the former case, mark it as an empty husk, so that
shrink_dentry_list() would know it can free the sucker.
drop the lock on dentry
... and usually the caller proceeds to drop a reference on the parent,
possibly retaking the lock on it.
That is painful for a bunch of reasons, starting with the need to take locks
out of order, but not limited to that - the parent of positive dentry can
change if we drop its ->d_lock, so getting these locks has to be done with
care. Moreover, as soon as dentry is out of the parent's list of children,
shrink_dcache_for_umount() won't see it anymore, making it appear as if
the parent is inexplicably busy. We do work around that by having
shrink_dentry_list() decrement the parent's refcount first and put it on
shrink list to be evicted once we are done with __dentry_kill() of child,
but that may in some cases lead to ->d_iput() on child called after the
parent got killed. That doesn't happen in cases where in-tree ->d_iput()
instances might want to look at the parent, but that's brittle as hell.
Solution: do removal from the parent's list of children in the very
end of __dentry_kill(). As the result, the callers do not need to
lock the parent and by the time we really need the parent locked,
dentry is negative and is guaranteed not to be moved around.
It does mean that ->d_prune() will be called with parent not locked.
It also means that we might see dentries in process of being torn
down while going through the parent's list of children; those dentries
will be unhashed, negative and with refcount marked dead. In practice,
that's enough for in-tree code that looks through the list of children
to do the right thing as-is. Out-of-tree code might need to be adjusted.
Calling conventions: __dentry_kill(dentry) is called with dentry->d_lock
held, along with ->i_lock of its inode (if any). It either returns
the parent (locked, with refcount decremented to 0) or NULL (if there'd
been no parent or if refcount decrement for parent hadn't reached 0).
lock_for_kill() is adjusted for new requirements - it doesn't touch
the parent's ->d_lock at all.
Callers adjusted. Note that for dput() we don't need to bother with
fast_dput() for the parent - we just need to check retain_dentry()
for it, since its ->d_lock is still held since the moment when
__dentry_kill() had taken it to remove the victim from the list of
children.
The kludge with early decrement of parent's refcount in
shrink_dentry_list() is no longer needed - shrink_dcache_for_umount()
sees the half-killed dentries in the list of children for as long
as they are pinning the parent. They are easily recognized and
accounted for by select_collect(), so we know we are not done yet.
As the result, we always have the expected ordering for ->d_iput()/->d_release()
vs. __dentry_kill() of the parent, no exceptions. Moreover, the current
rules for shrink lists (one must make sure that shrink_dcache_for_umount()
won't happen while any dentries from the superblock in question are on
any shrink lists) are gone - shrink_dcache_for_umount() will do the
right thing in all cases, taking such dentries out. Their empty
husks (memory occupied by struct dentry itself + its external name,
if any) will remain on the shrink lists, but they are no obstacles
to filesystem shutdown. And such husks will get freed as soon as
shrink_dentry_list() of the list they are on gets to them.
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-11-07 21:14:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
while (lock_for_kill(dentry)) {
|
|
|
|
rcu_read_unlock();
|
|
|
|
dentry = __dentry_kill(dentry);
|
|
|
|
if (!dentry)
|
2018-04-15 22:31:03 +00:00
|
|
|
return;
|
2023-11-23 22:33:21 +00:00
|
|
|
if (retain_dentry(dentry, true)) {
|
2018-04-15 22:31:03 +00:00
|
|
|
spin_unlock(&dentry->d_lock);
|
|
|
|
return;
|
|
|
|
}
|
__dentry_kill(): new locking scheme
Currently we enter __dentry_kill() with parent (along with the victim
dentry and victim's inode) held locked. Then we
mark dentry refcount as dead
call ->d_prune()
remove dentry from hash
remove it from the parent's list of children
unlock the parent, don't need it from that point on
detach dentry from inode, unlock dentry and drop the inode
(via ->d_iput())
call ->d_release()
regain the lock on dentry
check if it's on a shrink list (in which case freeing its empty husk
has to be left to shrink_dentry_list()) or not (in which case we can free it
ourselves). In the former case, mark it as an empty husk, so that
shrink_dentry_list() would know it can free the sucker.
drop the lock on dentry
... and usually the caller proceeds to drop a reference on the parent,
possibly retaking the lock on it.
That is painful for a bunch of reasons, starting with the need to take locks
out of order, but not limited to that - the parent of positive dentry can
change if we drop its ->d_lock, so getting these locks has to be done with
care. Moreover, as soon as dentry is out of the parent's list of children,
shrink_dcache_for_umount() won't see it anymore, making it appear as if
the parent is inexplicably busy. We do work around that by having
shrink_dentry_list() decrement the parent's refcount first and put it on
shrink list to be evicted once we are done with __dentry_kill() of child,
but that may in some cases lead to ->d_iput() on child called after the
parent got killed. That doesn't happen in cases where in-tree ->d_iput()
instances might want to look at the parent, but that's brittle as hell.
Solution: do removal from the parent's list of children in the very
end of __dentry_kill(). As the result, the callers do not need to
lock the parent and by the time we really need the parent locked,
dentry is negative and is guaranteed not to be moved around.
It does mean that ->d_prune() will be called with parent not locked.
It also means that we might see dentries in process of being torn
down while going through the parent's list of children; those dentries
will be unhashed, negative and with refcount marked dead. In practice,
that's enough for in-tree code that looks through the list of children
to do the right thing as-is. Out-of-tree code might need to be adjusted.
Calling conventions: __dentry_kill(dentry) is called with dentry->d_lock
held, along with ->i_lock of its inode (if any). It either returns
the parent (locked, with refcount decremented to 0) or NULL (if there'd
been no parent or if refcount decrement for parent hadn't reached 0).
lock_for_kill() is adjusted for new requirements - it doesn't touch
the parent's ->d_lock at all.
Callers adjusted. Note that for dput() we don't need to bother with
fast_dput() for the parent - we just need to check retain_dentry()
for it, since its ->d_lock is still held since the moment when
__dentry_kill() had taken it to remove the victim from the list of
children.
The kludge with early decrement of parent's refcount in
shrink_dentry_list() is no longer needed - shrink_dcache_for_umount()
sees the half-killed dentries in the list of children for as long
as they are pinning the parent. They are easily recognized and
accounted for by select_collect(), so we know we are not done yet.
As the result, we always have the expected ordering for ->d_iput()/->d_release()
vs. __dentry_kill() of the parent, no exceptions. Moreover, the current
rules for shrink lists (one must make sure that shrink_dcache_for_umount()
won't happen while any dentries from the superblock in question are on
any shrink lists) are gone - shrink_dcache_for_umount() will do the
right thing in all cases, taking such dentries out. Their empty
husks (memory occupied by struct dentry itself + its external name,
if any) will remain on the shrink lists, but they are no obstacles
to filesystem shutdown. And such husks will get freed as soon as
shrink_dentry_list() of the list they are on gets to them.
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-11-07 21:14:08 +00:00
|
|
|
rcu_read_lock();
|
2016-07-06 03:32:20 +00:00
|
|
|
}
|
__dentry_kill(): new locking scheme
Currently we enter __dentry_kill() with parent (along with the victim
dentry and victim's inode) held locked. Then we
mark dentry refcount as dead
call ->d_prune()
remove dentry from hash
remove it from the parent's list of children
unlock the parent, don't need it from that point on
detach dentry from inode, unlock dentry and drop the inode
(via ->d_iput())
call ->d_release()
regain the lock on dentry
check if it's on a shrink list (in which case freeing its empty husk
has to be left to shrink_dentry_list()) or not (in which case we can free it
ourselves). In the former case, mark it as an empty husk, so that
shrink_dentry_list() would know it can free the sucker.
drop the lock on dentry
... and usually the caller proceeds to drop a reference on the parent,
possibly retaking the lock on it.
That is painful for a bunch of reasons, starting with the need to take locks
out of order, but not limited to that - the parent of positive dentry can
change if we drop its ->d_lock, so getting these locks has to be done with
care. Moreover, as soon as dentry is out of the parent's list of children,
shrink_dcache_for_umount() won't see it anymore, making it appear as if
the parent is inexplicably busy. We do work around that by having
shrink_dentry_list() decrement the parent's refcount first and put it on
shrink list to be evicted once we are done with __dentry_kill() of child,
but that may in some cases lead to ->d_iput() on child called after the
parent got killed. That doesn't happen in cases where in-tree ->d_iput()
instances might want to look at the parent, but that's brittle as hell.
Solution: do removal from the parent's list of children in the very
end of __dentry_kill(). As the result, the callers do not need to
lock the parent and by the time we really need the parent locked,
dentry is negative and is guaranteed not to be moved around.
It does mean that ->d_prune() will be called with parent not locked.
It also means that we might see dentries in process of being torn
down while going through the parent's list of children; those dentries
will be unhashed, negative and with refcount marked dead. In practice,
that's enough for in-tree code that looks through the list of children
to do the right thing as-is. Out-of-tree code might need to be adjusted.
Calling conventions: __dentry_kill(dentry) is called with dentry->d_lock
held, along with ->i_lock of its inode (if any). It either returns
the parent (locked, with refcount decremented to 0) or NULL (if there'd
been no parent or if refcount decrement for parent hadn't reached 0).
lock_for_kill() is adjusted for new requirements - it doesn't touch
the parent's ->d_lock at all.
Callers adjusted. Note that for dput() we don't need to bother with
fast_dput() for the parent - we just need to check retain_dentry()
for it, since its ->d_lock is still held since the moment when
__dentry_kill() had taken it to remove the victim from the list of
children.
The kludge with early decrement of parent's refcount in
shrink_dentry_list() is no longer needed - shrink_dcache_for_umount()
sees the half-killed dentries in the list of children for as long
as they are pinning the parent. They are easily recognized and
accounted for by select_collect(), so we know we are not done yet.
As the result, we always have the expected ordering for ->d_iput()/->d_release()
vs. __dentry_kill() of the parent, no exceptions. Moreover, the current
rules for shrink lists (one must make sure that shrink_dcache_for_umount()
won't happen while any dentries from the superblock in question are on
any shrink lists) are gone - shrink_dcache_for_umount() will do the
right thing in all cases, taking such dentries out. Their empty
husks (memory occupied by struct dentry itself + its external name,
if any) will remain on the shrink lists, but they are no obstacles
to filesystem shutdown. And such husks will get freed as soon as
shrink_dentry_list() of the list they are on gets to them.
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-11-07 21:14:08 +00:00
|
|
|
rcu_read_unlock();
|
|
|
|
spin_unlock(&dentry->d_lock);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2010-01-05 20:45:18 +00:00
|
|
|
EXPORT_SYMBOL(dput);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2023-10-30 04:43:48 +00:00
|
|
|
static void to_shrink_list(struct dentry *dentry, struct list_head *list)
|
Teach shrink_dcache_parent() to cope with mixed-filesystem shrink lists
Currently, running into a shrink list that contains dentries from different
filesystems can cause several unpleasant things for shrink_dcache_parent()
and for umount(2).
The first problem is that there's a window during shrink_dentry_list() between
__dentry_kill() takes a victim out and dropping reference to its parent. During
that window the parent looks like a genuine busy dentry. shrink_dcache_parent()
(or, worse yet, shrink_dcache_for_umount()) coming at that time will see no
eviction candidates and no indication that it needs to wait for some
shrink_dentry_list() to proceed further.
That applies for any shrink list that might intersect with the subtree we are
trying to shrink; the only reason it does not blow on umount(2) in the mainline
is that we unregister the memory shrinker before hitting shrink_dcache_for_umount().
Another problem happens if something in a mixed-filesystem shrink list gets
be stuck in e.g. iput(), getting umount of unrelated fs to spin waiting for
the stuck shrinker to get around to our dentries.
Solution:
1) have shrink_dentry_list() decrement the parent's refcount and
make sure it's on a shrink list (ours unless it already had been on some
other) before calling __dentry_kill(). That eliminates the window when
shrink_dcache_parent() would've blown past the entire subtree without
noticing anything with zero refcount not on shrink lists.
2) when shrink_dcache_parent() has found no eviction candidates,
but some dentries are still sitting on shrink lists, rather than
repeating the scan in hope that shrinkers have progressed, scan looking
for something on shrink lists with zero refcount. If such a thing is
found, grab rcu_read_lock() and stop the scan, with caller locking
it for eviction, dropping out of RCU and doing __dentry_kill(), with
the same treatment for parent as shrink_dentry_list() would do.
Note that right now mixed-filesystem shrink lists do not occur, so this
is not a mainline bug. Howevere, there's a bunch of uses for such
beasts (e.g. the "try and evict everything we can out of given page"
patches; there are potential uses in mount-related code, considerably
simplifying the life in fs/namespace.c, etc.)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2019-06-29 22:31:24 +00:00
|
|
|
__must_hold(&dentry->d_lock)
|
|
|
|
{
|
2023-10-30 04:43:48 +00:00
|
|
|
if (!(dentry->d_flags & DCACHE_SHRINK_LIST)) {
|
Teach shrink_dcache_parent() to cope with mixed-filesystem shrink lists
Currently, running into a shrink list that contains dentries from different
filesystems can cause several unpleasant things for shrink_dcache_parent()
and for umount(2).
The first problem is that there's a window during shrink_dentry_list() between
__dentry_kill() takes a victim out and dropping reference to its parent. During
that window the parent looks like a genuine busy dentry. shrink_dcache_parent()
(or, worse yet, shrink_dcache_for_umount()) coming at that time will see no
eviction candidates and no indication that it needs to wait for some
shrink_dentry_list() to proceed further.
That applies for any shrink list that might intersect with the subtree we are
trying to shrink; the only reason it does not blow on umount(2) in the mainline
is that we unregister the memory shrinker before hitting shrink_dcache_for_umount().
Another problem happens if something in a mixed-filesystem shrink list gets
be stuck in e.g. iput(), getting umount of unrelated fs to spin waiting for
the stuck shrinker to get around to our dentries.
Solution:
1) have shrink_dentry_list() decrement the parent's refcount and
make sure it's on a shrink list (ours unless it already had been on some
other) before calling __dentry_kill(). That eliminates the window when
shrink_dcache_parent() would've blown past the entire subtree without
noticing anything with zero refcount not on shrink lists.
2) when shrink_dcache_parent() has found no eviction candidates,
but some dentries are still sitting on shrink lists, rather than
repeating the scan in hope that shrinkers have progressed, scan looking
for something on shrink lists with zero refcount. If such a thing is
found, grab rcu_read_lock() and stop the scan, with caller locking
it for eviction, dropping out of RCU and doing __dentry_kill(), with
the same treatment for parent as shrink_dentry_list() would do.
Note that right now mixed-filesystem shrink lists do not occur, so this
is not a mainline bug. Howevere, there's a bunch of uses for such
beasts (e.g. the "try and evict everything we can out of given page"
patches; there are potential uses in mount-related code, considerably
simplifying the life in fs/namespace.c, etc.)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2019-06-29 22:31:24 +00:00
|
|
|
if (dentry->d_flags & DCACHE_LRU_LIST)
|
|
|
|
d_lru_del(dentry);
|
2023-10-30 05:06:06 +00:00
|
|
|
d_shrink_add(dentry, list);
|
Teach shrink_dcache_parent() to cope with mixed-filesystem shrink lists
Currently, running into a shrink list that contains dentries from different
filesystems can cause several unpleasant things for shrink_dcache_parent()
and for umount(2).
The first problem is that there's a window during shrink_dentry_list() between
__dentry_kill() takes a victim out and dropping reference to its parent. During
that window the parent looks like a genuine busy dentry. shrink_dcache_parent()
(or, worse yet, shrink_dcache_for_umount()) coming at that time will see no
eviction candidates and no indication that it needs to wait for some
shrink_dentry_list() to proceed further.
That applies for any shrink list that might intersect with the subtree we are
trying to shrink; the only reason it does not blow on umount(2) in the mainline
is that we unregister the memory shrinker before hitting shrink_dcache_for_umount().
Another problem happens if something in a mixed-filesystem shrink list gets
be stuck in e.g. iput(), getting umount of unrelated fs to spin waiting for
the stuck shrinker to get around to our dentries.
Solution:
1) have shrink_dentry_list() decrement the parent's refcount and
make sure it's on a shrink list (ours unless it already had been on some
other) before calling __dentry_kill(). That eliminates the window when
shrink_dcache_parent() would've blown past the entire subtree without
noticing anything with zero refcount not on shrink lists.
2) when shrink_dcache_parent() has found no eviction candidates,
but some dentries are still sitting on shrink lists, rather than
repeating the scan in hope that shrinkers have progressed, scan looking
for something on shrink lists with zero refcount. If such a thing is
found, grab rcu_read_lock() and stop the scan, with caller locking
it for eviction, dropping out of RCU and doing __dentry_kill(), with
the same treatment for parent as shrink_dentry_list() would do.
Note that right now mixed-filesystem shrink lists do not occur, so this
is not a mainline bug. Howevere, there's a bunch of uses for such
beasts (e.g. the "try and evict everything we can out of given page"
patches; there are potential uses in mount-related code, considerably
simplifying the life in fs/namespace.c, etc.)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2019-06-29 22:31:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void dput_to_list(struct dentry *dentry, struct list_head *list)
|
|
|
|
{
|
|
|
|
rcu_read_lock();
|
|
|
|
if (likely(fast_dput(dentry))) {
|
|
|
|
rcu_read_unlock();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
rcu_read_unlock();
|
2023-10-31 04:45:40 +00:00
|
|
|
to_shrink_list(dentry, list);
|
Teach shrink_dcache_parent() to cope with mixed-filesystem shrink lists
Currently, running into a shrink list that contains dentries from different
filesystems can cause several unpleasant things for shrink_dcache_parent()
and for umount(2).
The first problem is that there's a window during shrink_dentry_list() between
__dentry_kill() takes a victim out and dropping reference to its parent. During
that window the parent looks like a genuine busy dentry. shrink_dcache_parent()
(or, worse yet, shrink_dcache_for_umount()) coming at that time will see no
eviction candidates and no indication that it needs to wait for some
shrink_dentry_list() to proceed further.
That applies for any shrink list that might intersect with the subtree we are
trying to shrink; the only reason it does not blow on umount(2) in the mainline
is that we unregister the memory shrinker before hitting shrink_dcache_for_umount().
Another problem happens if something in a mixed-filesystem shrink list gets
be stuck in e.g. iput(), getting umount of unrelated fs to spin waiting for
the stuck shrinker to get around to our dentries.
Solution:
1) have shrink_dentry_list() decrement the parent's refcount and
make sure it's on a shrink list (ours unless it already had been on some
other) before calling __dentry_kill(). That eliminates the window when
shrink_dcache_parent() would've blown past the entire subtree without
noticing anything with zero refcount not on shrink lists.
2) when shrink_dcache_parent() has found no eviction candidates,
but some dentries are still sitting on shrink lists, rather than
repeating the scan in hope that shrinkers have progressed, scan looking
for something on shrink lists with zero refcount. If such a thing is
found, grab rcu_read_lock() and stop the scan, with caller locking
it for eviction, dropping out of RCU and doing __dentry_kill(), with
the same treatment for parent as shrink_dentry_list() would do.
Note that right now mixed-filesystem shrink lists do not occur, so this
is not a mainline bug. Howevere, there's a bunch of uses for such
beasts (e.g. the "try and evict everything we can out of given page"
patches; there are potential uses in mount-related code, considerably
simplifying the life in fs/namespace.c, etc.)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2019-06-29 22:31:24 +00:00
|
|
|
spin_unlock(&dentry->d_lock);
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2011-01-07 06:49:32 +00:00
|
|
|
struct dentry *dget_parent(struct dentry *dentry)
|
|
|
|
{
|
2013-09-02 18:29:22 +00:00
|
|
|
int gotref;
|
2011-01-07 06:49:32 +00:00
|
|
|
struct dentry *ret;
|
2019-10-31 05:43:31 +00:00
|
|
|
unsigned seq;
|
2011-01-07 06:49:32 +00:00
|
|
|
|
2013-09-02 18:29:22 +00:00
|
|
|
/*
|
|
|
|
* Do optimistic parent lookup without any
|
|
|
|
* locking.
|
|
|
|
*/
|
|
|
|
rcu_read_lock();
|
2019-10-31 05:43:31 +00:00
|
|
|
seq = raw_seqcount_begin(&dentry->d_seq);
|
locking/atomics, fs/dcache: Convert ACCESS_ONCE() to READ_ONCE()/WRITE_ONCE()
For several reasons, it is desirable to use {READ,WRITE}_ONCE() in
preference to ACCESS_ONCE(), and new code is expected to use one of the
former. So far, there's been no reason to change most existing uses of
ACCESS_ONCE(), as these aren't currently harmful.
However, for some features it is necessary to instrument reads and
writes separately, which is not possible with ACCESS_ONCE(). This
distinction is critical to correct operation.
It's possible to transform the bulk of kernel code using the Coccinelle
script below. However, this doesn't handle comments, leaving references
to ACCESS_ONCE() instances which have been removed. As a preparatory
step, this patch converts the dcache code and comments to use
{READ,WRITE}_ONCE() consistently.
----
virtual patch
@ depends on patch @
expression E1, E2;
@@
- ACCESS_ONCE(E1) = E2
+ WRITE_ONCE(E1, E2)
@ depends on patch @
expression E;
@@
- ACCESS_ONCE(E)
+ READ_ONCE(E)
----
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: davem@davemloft.net
Cc: linux-arch@vger.kernel.org
Cc: mpe@ellerman.id.au
Cc: shuah@kernel.org
Cc: snitzer@redhat.com
Cc: thor.thayer@linux.intel.com
Cc: tj@kernel.org
Cc: will.deacon@arm.com
Link: http://lkml.kernel.org/r/1508792849-3115-4-git-send-email-paulmck@linux.vnet.ibm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2017-10-23 21:07:14 +00:00
|
|
|
ret = READ_ONCE(dentry->d_parent);
|
2013-09-02 18:29:22 +00:00
|
|
|
gotref = lockref_get_not_zero(&ret->d_lockref);
|
|
|
|
rcu_read_unlock();
|
|
|
|
if (likely(gotref)) {
|
2019-10-31 05:43:31 +00:00
|
|
|
if (!read_seqcount_retry(&dentry->d_seq, seq))
|
2013-09-02 18:29:22 +00:00
|
|
|
return ret;
|
|
|
|
dput(ret);
|
|
|
|
}
|
|
|
|
|
2011-01-07 06:49:32 +00:00
|
|
|
repeat:
|
2011-01-07 06:49:44 +00:00
|
|
|
/*
|
|
|
|
* Don't need rcu_dereference because we re-check it was correct under
|
|
|
|
* the lock.
|
|
|
|
*/
|
|
|
|
rcu_read_lock();
|
2011-01-07 06:49:32 +00:00
|
|
|
ret = dentry->d_parent;
|
2011-01-07 06:49:44 +00:00
|
|
|
spin_lock(&ret->d_lock);
|
|
|
|
if (unlikely(ret != dentry->d_parent)) {
|
|
|
|
spin_unlock(&ret->d_lock);
|
|
|
|
rcu_read_unlock();
|
2011-01-07 06:49:32 +00:00
|
|
|
goto repeat;
|
|
|
|
}
|
2011-01-07 06:49:44 +00:00
|
|
|
rcu_read_unlock();
|
2013-08-29 01:24:59 +00:00
|
|
|
BUG_ON(!ret->d_lockref.count);
|
|
|
|
ret->d_lockref.count++;
|
2011-01-07 06:49:32 +00:00
|
|
|
spin_unlock(&ret->d_lock);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(dget_parent);
|
|
|
|
|
2018-04-25 14:52:25 +00:00
|
|
|
static struct dentry * __d_find_any_alias(struct inode *inode)
|
|
|
|
{
|
|
|
|
struct dentry *alias;
|
|
|
|
|
|
|
|
if (hlist_empty(&inode->i_dentry))
|
|
|
|
return NULL;
|
|
|
|
alias = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias);
|
2023-10-29 17:41:06 +00:00
|
|
|
lockref_get(&alias->d_lockref);
|
2018-04-25 14:52:25 +00:00
|
|
|
return alias;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* d_find_any_alias - find any alias for a given inode
|
|
|
|
* @inode: inode to find an alias for
|
|
|
|
*
|
|
|
|
* If any aliases exist for the given inode, take and return a
|
|
|
|
* reference for one of them. If no aliases exist, return %NULL.
|
|
|
|
*/
|
|
|
|
struct dentry *d_find_any_alias(struct inode *inode)
|
|
|
|
{
|
|
|
|
struct dentry *de;
|
|
|
|
|
|
|
|
spin_lock(&inode->i_lock);
|
|
|
|
de = __d_find_any_alias(inode);
|
|
|
|
spin_unlock(&inode->i_lock);
|
|
|
|
return de;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(d_find_any_alias);
|
|
|
|
|
2014-01-16 16:15:51 +00:00
|
|
|
static struct dentry *__d_find_alias(struct inode *inode)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2018-04-25 14:52:25 +00:00
|
|
|
struct dentry *alias;
|
|
|
|
|
|
|
|
if (S_ISDIR(inode->i_mode))
|
|
|
|
return __d_find_any_alias(inode);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2014-10-26 23:19:16 +00:00
|
|
|
hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
|
2011-01-07 06:49:33 +00:00
|
|
|
spin_lock(&alias->d_lock);
|
2018-04-25 14:52:25 +00:00
|
|
|
if (!d_unhashed(alias)) {
|
2023-11-06 13:44:17 +00:00
|
|
|
dget_dlock(alias);
|
2014-01-16 22:17:31 +00:00
|
|
|
spin_unlock(&alias->d_lock);
|
|
|
|
return alias;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2011-01-07 06:49:33 +00:00
|
|
|
spin_unlock(&alias->d_lock);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2011-01-07 06:49:33 +00:00
|
|
|
return NULL;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2021-01-14 08:04:39 +00:00
|
|
|
/**
|
|
|
|
* d_find_alias - grab a hashed alias of inode
|
|
|
|
* @inode: inode in question
|
|
|
|
*
|
|
|
|
* If inode has a hashed alias, or is a directory and has any alias,
|
|
|
|
* acquire the reference to alias and return it. Otherwise return NULL.
|
|
|
|
* Notice that if inode is a directory there can be only one alias and
|
|
|
|
* it can be unhashed only if it has no children, or if it is the root
|
|
|
|
* of a filesystem, or if the directory was renamed and d_revalidate
|
|
|
|
* was the first vfs operation to notice.
|
|
|
|
*
|
|
|
|
* If the inode has an IS_ROOT, DCACHE_DISCONNECTED alias, then prefer
|
|
|
|
* any other hashed alias over that one.
|
|
|
|
*/
|
2011-01-07 06:49:33 +00:00
|
|
|
struct dentry *d_find_alias(struct inode *inode)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2006-03-25 11:06:36 +00:00
|
|
|
struct dentry *de = NULL;
|
|
|
|
|
2012-06-09 17:51:19 +00:00
|
|
|
if (!hlist_empty(&inode->i_dentry)) {
|
2011-01-07 06:50:06 +00:00
|
|
|
spin_lock(&inode->i_lock);
|
2014-01-16 16:15:51 +00:00
|
|
|
de = __d_find_alias(inode);
|
2011-01-07 06:50:06 +00:00
|
|
|
spin_unlock(&inode->i_lock);
|
2006-03-25 11:06:36 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
return de;
|
|
|
|
}
|
2010-01-05 20:45:18 +00:00
|
|
|
EXPORT_SYMBOL(d_find_alias);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2021-01-05 19:13:52 +00:00
|
|
|
/*
|
|
|
|
* Caller MUST be holding rcu_read_lock() and be guaranteed
|
|
|
|
* that inode won't get freed until rcu_read_unlock().
|
|
|
|
*/
|
|
|
|
struct dentry *d_find_alias_rcu(struct inode *inode)
|
|
|
|
{
|
|
|
|
struct hlist_head *l = &inode->i_dentry;
|
|
|
|
struct dentry *de = NULL;
|
|
|
|
|
|
|
|
spin_lock(&inode->i_lock);
|
|
|
|
// ->i_dentry and ->i_rcu are colocated, but the latter won't be
|
|
|
|
// used without having I_FREEING set, which means no aliases left
|
|
|
|
if (likely(!(inode->i_state & I_FREEING) && !hlist_empty(l))) {
|
|
|
|
if (S_ISDIR(inode->i_mode)) {
|
|
|
|
de = hlist_entry(l->first, struct dentry, d_u.d_alias);
|
|
|
|
} else {
|
|
|
|
hlist_for_each_entry(de, l, d_u.d_alias)
|
|
|
|
if (!d_unhashed(de))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
spin_unlock(&inode->i_lock);
|
|
|
|
return de;
|
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* Try to kill dentries associated with this inode.
|
|
|
|
* WARNING: you must own a reference to inode.
|
|
|
|
*/
|
|
|
|
void d_prune_aliases(struct inode *inode)
|
|
|
|
{
|
2023-11-03 18:46:14 +00:00
|
|
|
LIST_HEAD(dispose);
|
2005-09-10 07:27:07 +00:00
|
|
|
struct dentry *dentry;
|
2023-11-03 18:46:14 +00:00
|
|
|
|
2011-01-07 06:50:06 +00:00
|
|
|
spin_lock(&inode->i_lock);
|
2014-10-26 23:19:16 +00:00
|
|
|
hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
|
2005-04-16 22:20:36 +00:00
|
|
|
spin_lock(&dentry->d_lock);
|
2023-11-03 18:46:14 +00:00
|
|
|
if (!dentry->d_lockref.count)
|
|
|
|
to_shrink_list(dentry, &dispose);
|
2005-04-16 22:20:36 +00:00
|
|
|
spin_unlock(&dentry->d_lock);
|
|
|
|
}
|
2011-01-07 06:50:06 +00:00
|
|
|
spin_unlock(&inode->i_lock);
|
2023-11-03 18:46:14 +00:00
|
|
|
shrink_dentry_list(&dispose);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2010-01-05 20:45:18 +00:00
|
|
|
EXPORT_SYMBOL(d_prune_aliases);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
__dentry_kill(): new locking scheme
Currently we enter __dentry_kill() with parent (along with the victim
dentry and victim's inode) held locked. Then we
mark dentry refcount as dead
call ->d_prune()
remove dentry from hash
remove it from the parent's list of children
unlock the parent, don't need it from that point on
detach dentry from inode, unlock dentry and drop the inode
(via ->d_iput())
call ->d_release()
regain the lock on dentry
check if it's on a shrink list (in which case freeing its empty husk
has to be left to shrink_dentry_list()) or not (in which case we can free it
ourselves). In the former case, mark it as an empty husk, so that
shrink_dentry_list() would know it can free the sucker.
drop the lock on dentry
... and usually the caller proceeds to drop a reference on the parent,
possibly retaking the lock on it.
That is painful for a bunch of reasons, starting with the need to take locks
out of order, but not limited to that - the parent of positive dentry can
change if we drop its ->d_lock, so getting these locks has to be done with
care. Moreover, as soon as dentry is out of the parent's list of children,
shrink_dcache_for_umount() won't see it anymore, making it appear as if
the parent is inexplicably busy. We do work around that by having
shrink_dentry_list() decrement the parent's refcount first and put it on
shrink list to be evicted once we are done with __dentry_kill() of child,
but that may in some cases lead to ->d_iput() on child called after the
parent got killed. That doesn't happen in cases where in-tree ->d_iput()
instances might want to look at the parent, but that's brittle as hell.
Solution: do removal from the parent's list of children in the very
end of __dentry_kill(). As the result, the callers do not need to
lock the parent and by the time we really need the parent locked,
dentry is negative and is guaranteed not to be moved around.
It does mean that ->d_prune() will be called with parent not locked.
It also means that we might see dentries in process of being torn
down while going through the parent's list of children; those dentries
will be unhashed, negative and with refcount marked dead. In practice,
that's enough for in-tree code that looks through the list of children
to do the right thing as-is. Out-of-tree code might need to be adjusted.
Calling conventions: __dentry_kill(dentry) is called with dentry->d_lock
held, along with ->i_lock of its inode (if any). It either returns
the parent (locked, with refcount decremented to 0) or NULL (if there'd
been no parent or if refcount decrement for parent hadn't reached 0).
lock_for_kill() is adjusted for new requirements - it doesn't touch
the parent's ->d_lock at all.
Callers adjusted. Note that for dput() we don't need to bother with
fast_dput() for the parent - we just need to check retain_dentry()
for it, since its ->d_lock is still held since the moment when
__dentry_kill() had taken it to remove the victim from the list of
children.
The kludge with early decrement of parent's refcount in
shrink_dentry_list() is no longer needed - shrink_dcache_for_umount()
sees the half-killed dentries in the list of children for as long
as they are pinning the parent. They are easily recognized and
accounted for by select_collect(), so we know we are not done yet.
As the result, we always have the expected ordering for ->d_iput()/->d_release()
vs. __dentry_kill() of the parent, no exceptions. Moreover, the current
rules for shrink lists (one must make sure that shrink_dcache_for_umount()
won't happen while any dentries from the superblock in question are on
any shrink lists) are gone - shrink_dcache_for_umount() will do the
right thing in all cases, taking such dentries out. Their empty
husks (memory occupied by struct dentry itself + its external name,
if any) will remain on the shrink lists, but they are no obstacles
to filesystem shutdown. And such husks will get freed as soon as
shrink_dentry_list() of the list they are on gets to them.
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-11-07 21:14:08 +00:00
|
|
|
static inline void shrink_kill(struct dentry *victim)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
__dentry_kill(): new locking scheme
Currently we enter __dentry_kill() with parent (along with the victim
dentry and victim's inode) held locked. Then we
mark dentry refcount as dead
call ->d_prune()
remove dentry from hash
remove it from the parent's list of children
unlock the parent, don't need it from that point on
detach dentry from inode, unlock dentry and drop the inode
(via ->d_iput())
call ->d_release()
regain the lock on dentry
check if it's on a shrink list (in which case freeing its empty husk
has to be left to shrink_dentry_list()) or not (in which case we can free it
ourselves). In the former case, mark it as an empty husk, so that
shrink_dentry_list() would know it can free the sucker.
drop the lock on dentry
... and usually the caller proceeds to drop a reference on the parent,
possibly retaking the lock on it.
That is painful for a bunch of reasons, starting with the need to take locks
out of order, but not limited to that - the parent of positive dentry can
change if we drop its ->d_lock, so getting these locks has to be done with
care. Moreover, as soon as dentry is out of the parent's list of children,
shrink_dcache_for_umount() won't see it anymore, making it appear as if
the parent is inexplicably busy. We do work around that by having
shrink_dentry_list() decrement the parent's refcount first and put it on
shrink list to be evicted once we are done with __dentry_kill() of child,
but that may in some cases lead to ->d_iput() on child called after the
parent got killed. That doesn't happen in cases where in-tree ->d_iput()
instances might want to look at the parent, but that's brittle as hell.
Solution: do removal from the parent's list of children in the very
end of __dentry_kill(). As the result, the callers do not need to
lock the parent and by the time we really need the parent locked,
dentry is negative and is guaranteed not to be moved around.
It does mean that ->d_prune() will be called with parent not locked.
It also means that we might see dentries in process of being torn
down while going through the parent's list of children; those dentries
will be unhashed, negative and with refcount marked dead. In practice,
that's enough for in-tree code that looks through the list of children
to do the right thing as-is. Out-of-tree code might need to be adjusted.
Calling conventions: __dentry_kill(dentry) is called with dentry->d_lock
held, along with ->i_lock of its inode (if any). It either returns
the parent (locked, with refcount decremented to 0) or NULL (if there'd
been no parent or if refcount decrement for parent hadn't reached 0).
lock_for_kill() is adjusted for new requirements - it doesn't touch
the parent's ->d_lock at all.
Callers adjusted. Note that for dput() we don't need to bother with
fast_dput() for the parent - we just need to check retain_dentry()
for it, since its ->d_lock is still held since the moment when
__dentry_kill() had taken it to remove the victim from the list of
children.
The kludge with early decrement of parent's refcount in
shrink_dentry_list() is no longer needed - shrink_dcache_for_umount()
sees the half-killed dentries in the list of children for as long
as they are pinning the parent. They are easily recognized and
accounted for by select_collect(), so we know we are not done yet.
As the result, we always have the expected ordering for ->d_iput()/->d_release()
vs. __dentry_kill() of the parent, no exceptions. Moreover, the current
rules for shrink lists (one must make sure that shrink_dcache_for_umount()
won't happen while any dentries from the superblock in question are on
any shrink lists) are gone - shrink_dcache_for_umount() will do the
right thing in all cases, taking such dentries out. Their empty
husks (memory occupied by struct dentry itself + its external name,
if any) will remain on the shrink lists, but they are no obstacles
to filesystem shutdown. And such husks will get freed as soon as
shrink_dentry_list() of the list they are on gets to them.
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-11-07 21:14:08 +00:00
|
|
|
do {
|
|
|
|
rcu_read_unlock();
|
|
|
|
victim = __dentry_kill(victim);
|
|
|
|
rcu_read_lock();
|
|
|
|
} while (victim && lock_for_kill(victim));
|
|
|
|
rcu_read_unlock();
|
|
|
|
if (victim)
|
|
|
|
spin_unlock(&victim->d_lock);
|
2018-02-24 02:54:18 +00:00
|
|
|
}
|
2011-01-07 06:49:48 +00:00
|
|
|
|
Teach shrink_dcache_parent() to cope with mixed-filesystem shrink lists
Currently, running into a shrink list that contains dentries from different
filesystems can cause several unpleasant things for shrink_dcache_parent()
and for umount(2).
The first problem is that there's a window during shrink_dentry_list() between
__dentry_kill() takes a victim out and dropping reference to its parent. During
that window the parent looks like a genuine busy dentry. shrink_dcache_parent()
(or, worse yet, shrink_dcache_for_umount()) coming at that time will see no
eviction candidates and no indication that it needs to wait for some
shrink_dentry_list() to proceed further.
That applies for any shrink list that might intersect with the subtree we are
trying to shrink; the only reason it does not blow on umount(2) in the mainline
is that we unregister the memory shrinker before hitting shrink_dcache_for_umount().
Another problem happens if something in a mixed-filesystem shrink list gets
be stuck in e.g. iput(), getting umount of unrelated fs to spin waiting for
the stuck shrinker to get around to our dentries.
Solution:
1) have shrink_dentry_list() decrement the parent's refcount and
make sure it's on a shrink list (ours unless it already had been on some
other) before calling __dentry_kill(). That eliminates the window when
shrink_dcache_parent() would've blown past the entire subtree without
noticing anything with zero refcount not on shrink lists.
2) when shrink_dcache_parent() has found no eviction candidates,
but some dentries are still sitting on shrink lists, rather than
repeating the scan in hope that shrinkers have progressed, scan looking
for something on shrink lists with zero refcount. If such a thing is
found, grab rcu_read_lock() and stop the scan, with caller locking
it for eviction, dropping out of RCU and doing __dentry_kill(), with
the same treatment for parent as shrink_dentry_list() would do.
Note that right now mixed-filesystem shrink lists do not occur, so this
is not a mainline bug. Howevere, there's a bunch of uses for such
beasts (e.g. the "try and evict everything we can out of given page"
patches; there are potential uses in mount-related code, considerably
simplifying the life in fs/namespace.c, etc.)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2019-06-29 22:31:24 +00:00
|
|
|
void shrink_dentry_list(struct list_head *list)
|
2018-02-24 02:54:18 +00:00
|
|
|
{
|
|
|
|
while (!list_empty(list)) {
|
2023-11-07 20:21:33 +00:00
|
|
|
struct dentry *dentry;
|
2014-05-28 13:48:44 +00:00
|
|
|
|
2018-02-24 02:54:18 +00:00
|
|
|
dentry = list_entry(list->prev, struct dentry, d_lru);
|
|
|
|
spin_lock(&dentry->d_lock);
|
2018-02-22 23:50:24 +00:00
|
|
|
rcu_read_lock();
|
don't try to cut corners in shrink_lock_dentry()
That is to say, do *not* treat the ->d_inode or ->d_parent changes
as "it's hard, return false; somebody must have grabbed it, so
even if has zero refcount, we don't need to bother killing it -
final dput() from whoever grabbed it would've done everything".
First of all, that is not guaranteed. It might have been dropped
by shrink_kill() handling of victim's parent, which would've found
it already on a shrink list (ours) and decided that they don't need
to put it on their shrink list.
What's more, dentry_kill() is doing pretty much the same thing,
cutting its own set of corners (it assumes that dentry can't
go from positive to negative, so its inode can change but only once
and only in one direction).
Doing that right allows to get rid of that not-quite-duplication
and removes the only reason for re-incrementing refcount before
the call of dentry_kill().
Replacement is called lock_for_kill(); called under rcu_read_lock
and with ->d_lock held. If it returns false, dentry has non-zero
refcount and the same locks are held. If it returns true,
dentry has zero refcount and all locks required by __dentry_kill()
are taken.
Part of __lock_parent() had been lifted into lock_parent() to
allow its reuse. Now it's called with rcu_read_lock already
held and dentry already unlocked.
Note that this is not the final change - locking requirements for
__dentry_kill() are going to change later in the series and the
set of locks taken by lock_for_kill() will be adjusted. Both
lock_parent() and __lock_parent() will be gone once that happens.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-10-31 05:23:47 +00:00
|
|
|
if (!lock_for_kill(dentry)) {
|
2023-10-30 17:57:12 +00:00
|
|
|
bool can_free;
|
2018-02-22 23:50:24 +00:00
|
|
|
rcu_read_unlock();
|
2018-02-24 02:54:18 +00:00
|
|
|
d_shrink_del(dentry);
|
2023-11-10 19:07:43 +00:00
|
|
|
can_free = dentry->d_flags & DCACHE_DENTRY_KILLED;
|
2014-05-28 13:48:44 +00:00
|
|
|
spin_unlock(&dentry->d_lock);
|
|
|
|
if (can_free)
|
|
|
|
dentry_free(dentry);
|
|
|
|
continue;
|
|
|
|
}
|
2018-02-24 02:54:18 +00:00
|
|
|
d_shrink_del(dentry);
|
__dentry_kill(): new locking scheme
Currently we enter __dentry_kill() with parent (along with the victim
dentry and victim's inode) held locked. Then we
mark dentry refcount as dead
call ->d_prune()
remove dentry from hash
remove it from the parent's list of children
unlock the parent, don't need it from that point on
detach dentry from inode, unlock dentry and drop the inode
(via ->d_iput())
call ->d_release()
regain the lock on dentry
check if it's on a shrink list (in which case freeing its empty husk
has to be left to shrink_dentry_list()) or not (in which case we can free it
ourselves). In the former case, mark it as an empty husk, so that
shrink_dentry_list() would know it can free the sucker.
drop the lock on dentry
... and usually the caller proceeds to drop a reference on the parent,
possibly retaking the lock on it.
That is painful for a bunch of reasons, starting with the need to take locks
out of order, but not limited to that - the parent of positive dentry can
change if we drop its ->d_lock, so getting these locks has to be done with
care. Moreover, as soon as dentry is out of the parent's list of children,
shrink_dcache_for_umount() won't see it anymore, making it appear as if
the parent is inexplicably busy. We do work around that by having
shrink_dentry_list() decrement the parent's refcount first and put it on
shrink list to be evicted once we are done with __dentry_kill() of child,
but that may in some cases lead to ->d_iput() on child called after the
parent got killed. That doesn't happen in cases where in-tree ->d_iput()
instances might want to look at the parent, but that's brittle as hell.
Solution: do removal from the parent's list of children in the very
end of __dentry_kill(). As the result, the callers do not need to
lock the parent and by the time we really need the parent locked,
dentry is negative and is guaranteed not to be moved around.
It does mean that ->d_prune() will be called with parent not locked.
It also means that we might see dentries in process of being torn
down while going through the parent's list of children; those dentries
will be unhashed, negative and with refcount marked dead. In practice,
that's enough for in-tree code that looks through the list of children
to do the right thing as-is. Out-of-tree code might need to be adjusted.
Calling conventions: __dentry_kill(dentry) is called with dentry->d_lock
held, along with ->i_lock of its inode (if any). It either returns
the parent (locked, with refcount decremented to 0) or NULL (if there'd
been no parent or if refcount decrement for parent hadn't reached 0).
lock_for_kill() is adjusted for new requirements - it doesn't touch
the parent's ->d_lock at all.
Callers adjusted. Note that for dput() we don't need to bother with
fast_dput() for the parent - we just need to check retain_dentry()
for it, since its ->d_lock is still held since the moment when
__dentry_kill() had taken it to remove the victim from the list of
children.
The kludge with early decrement of parent's refcount in
shrink_dentry_list() is no longer needed - shrink_dcache_for_umount()
sees the half-killed dentries in the list of children for as long
as they are pinning the parent. They are easily recognized and
accounted for by select_collect(), so we know we are not done yet.
As the result, we always have the expected ordering for ->d_iput()/->d_release()
vs. __dentry_kill() of the parent, no exceptions. Moreover, the current
rules for shrink lists (one must make sure that shrink_dcache_for_umount()
won't happen while any dentries from the superblock in question are on
any shrink lists) are gone - shrink_dcache_for_umount() will do the
right thing in all cases, taking such dentries out. Their empty
husks (memory occupied by struct dentry itself + its external name,
if any) will remain on the shrink lists, but they are no obstacles
to filesystem shutdown. And such husks will get freed as soon as
shrink_dentry_list() of the list they are on gets to them.
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-11-07 21:14:08 +00:00
|
|
|
shrink_kill(dentry);
|
fix soft lock up at NFS mount via per-SB LRU-list of unused dentries
[Summary]
Split LRU-list of unused dentries to one per superblock to avoid soft
lock up during NFS mounts and remounting of any filesystem.
Previously I posted here:
http://lkml.org/lkml/2008/3/5/590
[Descriptions]
- background
dentry_unused is a list of dentries which are not referenced.
dentry_unused grows up when references on directories or files are
released. This list can be very long if there is huge free memory.
- the problem
When shrink_dcache_sb() is called, it scans all dentry_unused linearly
under spin_lock(), and if dentry->d_sb is differnt from given
superblock, scan next dentry. This scan costs very much if there are
many entries, and very ineffective if there are many superblocks.
IOW, When we need to shrink unused dentries on one dentry, but scans
unused dentries on all superblocks in the system. For example, we scan
500 dentries to unmount a filesystem, but scans 1,000,000 or more unused
dentries on other superblocks.
In our case , At mounting NFS*, shrink_dcache_sb() is called to shrink
unused dentries on NFS, but scans 100,000,000 unused dentries on
superblocks in the system such as local ext3 filesystems. I hear NFS
mounting took 1 min on some system in use.
* : NFS uses virtual filesystem in rpc layer, so NFS is affected by
this problem.
100,000,000 is possible number on large systems.
Per-superblock LRU of unused dentried can reduce the cost in
reasonable manner.
- How to fix
I found this problem is solved by David Chinner's "Per-superblock
unused dentry LRU lists V3"(1), so I rebase it and add some fix to
reclaim with fairness, which is in Andrew Morton's comments(2).
1) http://lkml.org/lkml/2006/5/25/318
2) http://lkml.org/lkml/2006/5/25/320
Split LRU-list of unused dentries to each superblocks. Then, NFS
mounting will check dentries under a superblock instead of all. But
this spliting will break LRU of dentry-unused. So, I've attempted to
make reclaim unused dentrins with fairness by calculate number of
dentries to scan on this sb based on following way
number of dentries to scan on this sb =
count * (number of dentries on this sb / number of dentries in the machine)
- ToDo
- I have to measuring performance number and do stress tests.
- When unmount occurs during prune_dcache(), scanning on same
superblock, It is unable to reach next superblock because it is gone
away. We restart scannig superblock from first one, it causes
unfairness of reclaim unused dentries on first superblock. But I think
this happens very rarely.
- Test Results
Result on 6GB boxes with excessive unused dentries.
Without patch:
$ cat /proc/sys/fs/dentry-state
10181835 10180203 45 0 0 0
# mount -t nfs 10.124.60.70:/work/kernel-src nfs
real 0m1.830s
user 0m0.001s
sys 0m1.653s
With this patch:
$ cat /proc/sys/fs/dentry-state
10236610 10234751 45 0 0 0
# mount -t nfs 10.124.60.70:/work/kernel-src nfs
real 0m0.106s
user 0m0.002s
sys 0m0.032s
[akpm@linux-foundation.org: fix comments]
Signed-off-by: Kentaro Makita <k-makita@np.css.fujitsu.com>
Cc: Neil Brown <neilb@suse.de>
Cc: Trond Myklebust <trond.myklebust@fys.uio.no>
Cc: David Chinner <dgc@sgi.com>
Cc: "J. Bruce Fields" <bfields@fieldses.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-07-24 04:27:13 +00:00
|
|
|
}
|
2010-10-10 09:36:25 +00:00
|
|
|
}
|
|
|
|
|
2015-02-12 22:59:35 +00:00
|
|
|
static enum lru_status dentry_lru_isolate(struct list_head *item,
|
|
|
|
struct list_lru_one *lru, spinlock_t *lru_lock, void *arg)
|
2013-08-28 00:18:00 +00:00
|
|
|
{
|
|
|
|
struct list_head *freeable = arg;
|
|
|
|
struct dentry *dentry = container_of(item, struct dentry, d_lru);
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* we are inverting the lru lock/dentry->d_lock here,
|
|
|
|
* so use a trylock. If we fail to get the lock, just skip
|
|
|
|
* it
|
|
|
|
*/
|
|
|
|
if (!spin_trylock(&dentry->d_lock))
|
|
|
|
return LRU_SKIP;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Referenced dentries are still in use. If they have active
|
|
|
|
* counts, just remove them from the LRU. Otherwise give them
|
|
|
|
* another pass through the LRU.
|
|
|
|
*/
|
|
|
|
if (dentry->d_lockref.count) {
|
2015-02-12 22:59:35 +00:00
|
|
|
d_lru_isolate(lru, dentry);
|
2013-08-28 00:18:00 +00:00
|
|
|
spin_unlock(&dentry->d_lock);
|
|
|
|
return LRU_REMOVED;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dentry->d_flags & DCACHE_REFERENCED) {
|
|
|
|
dentry->d_flags &= ~DCACHE_REFERENCED;
|
|
|
|
spin_unlock(&dentry->d_lock);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The list move itself will be made by the common LRU code. At
|
|
|
|
* this point, we've dropped the dentry->d_lock but keep the
|
|
|
|
* lru lock. This is safe to do, since every list movement is
|
|
|
|
* protected by the lru lock even if both locks are held.
|
|
|
|
*
|
|
|
|
* This is guaranteed by the fact that all LRU management
|
|
|
|
* functions are intermediated by the LRU API calls like
|
list_lru: allow explicit memcg and NUMA node selection
Patch series "workload-specific and memory pressure-driven zswap
writeback", v8.
There are currently several issues with zswap writeback:
1. There is only a single global LRU for zswap, making it impossible to
perform worload-specific shrinking - an memcg under memory pressure
cannot determine which pages in the pool it owns, and often ends up
writing pages from other memcgs. This issue has been previously
observed in practice and mitigated by simply disabling
memcg-initiated shrinking:
https://lore.kernel.org/all/20230530232435.3097106-1-nphamcs@gmail.com/T/#u
But this solution leaves a lot to be desired, as we still do not
have an avenue for an memcg to free up its own memory locked up in
the zswap pool.
2. We only shrink the zswap pool when the user-defined limit is hit.
This means that if we set the limit too high, cold data that are
unlikely to be used again will reside in the pool, wasting precious
memory. It is hard to predict how much zswap space will be needed
ahead of time, as this depends on the workload (specifically, on
factors such as memory access patterns and compressibility of the
memory pages).
This patch series solves these issues by separating the global zswap LRU
into per-memcg and per-NUMA LRUs, and performs workload-specific (i.e
memcg- and NUMA-aware) zswap writeback under memory pressure. The new
shrinker does not have any parameter that must be tuned by the user, and
can be opted in or out on a per-memcg basis.
As a proof of concept, we ran the following synthetic benchmark: build the
linux kernel in a memory-limited cgroup, and allocate some cold data in
tmpfs to see if the shrinker could write them out and improved the overall
performance. Depending on the amount of cold data generated, we observe
from 14% to 35% reduction in kernel CPU time used in the kernel builds.
This patch (of 6):
The interface of list_lru is based on the assumption that the list node
and the data it represents belong to the same allocated on the correct
node/memcg. While this assumption is valid for existing slab objects LRU
such as dentries and inodes, it is undocumented, and rather inflexible for
certain potential list_lru users (such as the upcoming zswap shrinker and
the THP shrinker). It has caused us a lot of issues during our
development.
This patch changes list_lru interface so that the caller must explicitly
specify numa node and memcg when adding and removing objects. The old
list_lru_add() and list_lru_del() are renamed to list_lru_add_obj() and
list_lru_del_obj(), respectively.
It also extends the list_lru API with a new function, list_lru_putback,
which undoes a previous list_lru_isolate call. Unlike list_lru_add, it
does not increment the LRU node count (as list_lru_isolate does not
decrement the node count). list_lru_putback also allows for explicit
memcg and NUMA node selection.
Link: https://lkml.kernel.org/r/20231130194023.4102148-1-nphamcs@gmail.com
Link: https://lkml.kernel.org/r/20231130194023.4102148-2-nphamcs@gmail.com
Signed-off-by: Nhat Pham <nphamcs@gmail.com>
Suggested-by: Johannes Weiner <hannes@cmpxchg.org>
Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Tested-by: Bagas Sanjaya <bagasdotme@gmail.com>
Cc: Chris Li <chrisl@kernel.org>
Cc: Dan Streetman <ddstreet@ieee.org>
Cc: Domenico Cerasuolo <cerasuolodomenico@gmail.com>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Seth Jennings <sjenning@redhat.com>
Cc: Shakeel Butt <shakeelb@google.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Vitaly Wool <vitaly.wool@konsulko.com>
Cc: Yosry Ahmed <yosryahmed@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
2023-11-30 19:40:18 +00:00
|
|
|
* list_lru_add_obj and list_lru_del_obj. List movement in this file
|
2013-08-28 00:18:00 +00:00
|
|
|
* only ever occur through this functions or through callbacks
|
|
|
|
* like this one, that are called from the LRU API.
|
|
|
|
*
|
|
|
|
* The only exceptions to this are functions like
|
|
|
|
* shrink_dentry_list, and code that first checks for the
|
|
|
|
* DCACHE_SHRINK_LIST flag. Those are guaranteed to be
|
|
|
|
* operating only with stack provided lists after they are
|
|
|
|
* properly isolated from the main list. It is thus, always a
|
|
|
|
* local access.
|
|
|
|
*/
|
|
|
|
return LRU_ROTATE;
|
|
|
|
}
|
|
|
|
|
2015-02-12 22:59:35 +00:00
|
|
|
d_lru_shrink_move(lru, dentry, freeable);
|
2013-08-28 00:18:00 +00:00
|
|
|
spin_unlock(&dentry->d_lock);
|
|
|
|
|
|
|
|
return LRU_REMOVED;
|
|
|
|
}
|
|
|
|
|
2010-10-10 09:36:25 +00:00
|
|
|
/**
|
2011-08-23 08:56:24 +00:00
|
|
|
* prune_dcache_sb - shrink the dcache
|
|
|
|
* @sb: superblock
|
list_lru: introduce list_lru_shrink_{count,walk}
Kmem accounting of memcg is unusable now, because it lacks slab shrinker
support. That means when we hit the limit we will get ENOMEM w/o any
chance to recover. What we should do then is to call shrink_slab, which
would reclaim old inode/dentry caches from this cgroup. This is what
this patch set is intended to do.
Basically, it does two things. First, it introduces the notion of
per-memcg slab shrinker. A shrinker that wants to reclaim objects per
cgroup should mark itself as SHRINKER_MEMCG_AWARE. Then it will be
passed the memory cgroup to scan from in shrink_control->memcg. For
such shrinkers shrink_slab iterates over the whole cgroup subtree under
the target cgroup and calls the shrinker for each kmem-active memory
cgroup.
Secondly, this patch set makes the list_lru structure per-memcg. It's
done transparently to list_lru users - everything they have to do is to
tell list_lru_init that they want memcg-aware list_lru. Then the
list_lru will automatically distribute objects among per-memcg lists
basing on which cgroup the object is accounted to. This way to make FS
shrinkers (icache, dcache) memcg-aware we only need to make them use
memcg-aware list_lru, and this is what this patch set does.
As before, this patch set only enables per-memcg kmem reclaim when the
pressure goes from memory.limit, not from memory.kmem.limit. Handling
memory.kmem.limit is going to be tricky due to GFP_NOFS allocations, and
it is still unclear whether we will have this knob in the unified
hierarchy.
This patch (of 9):
NUMA aware slab shrinkers use the list_lru structure to distribute
objects coming from different NUMA nodes to different lists. Whenever
such a shrinker needs to count or scan objects from a particular node,
it issues commands like this:
count = list_lru_count_node(lru, sc->nid);
freed = list_lru_walk_node(lru, sc->nid, isolate_func,
isolate_arg, &sc->nr_to_scan);
where sc is an instance of the shrink_control structure passed to it
from vmscan.
To simplify this, let's add special list_lru functions to be used by
shrinkers, list_lru_shrink_count() and list_lru_shrink_walk(), which
consolidate the nid and nr_to_scan arguments in the shrink_control
structure.
This will also allow us to avoid patching shrinkers that use list_lru
when we make shrink_slab() per-memcg - all we will have to do is extend
the shrink_control structure to include the target memcg and make
list_lru_shrink_{count,walk} handle this appropriately.
Signed-off-by: Vladimir Davydov <vdavydov@parallels.com>
Suggested-by: Dave Chinner <david@fromorbit.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Greg Thelen <gthelen@google.com>
Cc: Glauber Costa <glommer@gmail.com>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Christoph Lameter <cl@linux.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Tejun Heo <tj@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2015-02-12 22:58:47 +00:00
|
|
|
* @sc: shrink control, passed to list_lru_shrink_walk()
|
2011-08-23 08:56:24 +00:00
|
|
|
*
|
list_lru: introduce list_lru_shrink_{count,walk}
Kmem accounting of memcg is unusable now, because it lacks slab shrinker
support. That means when we hit the limit we will get ENOMEM w/o any
chance to recover. What we should do then is to call shrink_slab, which
would reclaim old inode/dentry caches from this cgroup. This is what
this patch set is intended to do.
Basically, it does two things. First, it introduces the notion of
per-memcg slab shrinker. A shrinker that wants to reclaim objects per
cgroup should mark itself as SHRINKER_MEMCG_AWARE. Then it will be
passed the memory cgroup to scan from in shrink_control->memcg. For
such shrinkers shrink_slab iterates over the whole cgroup subtree under
the target cgroup and calls the shrinker for each kmem-active memory
cgroup.
Secondly, this patch set makes the list_lru structure per-memcg. It's
done transparently to list_lru users - everything they have to do is to
tell list_lru_init that they want memcg-aware list_lru. Then the
list_lru will automatically distribute objects among per-memcg lists
basing on which cgroup the object is accounted to. This way to make FS
shrinkers (icache, dcache) memcg-aware we only need to make them use
memcg-aware list_lru, and this is what this patch set does.
As before, this patch set only enables per-memcg kmem reclaim when the
pressure goes from memory.limit, not from memory.kmem.limit. Handling
memory.kmem.limit is going to be tricky due to GFP_NOFS allocations, and
it is still unclear whether we will have this knob in the unified
hierarchy.
This patch (of 9):
NUMA aware slab shrinkers use the list_lru structure to distribute
objects coming from different NUMA nodes to different lists. Whenever
such a shrinker needs to count or scan objects from a particular node,
it issues commands like this:
count = list_lru_count_node(lru, sc->nid);
freed = list_lru_walk_node(lru, sc->nid, isolate_func,
isolate_arg, &sc->nr_to_scan);
where sc is an instance of the shrink_control structure passed to it
from vmscan.
To simplify this, let's add special list_lru functions to be used by
shrinkers, list_lru_shrink_count() and list_lru_shrink_walk(), which
consolidate the nid and nr_to_scan arguments in the shrink_control
structure.
This will also allow us to avoid patching shrinkers that use list_lru
when we make shrink_slab() per-memcg - all we will have to do is extend
the shrink_control structure to include the target memcg and make
list_lru_shrink_{count,walk} handle this appropriately.
Signed-off-by: Vladimir Davydov <vdavydov@parallels.com>
Suggested-by: Dave Chinner <david@fromorbit.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Greg Thelen <gthelen@google.com>
Cc: Glauber Costa <glommer@gmail.com>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Christoph Lameter <cl@linux.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Tejun Heo <tj@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2015-02-12 22:58:47 +00:00
|
|
|
* Attempt to shrink the superblock dcache LRU by @sc->nr_to_scan entries. This
|
|
|
|
* is done when we need more memory and called from the superblock shrinker
|
2011-08-23 08:56:24 +00:00
|
|
|
* function.
|
2010-10-10 09:36:25 +00:00
|
|
|
*
|
2011-08-23 08:56:24 +00:00
|
|
|
* This function may fail to free any resources if all the dentries are in
|
|
|
|
* use.
|
2010-10-10 09:36:25 +00:00
|
|
|
*/
|
list_lru: introduce list_lru_shrink_{count,walk}
Kmem accounting of memcg is unusable now, because it lacks slab shrinker
support. That means when we hit the limit we will get ENOMEM w/o any
chance to recover. What we should do then is to call shrink_slab, which
would reclaim old inode/dentry caches from this cgroup. This is what
this patch set is intended to do.
Basically, it does two things. First, it introduces the notion of
per-memcg slab shrinker. A shrinker that wants to reclaim objects per
cgroup should mark itself as SHRINKER_MEMCG_AWARE. Then it will be
passed the memory cgroup to scan from in shrink_control->memcg. For
such shrinkers shrink_slab iterates over the whole cgroup subtree under
the target cgroup and calls the shrinker for each kmem-active memory
cgroup.
Secondly, this patch set makes the list_lru structure per-memcg. It's
done transparently to list_lru users - everything they have to do is to
tell list_lru_init that they want memcg-aware list_lru. Then the
list_lru will automatically distribute objects among per-memcg lists
basing on which cgroup the object is accounted to. This way to make FS
shrinkers (icache, dcache) memcg-aware we only need to make them use
memcg-aware list_lru, and this is what this patch set does.
As before, this patch set only enables per-memcg kmem reclaim when the
pressure goes from memory.limit, not from memory.kmem.limit. Handling
memory.kmem.limit is going to be tricky due to GFP_NOFS allocations, and
it is still unclear whether we will have this knob in the unified
hierarchy.
This patch (of 9):
NUMA aware slab shrinkers use the list_lru structure to distribute
objects coming from different NUMA nodes to different lists. Whenever
such a shrinker needs to count or scan objects from a particular node,
it issues commands like this:
count = list_lru_count_node(lru, sc->nid);
freed = list_lru_walk_node(lru, sc->nid, isolate_func,
isolate_arg, &sc->nr_to_scan);
where sc is an instance of the shrink_control structure passed to it
from vmscan.
To simplify this, let's add special list_lru functions to be used by
shrinkers, list_lru_shrink_count() and list_lru_shrink_walk(), which
consolidate the nid and nr_to_scan arguments in the shrink_control
structure.
This will also allow us to avoid patching shrinkers that use list_lru
when we make shrink_slab() per-memcg - all we will have to do is extend
the shrink_control structure to include the target memcg and make
list_lru_shrink_{count,walk} handle this appropriately.
Signed-off-by: Vladimir Davydov <vdavydov@parallels.com>
Suggested-by: Dave Chinner <david@fromorbit.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Greg Thelen <gthelen@google.com>
Cc: Glauber Costa <glommer@gmail.com>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Christoph Lameter <cl@linux.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Tejun Heo <tj@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2015-02-12 22:58:47 +00:00
|
|
|
long prune_dcache_sb(struct super_block *sb, struct shrink_control *sc)
|
2010-10-10 09:36:25 +00:00
|
|
|
{
|
2013-08-28 00:18:00 +00:00
|
|
|
LIST_HEAD(dispose);
|
|
|
|
long freed;
|
2010-10-10 09:36:25 +00:00
|
|
|
|
list_lru: introduce list_lru_shrink_{count,walk}
Kmem accounting of memcg is unusable now, because it lacks slab shrinker
support. That means when we hit the limit we will get ENOMEM w/o any
chance to recover. What we should do then is to call shrink_slab, which
would reclaim old inode/dentry caches from this cgroup. This is what
this patch set is intended to do.
Basically, it does two things. First, it introduces the notion of
per-memcg slab shrinker. A shrinker that wants to reclaim objects per
cgroup should mark itself as SHRINKER_MEMCG_AWARE. Then it will be
passed the memory cgroup to scan from in shrink_control->memcg. For
such shrinkers shrink_slab iterates over the whole cgroup subtree under
the target cgroup and calls the shrinker for each kmem-active memory
cgroup.
Secondly, this patch set makes the list_lru structure per-memcg. It's
done transparently to list_lru users - everything they have to do is to
tell list_lru_init that they want memcg-aware list_lru. Then the
list_lru will automatically distribute objects among per-memcg lists
basing on which cgroup the object is accounted to. This way to make FS
shrinkers (icache, dcache) memcg-aware we only need to make them use
memcg-aware list_lru, and this is what this patch set does.
As before, this patch set only enables per-memcg kmem reclaim when the
pressure goes from memory.limit, not from memory.kmem.limit. Handling
memory.kmem.limit is going to be tricky due to GFP_NOFS allocations, and
it is still unclear whether we will have this knob in the unified
hierarchy.
This patch (of 9):
NUMA aware slab shrinkers use the list_lru structure to distribute
objects coming from different NUMA nodes to different lists. Whenever
such a shrinker needs to count or scan objects from a particular node,
it issues commands like this:
count = list_lru_count_node(lru, sc->nid);
freed = list_lru_walk_node(lru, sc->nid, isolate_func,
isolate_arg, &sc->nr_to_scan);
where sc is an instance of the shrink_control structure passed to it
from vmscan.
To simplify this, let's add special list_lru functions to be used by
shrinkers, list_lru_shrink_count() and list_lru_shrink_walk(), which
consolidate the nid and nr_to_scan arguments in the shrink_control
structure.
This will also allow us to avoid patching shrinkers that use list_lru
when we make shrink_slab() per-memcg - all we will have to do is extend
the shrink_control structure to include the target memcg and make
list_lru_shrink_{count,walk} handle this appropriately.
Signed-off-by: Vladimir Davydov <vdavydov@parallels.com>
Suggested-by: Dave Chinner <david@fromorbit.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Greg Thelen <gthelen@google.com>
Cc: Glauber Costa <glommer@gmail.com>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Christoph Lameter <cl@linux.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Tejun Heo <tj@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2015-02-12 22:58:47 +00:00
|
|
|
freed = list_lru_shrink_walk(&sb->s_dentry_lru, sc,
|
|
|
|
dentry_lru_isolate, &dispose);
|
2013-08-28 00:18:00 +00:00
|
|
|
shrink_dentry_list(&dispose);
|
2013-08-28 00:17:57 +00:00
|
|
|
return freed;
|
fix soft lock up at NFS mount via per-SB LRU-list of unused dentries
[Summary]
Split LRU-list of unused dentries to one per superblock to avoid soft
lock up during NFS mounts and remounting of any filesystem.
Previously I posted here:
http://lkml.org/lkml/2008/3/5/590
[Descriptions]
- background
dentry_unused is a list of dentries which are not referenced.
dentry_unused grows up when references on directories or files are
released. This list can be very long if there is huge free memory.
- the problem
When shrink_dcache_sb() is called, it scans all dentry_unused linearly
under spin_lock(), and if dentry->d_sb is differnt from given
superblock, scan next dentry. This scan costs very much if there are
many entries, and very ineffective if there are many superblocks.
IOW, When we need to shrink unused dentries on one dentry, but scans
unused dentries on all superblocks in the system. For example, we scan
500 dentries to unmount a filesystem, but scans 1,000,000 or more unused
dentries on other superblocks.
In our case , At mounting NFS*, shrink_dcache_sb() is called to shrink
unused dentries on NFS, but scans 100,000,000 unused dentries on
superblocks in the system such as local ext3 filesystems. I hear NFS
mounting took 1 min on some system in use.
* : NFS uses virtual filesystem in rpc layer, so NFS is affected by
this problem.
100,000,000 is possible number on large systems.
Per-superblock LRU of unused dentried can reduce the cost in
reasonable manner.
- How to fix
I found this problem is solved by David Chinner's "Per-superblock
unused dentry LRU lists V3"(1), so I rebase it and add some fix to
reclaim with fairness, which is in Andrew Morton's comments(2).
1) http://lkml.org/lkml/2006/5/25/318
2) http://lkml.org/lkml/2006/5/25/320
Split LRU-list of unused dentries to each superblocks. Then, NFS
mounting will check dentries under a superblock instead of all. But
this spliting will break LRU of dentry-unused. So, I've attempted to
make reclaim unused dentrins with fairness by calculate number of
dentries to scan on this sb based on following way
number of dentries to scan on this sb =
count * (number of dentries on this sb / number of dentries in the machine)
- ToDo
- I have to measuring performance number and do stress tests.
- When unmount occurs during prune_dcache(), scanning on same
superblock, It is unable to reach next superblock because it is gone
away. We restart scannig superblock from first one, it causes
unfairness of reclaim unused dentries on first superblock. But I think
this happens very rarely.
- Test Results
Result on 6GB boxes with excessive unused dentries.
Without patch:
$ cat /proc/sys/fs/dentry-state
10181835 10180203 45 0 0 0
# mount -t nfs 10.124.60.70:/work/kernel-src nfs
real 0m1.830s
user 0m0.001s
sys 0m1.653s
With this patch:
$ cat /proc/sys/fs/dentry-state
10236610 10234751 45 0 0 0
# mount -t nfs 10.124.60.70:/work/kernel-src nfs
real 0m0.106s
user 0m0.002s
sys 0m0.032s
[akpm@linux-foundation.org: fix comments]
Signed-off-by: Kentaro Makita <k-makita@np.css.fujitsu.com>
Cc: Neil Brown <neilb@suse.de>
Cc: Trond Myklebust <trond.myklebust@fys.uio.no>
Cc: David Chinner <dgc@sgi.com>
Cc: "J. Bruce Fields" <bfields@fieldses.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-07-24 04:27:13 +00:00
|
|
|
}
|
2011-01-07 06:49:31 +00:00
|
|
|
|
list_lru: remove special case function list_lru_dispose_all.
The list_lru implementation has one function, list_lru_dispose_all, with
only one user (the dentry code). At first, such function appears to make
sense because we are really not interested in the result of isolating each
dentry separately - all of them are going away anyway. However, it's
implementation is buggy in the following way:
When we call list_lru_dispose_all in fs/dcache.c, we scan all dentries
marking them with DCACHE_SHRINK_LIST. However, this is done without the
nlru->lock taken. The imediate result of that is that someone else may
add or remove the dentry from the LRU at the same time. When list_lru_del
happens in that scenario we will see an element that is not yet marked
with DCACHE_SHRINK_LIST (even though it will be in the future) and
obviously remove it from an lru where the element no longer is. Since
list_lru_dispose_all will in effect count down nlru's nr_items and
list_lru_del will do the same, this will lead to an imbalance.
The solution for this would not be so simple: we can obviously just keep
the lru_lock taken, but then we have no guarantees that we will be able to
acquire the dentry lock (dentry->d_lock). To properly solve this, we need
a communication mechanism between the lru and dentry code, so they can
coordinate this with each other.
Such mechanism already exists in the form of the list_lru_walk_cb
callback. So it is possible to construct a dcache-side prune function
that does the right thing only by calling list_lru_walk in a loop until no
more dentries are available.
With only one user, plus the fact that a sane solution for the problem
would involve boucing between dcache and list_lru anyway, I see little
justification to keep the special case list_lru_dispose_all in tree.
Signed-off-by: Glauber Costa <glommer@openvz.org>
Cc: Michal Hocko <mhocko@suse.cz>
Acked-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2013-08-28 00:18:03 +00:00
|
|
|
static enum lru_status dentry_lru_isolate_shrink(struct list_head *item,
|
2015-02-12 22:59:35 +00:00
|
|
|
struct list_lru_one *lru, spinlock_t *lru_lock, void *arg)
|
2013-08-28 00:17:55 +00:00
|
|
|
{
|
list_lru: remove special case function list_lru_dispose_all.
The list_lru implementation has one function, list_lru_dispose_all, with
only one user (the dentry code). At first, such function appears to make
sense because we are really not interested in the result of isolating each
dentry separately - all of them are going away anyway. However, it's
implementation is buggy in the following way:
When we call list_lru_dispose_all in fs/dcache.c, we scan all dentries
marking them with DCACHE_SHRINK_LIST. However, this is done without the
nlru->lock taken. The imediate result of that is that someone else may
add or remove the dentry from the LRU at the same time. When list_lru_del
happens in that scenario we will see an element that is not yet marked
with DCACHE_SHRINK_LIST (even though it will be in the future) and
obviously remove it from an lru where the element no longer is. Since
list_lru_dispose_all will in effect count down nlru's nr_items and
list_lru_del will do the same, this will lead to an imbalance.
The solution for this would not be so simple: we can obviously just keep
the lru_lock taken, but then we have no guarantees that we will be able to
acquire the dentry lock (dentry->d_lock). To properly solve this, we need
a communication mechanism between the lru and dentry code, so they can
coordinate this with each other.
Such mechanism already exists in the form of the list_lru_walk_cb
callback. So it is possible to construct a dcache-side prune function
that does the right thing only by calling list_lru_walk in a loop until no
more dentries are available.
With only one user, plus the fact that a sane solution for the problem
would involve boucing between dcache and list_lru anyway, I see little
justification to keep the special case list_lru_dispose_all in tree.
Signed-off-by: Glauber Costa <glommer@openvz.org>
Cc: Michal Hocko <mhocko@suse.cz>
Acked-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2013-08-28 00:18:03 +00:00
|
|
|
struct list_head *freeable = arg;
|
|
|
|
struct dentry *dentry = container_of(item, struct dentry, d_lru);
|
2013-08-28 00:17:55 +00:00
|
|
|
|
list_lru: remove special case function list_lru_dispose_all.
The list_lru implementation has one function, list_lru_dispose_all, with
only one user (the dentry code). At first, such function appears to make
sense because we are really not interested in the result of isolating each
dentry separately - all of them are going away anyway. However, it's
implementation is buggy in the following way:
When we call list_lru_dispose_all in fs/dcache.c, we scan all dentries
marking them with DCACHE_SHRINK_LIST. However, this is done without the
nlru->lock taken. The imediate result of that is that someone else may
add or remove the dentry from the LRU at the same time. When list_lru_del
happens in that scenario we will see an element that is not yet marked
with DCACHE_SHRINK_LIST (even though it will be in the future) and
obviously remove it from an lru where the element no longer is. Since
list_lru_dispose_all will in effect count down nlru's nr_items and
list_lru_del will do the same, this will lead to an imbalance.
The solution for this would not be so simple: we can obviously just keep
the lru_lock taken, but then we have no guarantees that we will be able to
acquire the dentry lock (dentry->d_lock). To properly solve this, we need
a communication mechanism between the lru and dentry code, so they can
coordinate this with each other.
Such mechanism already exists in the form of the list_lru_walk_cb
callback. So it is possible to construct a dcache-side prune function
that does the right thing only by calling list_lru_walk in a loop until no
more dentries are available.
With only one user, plus the fact that a sane solution for the problem
would involve boucing between dcache and list_lru anyway, I see little
justification to keep the special case list_lru_dispose_all in tree.
Signed-off-by: Glauber Costa <glommer@openvz.org>
Cc: Michal Hocko <mhocko@suse.cz>
Acked-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2013-08-28 00:18:03 +00:00
|
|
|
/*
|
|
|
|
* we are inverting the lru lock/dentry->d_lock here,
|
|
|
|
* so use a trylock. If we fail to get the lock, just skip
|
|
|
|
* it
|
|
|
|
*/
|
|
|
|
if (!spin_trylock(&dentry->d_lock))
|
|
|
|
return LRU_SKIP;
|
|
|
|
|
2015-02-12 22:59:35 +00:00
|
|
|
d_lru_shrink_move(lru, dentry, freeable);
|
list_lru: remove special case function list_lru_dispose_all.
The list_lru implementation has one function, list_lru_dispose_all, with
only one user (the dentry code). At first, such function appears to make
sense because we are really not interested in the result of isolating each
dentry separately - all of them are going away anyway. However, it's
implementation is buggy in the following way:
When we call list_lru_dispose_all in fs/dcache.c, we scan all dentries
marking them with DCACHE_SHRINK_LIST. However, this is done without the
nlru->lock taken. The imediate result of that is that someone else may
add or remove the dentry from the LRU at the same time. When list_lru_del
happens in that scenario we will see an element that is not yet marked
with DCACHE_SHRINK_LIST (even though it will be in the future) and
obviously remove it from an lru where the element no longer is. Since
list_lru_dispose_all will in effect count down nlru's nr_items and
list_lru_del will do the same, this will lead to an imbalance.
The solution for this would not be so simple: we can obviously just keep
the lru_lock taken, but then we have no guarantees that we will be able to
acquire the dentry lock (dentry->d_lock). To properly solve this, we need
a communication mechanism between the lru and dentry code, so they can
coordinate this with each other.
Such mechanism already exists in the form of the list_lru_walk_cb
callback. So it is possible to construct a dcache-side prune function
that does the right thing only by calling list_lru_walk in a loop until no
more dentries are available.
With only one user, plus the fact that a sane solution for the problem
would involve boucing between dcache and list_lru anyway, I see little
justification to keep the special case list_lru_dispose_all in tree.
Signed-off-by: Glauber Costa <glommer@openvz.org>
Cc: Michal Hocko <mhocko@suse.cz>
Acked-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2013-08-28 00:18:03 +00:00
|
|
|
spin_unlock(&dentry->d_lock);
|
2011-01-07 06:49:47 +00:00
|
|
|
|
list_lru: remove special case function list_lru_dispose_all.
The list_lru implementation has one function, list_lru_dispose_all, with
only one user (the dentry code). At first, such function appears to make
sense because we are really not interested in the result of isolating each
dentry separately - all of them are going away anyway. However, it's
implementation is buggy in the following way:
When we call list_lru_dispose_all in fs/dcache.c, we scan all dentries
marking them with DCACHE_SHRINK_LIST. However, this is done without the
nlru->lock taken. The imediate result of that is that someone else may
add or remove the dentry from the LRU at the same time. When list_lru_del
happens in that scenario we will see an element that is not yet marked
with DCACHE_SHRINK_LIST (even though it will be in the future) and
obviously remove it from an lru where the element no longer is. Since
list_lru_dispose_all will in effect count down nlru's nr_items and
list_lru_del will do the same, this will lead to an imbalance.
The solution for this would not be so simple: we can obviously just keep
the lru_lock taken, but then we have no guarantees that we will be able to
acquire the dentry lock (dentry->d_lock). To properly solve this, we need
a communication mechanism between the lru and dentry code, so they can
coordinate this with each other.
Such mechanism already exists in the form of the list_lru_walk_cb
callback. So it is possible to construct a dcache-side prune function
that does the right thing only by calling list_lru_walk in a loop until no
more dentries are available.
With only one user, plus the fact that a sane solution for the problem
would involve boucing between dcache and list_lru anyway, I see little
justification to keep the special case list_lru_dispose_all in tree.
Signed-off-by: Glauber Costa <glommer@openvz.org>
Cc: Michal Hocko <mhocko@suse.cz>
Acked-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2013-08-28 00:18:03 +00:00
|
|
|
return LRU_REMOVED;
|
fix soft lock up at NFS mount via per-SB LRU-list of unused dentries
[Summary]
Split LRU-list of unused dentries to one per superblock to avoid soft
lock up during NFS mounts and remounting of any filesystem.
Previously I posted here:
http://lkml.org/lkml/2008/3/5/590
[Descriptions]
- background
dentry_unused is a list of dentries which are not referenced.
dentry_unused grows up when references on directories or files are
released. This list can be very long if there is huge free memory.
- the problem
When shrink_dcache_sb() is called, it scans all dentry_unused linearly
under spin_lock(), and if dentry->d_sb is differnt from given
superblock, scan next dentry. This scan costs very much if there are
many entries, and very ineffective if there are many superblocks.
IOW, When we need to shrink unused dentries on one dentry, but scans
unused dentries on all superblocks in the system. For example, we scan
500 dentries to unmount a filesystem, but scans 1,000,000 or more unused
dentries on other superblocks.
In our case , At mounting NFS*, shrink_dcache_sb() is called to shrink
unused dentries on NFS, but scans 100,000,000 unused dentries on
superblocks in the system such as local ext3 filesystems. I hear NFS
mounting took 1 min on some system in use.
* : NFS uses virtual filesystem in rpc layer, so NFS is affected by
this problem.
100,000,000 is possible number on large systems.
Per-superblock LRU of unused dentried can reduce the cost in
reasonable manner.
- How to fix
I found this problem is solved by David Chinner's "Per-superblock
unused dentry LRU lists V3"(1), so I rebase it and add some fix to
reclaim with fairness, which is in Andrew Morton's comments(2).
1) http://lkml.org/lkml/2006/5/25/318
2) http://lkml.org/lkml/2006/5/25/320
Split LRU-list of unused dentries to each superblocks. Then, NFS
mounting will check dentries under a superblock instead of all. But
this spliting will break LRU of dentry-unused. So, I've attempted to
make reclaim unused dentrins with fairness by calculate number of
dentries to scan on this sb based on following way
number of dentries to scan on this sb =
count * (number of dentries on this sb / number of dentries in the machine)
- ToDo
- I have to measuring performance number and do stress tests.
- When unmount occurs during prune_dcache(), scanning on same
superblock, It is unable to reach next superblock because it is gone
away. We restart scannig superblock from first one, it causes
unfairness of reclaim unused dentries on first superblock. But I think
this happens very rarely.
- Test Results
Result on 6GB boxes with excessive unused dentries.
Without patch:
$ cat /proc/sys/fs/dentry-state
10181835 10180203 45 0 0 0
# mount -t nfs 10.124.60.70:/work/kernel-src nfs
real 0m1.830s
user 0m0.001s
sys 0m1.653s
With this patch:
$ cat /proc/sys/fs/dentry-state
10236610 10234751 45 0 0 0
# mount -t nfs 10.124.60.70:/work/kernel-src nfs
real 0m0.106s
user 0m0.002s
sys 0m0.032s
[akpm@linux-foundation.org: fix comments]
Signed-off-by: Kentaro Makita <k-makita@np.css.fujitsu.com>
Cc: Neil Brown <neilb@suse.de>
Cc: Trond Myklebust <trond.myklebust@fys.uio.no>
Cc: David Chinner <dgc@sgi.com>
Cc: "J. Bruce Fields" <bfields@fieldses.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-07-24 04:27:13 +00:00
|
|
|
}
|
|
|
|
|
list_lru: remove special case function list_lru_dispose_all.
The list_lru implementation has one function, list_lru_dispose_all, with
only one user (the dentry code). At first, such function appears to make
sense because we are really not interested in the result of isolating each
dentry separately - all of them are going away anyway. However, it's
implementation is buggy in the following way:
When we call list_lru_dispose_all in fs/dcache.c, we scan all dentries
marking them with DCACHE_SHRINK_LIST. However, this is done without the
nlru->lock taken. The imediate result of that is that someone else may
add or remove the dentry from the LRU at the same time. When list_lru_del
happens in that scenario we will see an element that is not yet marked
with DCACHE_SHRINK_LIST (even though it will be in the future) and
obviously remove it from an lru where the element no longer is. Since
list_lru_dispose_all will in effect count down nlru's nr_items and
list_lru_del will do the same, this will lead to an imbalance.
The solution for this would not be so simple: we can obviously just keep
the lru_lock taken, but then we have no guarantees that we will be able to
acquire the dentry lock (dentry->d_lock). To properly solve this, we need
a communication mechanism between the lru and dentry code, so they can
coordinate this with each other.
Such mechanism already exists in the form of the list_lru_walk_cb
callback. So it is possible to construct a dcache-side prune function
that does the right thing only by calling list_lru_walk in a loop until no
more dentries are available.
With only one user, plus the fact that a sane solution for the problem
would involve boucing between dcache and list_lru anyway, I see little
justification to keep the special case list_lru_dispose_all in tree.
Signed-off-by: Glauber Costa <glommer@openvz.org>
Cc: Michal Hocko <mhocko@suse.cz>
Acked-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2013-08-28 00:18:03 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/**
|
|
|
|
* shrink_dcache_sb - shrink dcache for a superblock
|
|
|
|
* @sb: superblock
|
|
|
|
*
|
2010-10-10 09:36:25 +00:00
|
|
|
* Shrink the dcache for the specified super block. This is used to free
|
|
|
|
* the dcache before unmounting a file system.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2010-10-10 09:36:25 +00:00
|
|
|
void shrink_dcache_sb(struct super_block *sb)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
list_lru: remove special case function list_lru_dispose_all.
The list_lru implementation has one function, list_lru_dispose_all, with
only one user (the dentry code). At first, such function appears to make
sense because we are really not interested in the result of isolating each
dentry separately - all of them are going away anyway. However, it's
implementation is buggy in the following way:
When we call list_lru_dispose_all in fs/dcache.c, we scan all dentries
marking them with DCACHE_SHRINK_LIST. However, this is done without the
nlru->lock taken. The imediate result of that is that someone else may
add or remove the dentry from the LRU at the same time. When list_lru_del
happens in that scenario we will see an element that is not yet marked
with DCACHE_SHRINK_LIST (even though it will be in the future) and
obviously remove it from an lru where the element no longer is. Since
list_lru_dispose_all will in effect count down nlru's nr_items and
list_lru_del will do the same, this will lead to an imbalance.
The solution for this would not be so simple: we can obviously just keep
the lru_lock taken, but then we have no guarantees that we will be able to
acquire the dentry lock (dentry->d_lock). To properly solve this, we need
a communication mechanism between the lru and dentry code, so they can
coordinate this with each other.
Such mechanism already exists in the form of the list_lru_walk_cb
callback. So it is possible to construct a dcache-side prune function
that does the right thing only by calling list_lru_walk in a loop until no
more dentries are available.
With only one user, plus the fact that a sane solution for the problem
would involve boucing between dcache and list_lru anyway, I see little
justification to keep the special case list_lru_dispose_all in tree.
Signed-off-by: Glauber Costa <glommer@openvz.org>
Cc: Michal Hocko <mhocko@suse.cz>
Acked-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2013-08-28 00:18:03 +00:00
|
|
|
do {
|
|
|
|
LIST_HEAD(dispose);
|
|
|
|
|
2019-01-30 18:52:36 +00:00
|
|
|
list_lru_walk(&sb->s_dentry_lru,
|
2017-07-10 22:50:00 +00:00
|
|
|
dentry_lru_isolate_shrink, &dispose, 1024);
|
list_lru: remove special case function list_lru_dispose_all.
The list_lru implementation has one function, list_lru_dispose_all, with
only one user (the dentry code). At first, such function appears to make
sense because we are really not interested in the result of isolating each
dentry separately - all of them are going away anyway. However, it's
implementation is buggy in the following way:
When we call list_lru_dispose_all in fs/dcache.c, we scan all dentries
marking them with DCACHE_SHRINK_LIST. However, this is done without the
nlru->lock taken. The imediate result of that is that someone else may
add or remove the dentry from the LRU at the same time. When list_lru_del
happens in that scenario we will see an element that is not yet marked
with DCACHE_SHRINK_LIST (even though it will be in the future) and
obviously remove it from an lru where the element no longer is. Since
list_lru_dispose_all will in effect count down nlru's nr_items and
list_lru_del will do the same, this will lead to an imbalance.
The solution for this would not be so simple: we can obviously just keep
the lru_lock taken, but then we have no guarantees that we will be able to
acquire the dentry lock (dentry->d_lock). To properly solve this, we need
a communication mechanism between the lru and dentry code, so they can
coordinate this with each other.
Such mechanism already exists in the form of the list_lru_walk_cb
callback. So it is possible to construct a dcache-side prune function
that does the right thing only by calling list_lru_walk in a loop until no
more dentries are available.
With only one user, plus the fact that a sane solution for the problem
would involve boucing between dcache and list_lru anyway, I see little
justification to keep the special case list_lru_dispose_all in tree.
Signed-off-by: Glauber Costa <glommer@openvz.org>
Cc: Michal Hocko <mhocko@suse.cz>
Acked-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2013-08-28 00:18:03 +00:00
|
|
|
shrink_dentry_list(&dispose);
|
2017-07-10 22:50:00 +00:00
|
|
|
} while (list_lru_count(&sb->s_dentry_lru) > 0);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2010-01-05 20:45:18 +00:00
|
|
|
EXPORT_SYMBOL(shrink_dcache_sb);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2013-09-05 09:44:35 +00:00
|
|
|
/**
|
|
|
|
* enum d_walk_ret - action to talke during tree walk
|
|
|
|
* @D_WALK_CONTINUE: contrinue walk
|
|
|
|
* @D_WALK_QUIT: quit walk
|
|
|
|
* @D_WALK_NORETRY: quit when retry is needed
|
|
|
|
* @D_WALK_SKIP: skip this dentry and its children
|
|
|
|
*/
|
|
|
|
enum d_walk_ret {
|
|
|
|
D_WALK_CONTINUE,
|
|
|
|
D_WALK_QUIT,
|
|
|
|
D_WALK_NORETRY,
|
|
|
|
D_WALK_SKIP,
|
|
|
|
};
|
2011-03-15 22:29:21 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/**
|
2013-09-05 09:44:35 +00:00
|
|
|
* d_walk - walk the dentry tree
|
|
|
|
* @parent: start of walk
|
|
|
|
* @data: data passed to @enter() and @finish()
|
|
|
|
* @enter: callback when first entering the dentry
|
2005-04-16 22:20:36 +00:00
|
|
|
*
|
2018-04-15 22:27:23 +00:00
|
|
|
* The @enter() callbacks are called with d_lock held.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2013-09-05 09:44:35 +00:00
|
|
|
static void d_walk(struct dentry *parent, void *data,
|
2018-04-15 22:27:23 +00:00
|
|
|
enum d_walk_ret (*enter)(void *, struct dentry *))
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2023-11-07 07:00:39 +00:00
|
|
|
struct dentry *this_parent, *dentry;
|
2013-09-09 19:22:25 +00:00
|
|
|
unsigned seq = 0;
|
2013-09-05 09:44:35 +00:00
|
|
|
enum d_walk_ret ret;
|
|
|
|
bool retry = true;
|
2011-01-07 06:49:37 +00:00
|
|
|
|
2011-01-07 06:49:39 +00:00
|
|
|
again:
|
2013-09-09 19:22:25 +00:00
|
|
|
read_seqbegin_or_lock(&rename_lock, &seq);
|
2011-01-07 06:49:39 +00:00
|
|
|
this_parent = parent;
|
2011-01-07 06:49:34 +00:00
|
|
|
spin_lock(&this_parent->d_lock);
|
2013-09-05 09:44:35 +00:00
|
|
|
|
|
|
|
ret = enter(data, this_parent);
|
|
|
|
switch (ret) {
|
|
|
|
case D_WALK_CONTINUE:
|
|
|
|
break;
|
|
|
|
case D_WALK_QUIT:
|
|
|
|
case D_WALK_SKIP:
|
|
|
|
goto out_unlock;
|
|
|
|
case D_WALK_NORETRY:
|
|
|
|
retry = false;
|
|
|
|
break;
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
repeat:
|
2023-11-07 07:00:39 +00:00
|
|
|
dentry = d_first_child(this_parent);
|
2005-04-16 22:20:36 +00:00
|
|
|
resume:
|
2023-11-07 07:00:39 +00:00
|
|
|
hlist_for_each_entry_from(dentry, d_sib) {
|
2016-06-10 15:32:47 +00:00
|
|
|
if (unlikely(dentry->d_flags & DCACHE_DENTRY_CURSOR))
|
|
|
|
continue;
|
|
|
|
|
2011-01-07 06:49:34 +00:00
|
|
|
spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
|
2013-09-05 09:44:35 +00:00
|
|
|
|
|
|
|
ret = enter(data, dentry);
|
|
|
|
switch (ret) {
|
|
|
|
case D_WALK_CONTINUE:
|
|
|
|
break;
|
|
|
|
case D_WALK_QUIT:
|
2011-01-07 06:49:34 +00:00
|
|
|
spin_unlock(&dentry->d_lock);
|
2013-09-05 09:44:35 +00:00
|
|
|
goto out_unlock;
|
|
|
|
case D_WALK_NORETRY:
|
|
|
|
retry = false;
|
|
|
|
break;
|
|
|
|
case D_WALK_SKIP:
|
|
|
|
spin_unlock(&dentry->d_lock);
|
|
|
|
continue;
|
2011-01-07 06:49:34 +00:00
|
|
|
}
|
2013-09-05 09:44:35 +00:00
|
|
|
|
2023-11-07 07:00:39 +00:00
|
|
|
if (!hlist_empty(&dentry->d_children)) {
|
2011-01-07 06:49:34 +00:00
|
|
|
spin_unlock(&this_parent->d_lock);
|
2019-09-19 16:09:40 +00:00
|
|
|
spin_release(&dentry->d_lock.dep_map, _RET_IP_);
|
2005-04-16 22:20:36 +00:00
|
|
|
this_parent = dentry;
|
2011-01-07 06:49:34 +00:00
|
|
|
spin_acquire(&this_parent->d_lock.dep_map, 0, 1, _RET_IP_);
|
2005-04-16 22:20:36 +00:00
|
|
|
goto repeat;
|
|
|
|
}
|
2011-01-07 06:49:34 +00:00
|
|
|
spin_unlock(&dentry->d_lock);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* All done at this level ... ascend and resume the search.
|
|
|
|
*/
|
2014-10-26 23:31:10 +00:00
|
|
|
rcu_read_lock();
|
|
|
|
ascend:
|
2005-04-16 22:20:36 +00:00
|
|
|
if (this_parent != parent) {
|
2023-11-07 07:00:39 +00:00
|
|
|
dentry = this_parent;
|
|
|
|
this_parent = dentry->d_parent;
|
2013-10-25 21:04:27 +00:00
|
|
|
|
2023-11-07 07:00:39 +00:00
|
|
|
spin_unlock(&dentry->d_lock);
|
2013-10-25 21:04:27 +00:00
|
|
|
spin_lock(&this_parent->d_lock);
|
|
|
|
|
2014-10-26 23:31:10 +00:00
|
|
|
/* might go back up the wrong parent if we have had a rename. */
|
|
|
|
if (need_seqretry(&rename_lock, seq))
|
2011-01-07 06:49:37 +00:00
|
|
|
goto rename_retry;
|
2015-05-29 03:09:19 +00:00
|
|
|
/* go into the first sibling still alive */
|
2023-11-07 07:00:39 +00:00
|
|
|
hlist_for_each_entry_continue(dentry, d_sib) {
|
|
|
|
if (likely(!(dentry->d_flags & DCACHE_DENTRY_KILLED))) {
|
|
|
|
rcu_read_unlock();
|
|
|
|
goto resume;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
goto ascend;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2014-10-26 23:31:10 +00:00
|
|
|
if (need_seqretry(&rename_lock, seq))
|
2011-01-07 06:49:37 +00:00
|
|
|
goto rename_retry;
|
2014-10-26 23:31:10 +00:00
|
|
|
rcu_read_unlock();
|
2013-09-05 09:44:35 +00:00
|
|
|
|
|
|
|
out_unlock:
|
|
|
|
spin_unlock(&this_parent->d_lock);
|
2013-09-09 19:22:25 +00:00
|
|
|
done_seqretry(&rename_lock, seq);
|
2013-09-05 09:44:35 +00:00
|
|
|
return;
|
2011-01-07 06:49:39 +00:00
|
|
|
|
|
|
|
rename_retry:
|
2014-10-26 23:31:10 +00:00
|
|
|
spin_unlock(&this_parent->d_lock);
|
|
|
|
rcu_read_unlock();
|
|
|
|
BUG_ON(seq & 1);
|
2013-09-05 09:44:35 +00:00
|
|
|
if (!retry)
|
|
|
|
return;
|
2013-09-09 19:22:25 +00:00
|
|
|
seq = 1;
|
2011-01-07 06:49:39 +00:00
|
|
|
goto again;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2013-09-05 09:44:35 +00:00
|
|
|
|
2016-11-23 21:03:41 +00:00
|
|
|
struct check_mount {
|
|
|
|
struct vfsmount *mnt;
|
|
|
|
unsigned int mounted;
|
|
|
|
};
|
|
|
|
|
|
|
|
static enum d_walk_ret path_check_mount(void *data, struct dentry *dentry)
|
|
|
|
{
|
|
|
|
struct check_mount *info = data;
|
|
|
|
struct path path = { .mnt = info->mnt, .dentry = dentry };
|
|
|
|
|
|
|
|
if (likely(!d_mountpoint(dentry)))
|
|
|
|
return D_WALK_CONTINUE;
|
|
|
|
if (__path_is_mountpoint(&path)) {
|
|
|
|
info->mounted = 1;
|
|
|
|
return D_WALK_QUIT;
|
|
|
|
}
|
|
|
|
return D_WALK_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* path_has_submounts - check for mounts over a dentry in the
|
|
|
|
* current namespace.
|
|
|
|
* @parent: path to check.
|
|
|
|
*
|
|
|
|
* Return true if the parent or its subdirectories contain
|
|
|
|
* a mount point in the current namespace.
|
|
|
|
*/
|
|
|
|
int path_has_submounts(const struct path *parent)
|
|
|
|
{
|
|
|
|
struct check_mount data = { .mnt = parent->mnt, .mounted = 0 };
|
|
|
|
|
|
|
|
read_seqlock_excl(&mount_lock);
|
2018-04-15 22:27:23 +00:00
|
|
|
d_walk(parent->dentry, &data, path_check_mount);
|
2016-11-23 21:03:41 +00:00
|
|
|
read_sequnlock_excl(&mount_lock);
|
|
|
|
|
|
|
|
return data.mounted;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(path_has_submounts);
|
|
|
|
|
2013-09-05 12:39:11 +00:00
|
|
|
/*
|
|
|
|
* Called by mount code to set a mountpoint and check if the mountpoint is
|
|
|
|
* reachable (e.g. NFS can unhash a directory dentry and then the complete
|
|
|
|
* subtree can become unreachable).
|
|
|
|
*
|
2014-02-13 17:39:37 +00:00
|
|
|
* Only one of d_invalidate() and d_set_mounted() must succeed. For
|
2013-09-05 12:39:11 +00:00
|
|
|
* this reason take rename_lock and d_lock on dentry and ancestors.
|
|
|
|
*/
|
|
|
|
int d_set_mounted(struct dentry *dentry)
|
|
|
|
{
|
|
|
|
struct dentry *p;
|
|
|
|
int ret = -ENOENT;
|
|
|
|
write_seqlock(&rename_lock);
|
|
|
|
for (p = dentry->d_parent; !IS_ROOT(p); p = p->d_parent) {
|
2014-02-13 17:39:37 +00:00
|
|
|
/* Need exclusion wrt. d_invalidate() */
|
2013-09-05 12:39:11 +00:00
|
|
|
spin_lock(&p->d_lock);
|
|
|
|
if (unlikely(d_unhashed(p))) {
|
|
|
|
spin_unlock(&p->d_lock);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
spin_unlock(&p->d_lock);
|
|
|
|
}
|
|
|
|
spin_lock(&dentry->d_lock);
|
|
|
|
if (!d_unlinked(dentry)) {
|
2017-01-03 01:18:43 +00:00
|
|
|
ret = -EBUSY;
|
|
|
|
if (!d_mountpoint(dentry)) {
|
|
|
|
dentry->d_flags |= DCACHE_MOUNTED;
|
|
|
|
ret = 0;
|
|
|
|
}
|
2013-09-05 12:39:11 +00:00
|
|
|
}
|
|
|
|
spin_unlock(&dentry->d_lock);
|
|
|
|
out:
|
|
|
|
write_sequnlock(&rename_lock);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
2012-09-18 20:35:51 +00:00
|
|
|
* Search the dentry child list of the specified parent,
|
2005-04-16 22:20:36 +00:00
|
|
|
* and move any unused dentries to the end of the unused
|
|
|
|
* list for prune_dcache(). We descend to the next level
|
2023-11-07 07:00:39 +00:00
|
|
|
* whenever the d_children list is non-empty and continue
|
2005-04-16 22:20:36 +00:00
|
|
|
* searching.
|
|
|
|
*
|
|
|
|
* It returns zero iff there are no unused children,
|
|
|
|
* otherwise it returns the number of children moved to
|
|
|
|
* the end of the unused list. This may not be the total
|
|
|
|
* number of unused children, because select_parent can
|
|
|
|
* drop the lock and return early due to latency
|
|
|
|
* constraints.
|
|
|
|
*/
|
|
|
|
|
2013-09-05 09:44:35 +00:00
|
|
|
struct select_data {
|
|
|
|
struct dentry *start;
|
Teach shrink_dcache_parent() to cope with mixed-filesystem shrink lists
Currently, running into a shrink list that contains dentries from different
filesystems can cause several unpleasant things for shrink_dcache_parent()
and for umount(2).
The first problem is that there's a window during shrink_dentry_list() between
__dentry_kill() takes a victim out and dropping reference to its parent. During
that window the parent looks like a genuine busy dentry. shrink_dcache_parent()
(or, worse yet, shrink_dcache_for_umount()) coming at that time will see no
eviction candidates and no indication that it needs to wait for some
shrink_dentry_list() to proceed further.
That applies for any shrink list that might intersect with the subtree we are
trying to shrink; the only reason it does not blow on umount(2) in the mainline
is that we unregister the memory shrinker before hitting shrink_dcache_for_umount().
Another problem happens if something in a mixed-filesystem shrink list gets
be stuck in e.g. iput(), getting umount of unrelated fs to spin waiting for
the stuck shrinker to get around to our dentries.
Solution:
1) have shrink_dentry_list() decrement the parent's refcount and
make sure it's on a shrink list (ours unless it already had been on some
other) before calling __dentry_kill(). That eliminates the window when
shrink_dcache_parent() would've blown past the entire subtree without
noticing anything with zero refcount not on shrink lists.
2) when shrink_dcache_parent() has found no eviction candidates,
but some dentries are still sitting on shrink lists, rather than
repeating the scan in hope that shrinkers have progressed, scan looking
for something on shrink lists with zero refcount. If such a thing is
found, grab rcu_read_lock() and stop the scan, with caller locking
it for eviction, dropping out of RCU and doing __dentry_kill(), with
the same treatment for parent as shrink_dentry_list() would do.
Note that right now mixed-filesystem shrink lists do not occur, so this
is not a mainline bug. Howevere, there's a bunch of uses for such
beasts (e.g. the "try and evict everything we can out of given page"
patches; there are potential uses in mount-related code, considerably
simplifying the life in fs/namespace.c, etc.)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2019-06-29 22:31:24 +00:00
|
|
|
union {
|
|
|
|
long found;
|
|
|
|
struct dentry *victim;
|
|
|
|
};
|
2013-09-05 09:44:35 +00:00
|
|
|
struct list_head dispose;
|
|
|
|
};
|
2011-01-07 06:49:31 +00:00
|
|
|
|
2013-09-05 09:44:35 +00:00
|
|
|
static enum d_walk_ret select_collect(void *_data, struct dentry *dentry)
|
|
|
|
{
|
|
|
|
struct select_data *data = _data;
|
|
|
|
enum d_walk_ret ret = D_WALK_CONTINUE;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2013-09-05 09:44:35 +00:00
|
|
|
if (data->start == dentry)
|
|
|
|
goto out;
|
2011-01-07 06:49:34 +00:00
|
|
|
|
2014-05-03 04:02:25 +00:00
|
|
|
if (dentry->d_flags & DCACHE_SHRINK_LIST) {
|
2013-09-05 09:44:35 +00:00
|
|
|
data->found++;
|
2023-10-31 01:07:34 +00:00
|
|
|
} else if (!dentry->d_lockref.count) {
|
|
|
|
to_shrink_list(dentry, &data->dispose);
|
|
|
|
data->found++;
|
__dentry_kill(): new locking scheme
Currently we enter __dentry_kill() with parent (along with the victim
dentry and victim's inode) held locked. Then we
mark dentry refcount as dead
call ->d_prune()
remove dentry from hash
remove it from the parent's list of children
unlock the parent, don't need it from that point on
detach dentry from inode, unlock dentry and drop the inode
(via ->d_iput())
call ->d_release()
regain the lock on dentry
check if it's on a shrink list (in which case freeing its empty husk
has to be left to shrink_dentry_list()) or not (in which case we can free it
ourselves). In the former case, mark it as an empty husk, so that
shrink_dentry_list() would know it can free the sucker.
drop the lock on dentry
... and usually the caller proceeds to drop a reference on the parent,
possibly retaking the lock on it.
That is painful for a bunch of reasons, starting with the need to take locks
out of order, but not limited to that - the parent of positive dentry can
change if we drop its ->d_lock, so getting these locks has to be done with
care. Moreover, as soon as dentry is out of the parent's list of children,
shrink_dcache_for_umount() won't see it anymore, making it appear as if
the parent is inexplicably busy. We do work around that by having
shrink_dentry_list() decrement the parent's refcount first and put it on
shrink list to be evicted once we are done with __dentry_kill() of child,
but that may in some cases lead to ->d_iput() on child called after the
parent got killed. That doesn't happen in cases where in-tree ->d_iput()
instances might want to look at the parent, but that's brittle as hell.
Solution: do removal from the parent's list of children in the very
end of __dentry_kill(). As the result, the callers do not need to
lock the parent and by the time we really need the parent locked,
dentry is negative and is guaranteed not to be moved around.
It does mean that ->d_prune() will be called with parent not locked.
It also means that we might see dentries in process of being torn
down while going through the parent's list of children; those dentries
will be unhashed, negative and with refcount marked dead. In practice,
that's enough for in-tree code that looks through the list of children
to do the right thing as-is. Out-of-tree code might need to be adjusted.
Calling conventions: __dentry_kill(dentry) is called with dentry->d_lock
held, along with ->i_lock of its inode (if any). It either returns
the parent (locked, with refcount decremented to 0) or NULL (if there'd
been no parent or if refcount decrement for parent hadn't reached 0).
lock_for_kill() is adjusted for new requirements - it doesn't touch
the parent's ->d_lock at all.
Callers adjusted. Note that for dput() we don't need to bother with
fast_dput() for the parent - we just need to check retain_dentry()
for it, since its ->d_lock is still held since the moment when
__dentry_kill() had taken it to remove the victim from the list of
children.
The kludge with early decrement of parent's refcount in
shrink_dentry_list() is no longer needed - shrink_dcache_for_umount()
sees the half-killed dentries in the list of children for as long
as they are pinning the parent. They are easily recognized and
accounted for by select_collect(), so we know we are not done yet.
As the result, we always have the expected ordering for ->d_iput()/->d_release()
vs. __dentry_kill() of the parent, no exceptions. Moreover, the current
rules for shrink lists (one must make sure that shrink_dcache_for_umount()
won't happen while any dentries from the superblock in question are on
any shrink lists) are gone - shrink_dcache_for_umount() will do the
right thing in all cases, taking such dentries out. Their empty
husks (memory occupied by struct dentry itself + its external name,
if any) will remain on the shrink lists, but they are no obstacles
to filesystem shutdown. And such husks will get freed as soon as
shrink_dentry_list() of the list they are on gets to them.
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-11-07 21:14:08 +00:00
|
|
|
} else if (dentry->d_lockref.count < 0) {
|
|
|
|
data->found++;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2013-09-05 09:44:35 +00:00
|
|
|
/*
|
|
|
|
* We can return to the caller if we have found some (this
|
|
|
|
* ensures forward progress). We'll be coming back to find
|
|
|
|
* the rest.
|
|
|
|
*/
|
2014-05-03 04:02:25 +00:00
|
|
|
if (!list_empty(&data->dispose))
|
|
|
|
ret = need_resched() ? D_WALK_QUIT : D_WALK_NORETRY;
|
2005-04-16 22:20:36 +00:00
|
|
|
out:
|
2013-09-05 09:44:35 +00:00
|
|
|
return ret;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
Teach shrink_dcache_parent() to cope with mixed-filesystem shrink lists
Currently, running into a shrink list that contains dentries from different
filesystems can cause several unpleasant things for shrink_dcache_parent()
and for umount(2).
The first problem is that there's a window during shrink_dentry_list() between
__dentry_kill() takes a victim out and dropping reference to its parent. During
that window the parent looks like a genuine busy dentry. shrink_dcache_parent()
(or, worse yet, shrink_dcache_for_umount()) coming at that time will see no
eviction candidates and no indication that it needs to wait for some
shrink_dentry_list() to proceed further.
That applies for any shrink list that might intersect with the subtree we are
trying to shrink; the only reason it does not blow on umount(2) in the mainline
is that we unregister the memory shrinker before hitting shrink_dcache_for_umount().
Another problem happens if something in a mixed-filesystem shrink list gets
be stuck in e.g. iput(), getting umount of unrelated fs to spin waiting for
the stuck shrinker to get around to our dentries.
Solution:
1) have shrink_dentry_list() decrement the parent's refcount and
make sure it's on a shrink list (ours unless it already had been on some
other) before calling __dentry_kill(). That eliminates the window when
shrink_dcache_parent() would've blown past the entire subtree without
noticing anything with zero refcount not on shrink lists.
2) when shrink_dcache_parent() has found no eviction candidates,
but some dentries are still sitting on shrink lists, rather than
repeating the scan in hope that shrinkers have progressed, scan looking
for something on shrink lists with zero refcount. If such a thing is
found, grab rcu_read_lock() and stop the scan, with caller locking
it for eviction, dropping out of RCU and doing __dentry_kill(), with
the same treatment for parent as shrink_dentry_list() would do.
Note that right now mixed-filesystem shrink lists do not occur, so this
is not a mainline bug. Howevere, there's a bunch of uses for such
beasts (e.g. the "try and evict everything we can out of given page"
patches; there are potential uses in mount-related code, considerably
simplifying the life in fs/namespace.c, etc.)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2019-06-29 22:31:24 +00:00
|
|
|
static enum d_walk_ret select_collect2(void *_data, struct dentry *dentry)
|
|
|
|
{
|
|
|
|
struct select_data *data = _data;
|
|
|
|
enum d_walk_ret ret = D_WALK_CONTINUE;
|
|
|
|
|
|
|
|
if (data->start == dentry)
|
|
|
|
goto out;
|
|
|
|
|
2023-10-31 01:07:34 +00:00
|
|
|
if (!dentry->d_lockref.count) {
|
|
|
|
if (dentry->d_flags & DCACHE_SHRINK_LIST) {
|
Teach shrink_dcache_parent() to cope with mixed-filesystem shrink lists
Currently, running into a shrink list that contains dentries from different
filesystems can cause several unpleasant things for shrink_dcache_parent()
and for umount(2).
The first problem is that there's a window during shrink_dentry_list() between
__dentry_kill() takes a victim out and dropping reference to its parent. During
that window the parent looks like a genuine busy dentry. shrink_dcache_parent()
(or, worse yet, shrink_dcache_for_umount()) coming at that time will see no
eviction candidates and no indication that it needs to wait for some
shrink_dentry_list() to proceed further.
That applies for any shrink list that might intersect with the subtree we are
trying to shrink; the only reason it does not blow on umount(2) in the mainline
is that we unregister the memory shrinker before hitting shrink_dcache_for_umount().
Another problem happens if something in a mixed-filesystem shrink list gets
be stuck in e.g. iput(), getting umount of unrelated fs to spin waiting for
the stuck shrinker to get around to our dentries.
Solution:
1) have shrink_dentry_list() decrement the parent's refcount and
make sure it's on a shrink list (ours unless it already had been on some
other) before calling __dentry_kill(). That eliminates the window when
shrink_dcache_parent() would've blown past the entire subtree without
noticing anything with zero refcount not on shrink lists.
2) when shrink_dcache_parent() has found no eviction candidates,
but some dentries are still sitting on shrink lists, rather than
repeating the scan in hope that shrinkers have progressed, scan looking
for something on shrink lists with zero refcount. If such a thing is
found, grab rcu_read_lock() and stop the scan, with caller locking
it for eviction, dropping out of RCU and doing __dentry_kill(), with
the same treatment for parent as shrink_dentry_list() would do.
Note that right now mixed-filesystem shrink lists do not occur, so this
is not a mainline bug. Howevere, there's a bunch of uses for such
beasts (e.g. the "try and evict everything we can out of given page"
patches; there are potential uses in mount-related code, considerably
simplifying the life in fs/namespace.c, etc.)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2019-06-29 22:31:24 +00:00
|
|
|
rcu_read_lock();
|
|
|
|
data->victim = dentry;
|
|
|
|
return D_WALK_QUIT;
|
|
|
|
}
|
2023-10-31 01:07:34 +00:00
|
|
|
to_shrink_list(dentry, &data->dispose);
|
Teach shrink_dcache_parent() to cope with mixed-filesystem shrink lists
Currently, running into a shrink list that contains dentries from different
filesystems can cause several unpleasant things for shrink_dcache_parent()
and for umount(2).
The first problem is that there's a window during shrink_dentry_list() between
__dentry_kill() takes a victim out and dropping reference to its parent. During
that window the parent looks like a genuine busy dentry. shrink_dcache_parent()
(or, worse yet, shrink_dcache_for_umount()) coming at that time will see no
eviction candidates and no indication that it needs to wait for some
shrink_dentry_list() to proceed further.
That applies for any shrink list that might intersect with the subtree we are
trying to shrink; the only reason it does not blow on umount(2) in the mainline
is that we unregister the memory shrinker before hitting shrink_dcache_for_umount().
Another problem happens if something in a mixed-filesystem shrink list gets
be stuck in e.g. iput(), getting umount of unrelated fs to spin waiting for
the stuck shrinker to get around to our dentries.
Solution:
1) have shrink_dentry_list() decrement the parent's refcount and
make sure it's on a shrink list (ours unless it already had been on some
other) before calling __dentry_kill(). That eliminates the window when
shrink_dcache_parent() would've blown past the entire subtree without
noticing anything with zero refcount not on shrink lists.
2) when shrink_dcache_parent() has found no eviction candidates,
but some dentries are still sitting on shrink lists, rather than
repeating the scan in hope that shrinkers have progressed, scan looking
for something on shrink lists with zero refcount. If such a thing is
found, grab rcu_read_lock() and stop the scan, with caller locking
it for eviction, dropping out of RCU and doing __dentry_kill(), with
the same treatment for parent as shrink_dentry_list() would do.
Note that right now mixed-filesystem shrink lists do not occur, so this
is not a mainline bug. Howevere, there's a bunch of uses for such
beasts (e.g. the "try and evict everything we can out of given page"
patches; there are potential uses in mount-related code, considerably
simplifying the life in fs/namespace.c, etc.)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2019-06-29 22:31:24 +00:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* We can return to the caller if we have found some (this
|
|
|
|
* ensures forward progress). We'll be coming back to find
|
|
|
|
* the rest.
|
|
|
|
*/
|
|
|
|
if (!list_empty(&data->dispose))
|
|
|
|
ret = need_resched() ? D_WALK_QUIT : D_WALK_NORETRY;
|
|
|
|
out:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/**
|
|
|
|
* shrink_dcache_parent - prune dcache
|
|
|
|
* @parent: parent of entries to prune
|
|
|
|
*
|
|
|
|
* Prune the dcache to remove unused children of the parent dentry.
|
|
|
|
*/
|
2013-09-05 09:44:35 +00:00
|
|
|
void shrink_dcache_parent(struct dentry *parent)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2013-09-05 09:44:35 +00:00
|
|
|
for (;;) {
|
Teach shrink_dcache_parent() to cope with mixed-filesystem shrink lists
Currently, running into a shrink list that contains dentries from different
filesystems can cause several unpleasant things for shrink_dcache_parent()
and for umount(2).
The first problem is that there's a window during shrink_dentry_list() between
__dentry_kill() takes a victim out and dropping reference to its parent. During
that window the parent looks like a genuine busy dentry. shrink_dcache_parent()
(or, worse yet, shrink_dcache_for_umount()) coming at that time will see no
eviction candidates and no indication that it needs to wait for some
shrink_dentry_list() to proceed further.
That applies for any shrink list that might intersect with the subtree we are
trying to shrink; the only reason it does not blow on umount(2) in the mainline
is that we unregister the memory shrinker before hitting shrink_dcache_for_umount().
Another problem happens if something in a mixed-filesystem shrink list gets
be stuck in e.g. iput(), getting umount of unrelated fs to spin waiting for
the stuck shrinker to get around to our dentries.
Solution:
1) have shrink_dentry_list() decrement the parent's refcount and
make sure it's on a shrink list (ours unless it already had been on some
other) before calling __dentry_kill(). That eliminates the window when
shrink_dcache_parent() would've blown past the entire subtree without
noticing anything with zero refcount not on shrink lists.
2) when shrink_dcache_parent() has found no eviction candidates,
but some dentries are still sitting on shrink lists, rather than
repeating the scan in hope that shrinkers have progressed, scan looking
for something on shrink lists with zero refcount. If such a thing is
found, grab rcu_read_lock() and stop the scan, with caller locking
it for eviction, dropping out of RCU and doing __dentry_kill(), with
the same treatment for parent as shrink_dentry_list() would do.
Note that right now mixed-filesystem shrink lists do not occur, so this
is not a mainline bug. Howevere, there's a bunch of uses for such
beasts (e.g. the "try and evict everything we can out of given page"
patches; there are potential uses in mount-related code, considerably
simplifying the life in fs/namespace.c, etc.)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2019-06-29 22:31:24 +00:00
|
|
|
struct select_data data = {.start = parent};
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2013-09-05 09:44:35 +00:00
|
|
|
INIT_LIST_HEAD(&data.dispose);
|
2018-04-15 22:27:23 +00:00
|
|
|
d_walk(parent, &data, select_collect);
|
2018-04-20 03:58:48 +00:00
|
|
|
|
|
|
|
if (!list_empty(&data.dispose)) {
|
|
|
|
shrink_dentry_list(&data.dispose);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
cond_resched();
|
2013-09-05 09:44:35 +00:00
|
|
|
if (!data.found)
|
|
|
|
break;
|
Teach shrink_dcache_parent() to cope with mixed-filesystem shrink lists
Currently, running into a shrink list that contains dentries from different
filesystems can cause several unpleasant things for shrink_dcache_parent()
and for umount(2).
The first problem is that there's a window during shrink_dentry_list() between
__dentry_kill() takes a victim out and dropping reference to its parent. During
that window the parent looks like a genuine busy dentry. shrink_dcache_parent()
(or, worse yet, shrink_dcache_for_umount()) coming at that time will see no
eviction candidates and no indication that it needs to wait for some
shrink_dentry_list() to proceed further.
That applies for any shrink list that might intersect with the subtree we are
trying to shrink; the only reason it does not blow on umount(2) in the mainline
is that we unregister the memory shrinker before hitting shrink_dcache_for_umount().
Another problem happens if something in a mixed-filesystem shrink list gets
be stuck in e.g. iput(), getting umount of unrelated fs to spin waiting for
the stuck shrinker to get around to our dentries.
Solution:
1) have shrink_dentry_list() decrement the parent's refcount and
make sure it's on a shrink list (ours unless it already had been on some
other) before calling __dentry_kill(). That eliminates the window when
shrink_dcache_parent() would've blown past the entire subtree without
noticing anything with zero refcount not on shrink lists.
2) when shrink_dcache_parent() has found no eviction candidates,
but some dentries are still sitting on shrink lists, rather than
repeating the scan in hope that shrinkers have progressed, scan looking
for something on shrink lists with zero refcount. If such a thing is
found, grab rcu_read_lock() and stop the scan, with caller locking
it for eviction, dropping out of RCU and doing __dentry_kill(), with
the same treatment for parent as shrink_dentry_list() would do.
Note that right now mixed-filesystem shrink lists do not occur, so this
is not a mainline bug. Howevere, there's a bunch of uses for such
beasts (e.g. the "try and evict everything we can out of given page"
patches; there are potential uses in mount-related code, considerably
simplifying the life in fs/namespace.c, etc.)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2019-06-29 22:31:24 +00:00
|
|
|
data.victim = NULL;
|
|
|
|
d_walk(parent, &data, select_collect2);
|
|
|
|
if (data.victim) {
|
|
|
|
spin_lock(&data.victim->d_lock);
|
don't try to cut corners in shrink_lock_dentry()
That is to say, do *not* treat the ->d_inode or ->d_parent changes
as "it's hard, return false; somebody must have grabbed it, so
even if has zero refcount, we don't need to bother killing it -
final dput() from whoever grabbed it would've done everything".
First of all, that is not guaranteed. It might have been dropped
by shrink_kill() handling of victim's parent, which would've found
it already on a shrink list (ours) and decided that they don't need
to put it on their shrink list.
What's more, dentry_kill() is doing pretty much the same thing,
cutting its own set of corners (it assumes that dentry can't
go from positive to negative, so its inode can change but only once
and only in one direction).
Doing that right allows to get rid of that not-quite-duplication
and removes the only reason for re-incrementing refcount before
the call of dentry_kill().
Replacement is called lock_for_kill(); called under rcu_read_lock
and with ->d_lock held. If it returns false, dentry has non-zero
refcount and the same locks are held. If it returns true,
dentry has zero refcount and all locks required by __dentry_kill()
are taken.
Part of __lock_parent() had been lifted into lock_parent() to
allow its reuse. Now it's called with rcu_read_lock already
held and dentry already unlocked.
Note that this is not the final change - locking requirements for
__dentry_kill() are going to change later in the series and the
set of locks taken by lock_for_kill() will be adjusted. Both
lock_parent() and __lock_parent() will be gone once that happens.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-10-31 05:23:47 +00:00
|
|
|
if (!lock_for_kill(data.victim)) {
|
Teach shrink_dcache_parent() to cope with mixed-filesystem shrink lists
Currently, running into a shrink list that contains dentries from different
filesystems can cause several unpleasant things for shrink_dcache_parent()
and for umount(2).
The first problem is that there's a window during shrink_dentry_list() between
__dentry_kill() takes a victim out and dropping reference to its parent. During
that window the parent looks like a genuine busy dentry. shrink_dcache_parent()
(or, worse yet, shrink_dcache_for_umount()) coming at that time will see no
eviction candidates and no indication that it needs to wait for some
shrink_dentry_list() to proceed further.
That applies for any shrink list that might intersect with the subtree we are
trying to shrink; the only reason it does not blow on umount(2) in the mainline
is that we unregister the memory shrinker before hitting shrink_dcache_for_umount().
Another problem happens if something in a mixed-filesystem shrink list gets
be stuck in e.g. iput(), getting umount of unrelated fs to spin waiting for
the stuck shrinker to get around to our dentries.
Solution:
1) have shrink_dentry_list() decrement the parent's refcount and
make sure it's on a shrink list (ours unless it already had been on some
other) before calling __dentry_kill(). That eliminates the window when
shrink_dcache_parent() would've blown past the entire subtree without
noticing anything with zero refcount not on shrink lists.
2) when shrink_dcache_parent() has found no eviction candidates,
but some dentries are still sitting on shrink lists, rather than
repeating the scan in hope that shrinkers have progressed, scan looking
for something on shrink lists with zero refcount. If such a thing is
found, grab rcu_read_lock() and stop the scan, with caller locking
it for eviction, dropping out of RCU and doing __dentry_kill(), with
the same treatment for parent as shrink_dentry_list() would do.
Note that right now mixed-filesystem shrink lists do not occur, so this
is not a mainline bug. Howevere, there's a bunch of uses for such
beasts (e.g. the "try and evict everything we can out of given page"
patches; there are potential uses in mount-related code, considerably
simplifying the life in fs/namespace.c, etc.)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2019-06-29 22:31:24 +00:00
|
|
|
spin_unlock(&data.victim->d_lock);
|
|
|
|
rcu_read_unlock();
|
|
|
|
} else {
|
__dentry_kill(): new locking scheme
Currently we enter __dentry_kill() with parent (along with the victim
dentry and victim's inode) held locked. Then we
mark dentry refcount as dead
call ->d_prune()
remove dentry from hash
remove it from the parent's list of children
unlock the parent, don't need it from that point on
detach dentry from inode, unlock dentry and drop the inode
(via ->d_iput())
call ->d_release()
regain the lock on dentry
check if it's on a shrink list (in which case freeing its empty husk
has to be left to shrink_dentry_list()) or not (in which case we can free it
ourselves). In the former case, mark it as an empty husk, so that
shrink_dentry_list() would know it can free the sucker.
drop the lock on dentry
... and usually the caller proceeds to drop a reference on the parent,
possibly retaking the lock on it.
That is painful for a bunch of reasons, starting with the need to take locks
out of order, but not limited to that - the parent of positive dentry can
change if we drop its ->d_lock, so getting these locks has to be done with
care. Moreover, as soon as dentry is out of the parent's list of children,
shrink_dcache_for_umount() won't see it anymore, making it appear as if
the parent is inexplicably busy. We do work around that by having
shrink_dentry_list() decrement the parent's refcount first and put it on
shrink list to be evicted once we are done with __dentry_kill() of child,
but that may in some cases lead to ->d_iput() on child called after the
parent got killed. That doesn't happen in cases where in-tree ->d_iput()
instances might want to look at the parent, but that's brittle as hell.
Solution: do removal from the parent's list of children in the very
end of __dentry_kill(). As the result, the callers do not need to
lock the parent and by the time we really need the parent locked,
dentry is negative and is guaranteed not to be moved around.
It does mean that ->d_prune() will be called with parent not locked.
It also means that we might see dentries in process of being torn
down while going through the parent's list of children; those dentries
will be unhashed, negative and with refcount marked dead. In practice,
that's enough for in-tree code that looks through the list of children
to do the right thing as-is. Out-of-tree code might need to be adjusted.
Calling conventions: __dentry_kill(dentry) is called with dentry->d_lock
held, along with ->i_lock of its inode (if any). It either returns
the parent (locked, with refcount decremented to 0) or NULL (if there'd
been no parent or if refcount decrement for parent hadn't reached 0).
lock_for_kill() is adjusted for new requirements - it doesn't touch
the parent's ->d_lock at all.
Callers adjusted. Note that for dput() we don't need to bother with
fast_dput() for the parent - we just need to check retain_dentry()
for it, since its ->d_lock is still held since the moment when
__dentry_kill() had taken it to remove the victim from the list of
children.
The kludge with early decrement of parent's refcount in
shrink_dentry_list() is no longer needed - shrink_dcache_for_umount()
sees the half-killed dentries in the list of children for as long
as they are pinning the parent. They are easily recognized and
accounted for by select_collect(), so we know we are not done yet.
As the result, we always have the expected ordering for ->d_iput()/->d_release()
vs. __dentry_kill() of the parent, no exceptions. Moreover, the current
rules for shrink lists (one must make sure that shrink_dcache_for_umount()
won't happen while any dentries from the superblock in question are on
any shrink lists) are gone - shrink_dcache_for_umount() will do the
right thing in all cases, taking such dentries out. Their empty
husks (memory occupied by struct dentry itself + its external name,
if any) will remain on the shrink lists, but they are no obstacles
to filesystem shutdown. And such husks will get freed as soon as
shrink_dentry_list() of the list they are on gets to them.
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2023-11-07 21:14:08 +00:00
|
|
|
shrink_kill(data.victim);
|
Teach shrink_dcache_parent() to cope with mixed-filesystem shrink lists
Currently, running into a shrink list that contains dentries from different
filesystems can cause several unpleasant things for shrink_dcache_parent()
and for umount(2).
The first problem is that there's a window during shrink_dentry_list() between
__dentry_kill() takes a victim out and dropping reference to its parent. During
that window the parent looks like a genuine busy dentry. shrink_dcache_parent()
(or, worse yet, shrink_dcache_for_umount()) coming at that time will see no
eviction candidates and no indication that it needs to wait for some
shrink_dentry_list() to proceed further.
That applies for any shrink list that might intersect with the subtree we are
trying to shrink; the only reason it does not blow on umount(2) in the mainline
is that we unregister the memory shrinker before hitting shrink_dcache_for_umount().
Another problem happens if something in a mixed-filesystem shrink list gets
be stuck in e.g. iput(), getting umount of unrelated fs to spin waiting for
the stuck shrinker to get around to our dentries.
Solution:
1) have shrink_dentry_list() decrement the parent's refcount and
make sure it's on a shrink list (ours unless it already had been on some
other) before calling __dentry_kill(). That eliminates the window when
shrink_dcache_parent() would've blown past the entire subtree without
noticing anything with zero refcount not on shrink lists.
2) when shrink_dcache_parent() has found no eviction candidates,
but some dentries are still sitting on shrink lists, rather than
repeating the scan in hope that shrinkers have progressed, scan looking
for something on shrink lists with zero refcount. If such a thing is
found, grab rcu_read_lock() and stop the scan, with caller locking
it for eviction, dropping out of RCU and doing __dentry_kill(), with
the same treatment for parent as shrink_dentry_list() would do.
Note that right now mixed-filesystem shrink lists do not occur, so this
is not a mainline bug. Howevere, there's a bunch of uses for such
beasts (e.g. the "try and evict everything we can out of given page"
patches; there are potential uses in mount-related code, considerably
simplifying the life in fs/namespace.c, etc.)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2019-06-29 22:31:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!list_empty(&data.dispose))
|
|
|
|
shrink_dentry_list(&data.dispose);
|
fs/dcache.c: add cond_resched() to shrink_dcache_parent()
Call cond_resched() in shrink_dcache_parent() to maintain interactivity.
Before this patch:
void shrink_dcache_parent(struct dentry * parent)
{
while ((found = select_parent(parent, &dispose)) != 0)
shrink_dentry_list(&dispose);
}
select_parent() populates the dispose list with dentries which
shrink_dentry_list() then deletes. select_parent() carefully uses
need_resched() to avoid doing too much work at once. But neither
shrink_dcache_parent() nor its called functions call cond_resched(). So
once need_resched() is set select_parent() will return single dentry
dispose list which is then deleted by shrink_dentry_list(). This is
inefficient when there are a lot of dentry to process. This can cause
softlockup and hurts interactivity on non preemptable kernels.
This change adds cond_resched() in shrink_dcache_parent(). The benefit
of this is that need_resched() is quickly cleared so that future calls
to select_parent() are able to efficiently return a big batch of dentry.
These additional cond_resched() do not seem to impact performance, at
least for the workload below.
Here is a program which can cause soft lockup if other system activity
sets need_resched().
int main()
{
struct rlimit rlim;
int i;
int f[100000];
char buf[20];
struct timeval t1, t2;
double diff;
/* cleanup past run */
system("rm -rf x");
/* boost nfile rlimit */
rlim.rlim_cur = 200000;
rlim.rlim_max = 200000;
if (setrlimit(RLIMIT_NOFILE, &rlim))
err(1, "setrlimit");
/* make directory for files */
if (mkdir("x", 0700))
err(1, "mkdir");
if (gettimeofday(&t1, NULL))
err(1, "gettimeofday");
/* populate directory with open files */
for (i = 0; i < 100000; i++) {
snprintf(buf, sizeof(buf), "x/%d", i);
f[i] = open(buf, O_CREAT);
if (f[i] == -1)
err(1, "open");
}
/* close some of the files */
for (i = 0; i < 85000; i++)
close(f[i]);
/* unlink all files, even open ones */
system("rm -rf x");
if (gettimeofday(&t2, NULL))
err(1, "gettimeofday");
diff = (((double)t2.tv_sec * 1000000 + t2.tv_usec) -
((double)t1.tv_sec * 1000000 + t1.tv_usec));
printf("done: %g elapsed\n", diff/1e6);
return 0;
}
Signed-off-by: Greg Thelen <gthelen@google.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2013-04-30 22:26:48 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2010-01-05 20:45:18 +00:00
|
|
|
EXPORT_SYMBOL(shrink_dcache_parent);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2014-05-03 00:36:10 +00:00
|
|
|
static enum d_walk_ret umount_check(void *_data, struct dentry *dentry)
|
2013-11-08 17:31:16 +00:00
|
|
|
{
|
2014-05-03 00:36:10 +00:00
|
|
|
/* it has busy descendents; complain about those instead */
|
2023-11-07 07:00:39 +00:00
|
|
|
if (!hlist_empty(&dentry->d_children))
|
2014-05-03 00:36:10 +00:00
|
|
|
return D_WALK_CONTINUE;
|
2013-11-08 17:31:16 +00:00
|
|
|
|
2014-05-03 00:36:10 +00:00
|
|
|
/* root with refcount 1 is fine */
|
|
|
|
if (dentry == _data && dentry->d_lockref.count == 1)
|
|
|
|
return D_WALK_CONTINUE;
|
|
|
|
|
2023-08-17 16:31:42 +00:00
|
|
|
WARN(1, "BUG: Dentry %p{i=%lx,n=%pd} "
|
2014-05-03 00:36:10 +00:00
|
|
|
" still in use (%d) [unmount of %s %s]\n",
|
2013-11-08 17:31:16 +00:00
|
|
|
dentry,
|
|
|
|
dentry->d_inode ?
|
|
|
|
dentry->d_inode->i_ino : 0UL,
|
2014-05-03 00:36:10 +00:00
|
|
|
dentry,
|
2013-11-08 17:31:16 +00:00
|
|
|
dentry->d_lockref.count,
|
|
|
|
dentry->d_sb->s_type->name,
|
|
|
|
dentry->d_sb->s_id);
|
2014-05-03 00:36:10 +00:00
|
|
|
return D_WALK_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_one_tree(struct dentry *dentry)
|
|
|
|
{
|
|
|
|
shrink_dcache_parent(dentry);
|
2018-04-15 22:27:23 +00:00
|
|
|
d_walk(dentry, dentry, umount_check);
|
2014-05-03 00:36:10 +00:00
|
|
|
d_drop(dentry);
|
|
|
|
dput(dentry);
|
2013-11-08 17:31:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* destroy the dentries attached to a superblock on unmounting
|
|
|
|
*/
|
|
|
|
void shrink_dcache_for_umount(struct super_block *sb)
|
|
|
|
{
|
|
|
|
struct dentry *dentry;
|
|
|
|
|
2024-06-02 12:37:19 +00:00
|
|
|
rwsem_assert_held_write(&sb->s_umount);
|
2013-11-08 17:31:16 +00:00
|
|
|
|
|
|
|
dentry = sb->s_root;
|
|
|
|
sb->s_root = NULL;
|
2014-05-03 00:36:10 +00:00
|
|
|
do_one_tree(dentry);
|
2013-11-08 17:31:16 +00:00
|
|
|
|
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 75a6f82a0d10 ("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 <neilb@suse.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2017-12-20 22:45:40 +00:00
|
|
|
while (!hlist_bl_empty(&sb->s_roots)) {
|
|
|
|
dentry = dget(hlist_bl_entry(hlist_bl_first(&sb->s_roots), struct dentry, d_hash));
|
2014-05-03 00:36:10 +00:00
|
|
|
do_one_tree(dentry);
|
2013-11-08 17:31:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-15 22:21:47 +00:00
|
|
|
static enum d_walk_ret find_submount(void *_data, struct dentry *dentry)
|
2013-09-05 09:44:36 +00:00
|
|
|
{
|
2018-04-15 22:21:47 +00:00
|
|
|
struct dentry **victim = _data;
|
2013-09-05 09:44:36 +00:00
|
|
|
if (d_mountpoint(dentry)) {
|
2023-11-06 13:44:17 +00:00
|
|
|
*victim = dget_dlock(dentry);
|
2013-09-05 09:44:36 +00:00
|
|
|
return D_WALK_QUIT;
|
|
|
|
}
|
2018-04-15 22:21:47 +00:00
|
|
|
return D_WALK_CONTINUE;
|
2013-09-05 09:44:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2014-02-13 17:39:37 +00:00
|
|
|
* d_invalidate - detach submounts, prune dcache, and drop
|
|
|
|
* @dentry: dentry to invalidate (aka detach, prune and drop)
|
2013-09-05 09:44:36 +00:00
|
|
|
*/
|
2014-02-13 17:46:25 +00:00
|
|
|
void d_invalidate(struct dentry *dentry)
|
2013-09-05 09:44:36 +00:00
|
|
|
{
|
2018-04-15 22:21:47 +00:00
|
|
|
bool had_submounts = false;
|
2014-02-13 17:39:37 +00:00
|
|
|
spin_lock(&dentry->d_lock);
|
|
|
|
if (d_unhashed(dentry)) {
|
|
|
|
spin_unlock(&dentry->d_lock);
|
2014-02-13 17:46:25 +00:00
|
|
|
return;
|
2014-02-13 17:39:37 +00:00
|
|
|
}
|
2018-04-15 22:21:47 +00:00
|
|
|
__d_drop(dentry);
|
2014-02-13 17:39:37 +00:00
|
|
|
spin_unlock(&dentry->d_lock);
|
|
|
|
|
2013-09-05 09:44:36 +00:00
|
|
|
/* Negative dentries can be dropped without further checks */
|
2018-04-15 22:21:47 +00:00
|
|
|
if (!dentry->d_inode)
|
2014-02-13 17:46:25 +00:00
|
|
|
return;
|
2013-09-05 09:44:36 +00:00
|
|
|
|
2018-04-15 22:21:47 +00:00
|
|
|
shrink_dcache_parent(dentry);
|
2013-09-05 09:44:36 +00:00
|
|
|
for (;;) {
|
2018-04-15 22:21:47 +00:00
|
|
|
struct dentry *victim = NULL;
|
2018-04-15 22:27:23 +00:00
|
|
|
d_walk(dentry, &victim, find_submount);
|
2018-04-15 22:21:47 +00:00
|
|
|
if (!victim) {
|
|
|
|
if (had_submounts)
|
|
|
|
shrink_dcache_parent(dentry);
|
2017-06-03 06:20:09 +00:00
|
|
|
return;
|
vfs: Lazily remove mounts on unlinked files and directories.
With the introduction of mount namespaces and bind mounts it became
possible to access files and directories that on some paths are mount
points but are not mount points on other paths. It is very confusing
when rm -rf somedir returns -EBUSY simply because somedir is mounted
somewhere else. With the addition of user namespaces allowing
unprivileged mounts this condition has gone from annoying to allowing
a DOS attack on other users in the system.
The possibility for mischief is removed by updating the vfs to support
rename, unlink and rmdir on a dentry that is a mountpoint and by
lazily unmounting mountpoints on deleted dentries.
In particular this change allows rename, unlink and rmdir system calls
on a dentry without a mountpoint in the current mount namespace to
succeed, and it allows rename, unlink, and rmdir performed on a
distributed filesystem to update the vfs cache even if when there is a
mount in some namespace on the original dentry.
There are two common patterns of maintaining mounts: Mounts on trusted
paths with the parent directory of the mount point and all ancestory
directories up to / owned by root and modifiable only by root
(i.e. /media/xxx, /dev, /dev/pts, /proc, /sys, /sys/fs/cgroup/{cpu,
cpuacct, ...}, /usr, /usr/local). Mounts on unprivileged directories
maintained by fusermount.
In the case of mounts in trusted directories owned by root and
modifiable only by root the current parent directory permissions are
sufficient to ensure a mount point on a trusted path is not removed
or renamed by anyone other than root, even if there is a context
where the there are no mount points to prevent this.
In the case of mounts in directories owned by less privileged users
races with users modifying the path of a mount point are already a
danger. fusermount already uses a combination of chdir,
/proc/<pid>/fd/NNN, and UMOUNT_NOFOLLOW to prevent these races. The
removable of global rename, unlink, and rmdir protection really adds
nothing new to consider only a widening of the attack window, and
fusermount is already safe against unprivileged users modifying the
directory simultaneously.
In principle for perfect userspace programs returning -EBUSY for
unlink, rmdir, and rename of dentires that have mounts in the local
namespace is actually unnecessary. Unfortunately not all userspace
programs are perfect so retaining -EBUSY for unlink, rmdir and rename
of dentries that have mounts in the current mount namespace plays an
important role of maintaining consistency with historical behavior and
making imperfect userspace applications hard to exploit.
v2: Remove spurious old_dentry.
v3: Optimized shrink_submounts_and_drop
Removed unsued afs label
v4: Simplified the changes to check_submounts_and_drop
Do not rename check_submounts_and_drop shrink_submounts_and_drop
Document what why we need atomicity in check_submounts_and_drop
Rely on the parent inode mutex to make d_revalidate and d_invalidate
an atomic unit.
v5: Refcount the mountpoint to detach in case of simultaneous
renames.
Reviewed-by: Miklos Szeredi <miklos@szeredi.hu>
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2013-10-02 01:33:48 +00:00
|
|
|
}
|
2018-04-15 22:21:47 +00:00
|
|
|
had_submounts = true;
|
|
|
|
detach_mounts(victim);
|
|
|
|
dput(victim);
|
2013-09-05 09:44:36 +00:00
|
|
|
}
|
|
|
|
}
|
2014-02-13 17:39:37 +00:00
|
|
|
EXPORT_SYMBOL(d_invalidate);
|
2013-09-05 09:44:36 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/**
|
2011-07-07 19:03:58 +00:00
|
|
|
* __d_alloc - allocate a dcache entry
|
|
|
|
* @sb: filesystem it will belong to
|
2005-04-16 22:20:36 +00:00
|
|
|
* @name: qstr of the name
|
|
|
|
*
|
|
|
|
* Allocates a dentry. It returns %NULL if there is insufficient memory
|
|
|
|
* available. On a success the dentry is returned. The name passed in is
|
|
|
|
* copied and the copy passed in may be reused after this call.
|
|
|
|
*/
|
|
|
|
|
2019-10-25 18:08:24 +00:00
|
|
|
static struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
struct dentry *dentry;
|
|
|
|
char *dname;
|
2016-06-28 09:47:32 +00:00
|
|
|
int err;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2022-03-22 21:41:09 +00:00
|
|
|
dentry = kmem_cache_alloc_lru(dentry_cache, &sb->s_dentry_lru,
|
|
|
|
GFP_KERNEL);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (!dentry)
|
|
|
|
return NULL;
|
|
|
|
|
2012-05-21 23:14:04 +00:00
|
|
|
/*
|
|
|
|
* We guarantee that the inline name is always NUL-terminated.
|
|
|
|
* This way the memcpy() done by the name switching in rename
|
|
|
|
* will still always have a NUL at the end, even if we might
|
|
|
|
* be overwriting an internal NUL character
|
|
|
|
*/
|
|
|
|
dentry->d_iname[DNAME_INLINE_LEN-1] = 0;
|
2016-03-25 00:38:43 +00:00
|
|
|
if (unlikely(!name)) {
|
2017-07-04 16:25:22 +00:00
|
|
|
name = &slash_name;
|
2016-03-25 00:38:43 +00:00
|
|
|
dname = dentry->d_iname;
|
|
|
|
} else if (name->len > DNAME_INLINE_LEN-1) {
|
Allow sharing external names after __d_move()
* external dentry names get a small structure prepended to them
(struct external_name).
* it contains an atomic refcount, matching the number of struct dentry
instances that have ->d_name.name pointing to that external name. The
first thing free_dentry() does is decrementing refcount of external name,
so the instances that are between the call of free_dentry() and
RCU-delayed actual freeing do not contribute.
* __d_move(x, y, false) makes the name of x equal to the name of y,
external or not. If y has an external name, extra reference is grabbed
and put into x->d_name.name. If x used to have an external name, the
reference to the old name is dropped and, should it reach zero, freeing
is scheduled via kfree_rcu().
* free_dentry() in dentry with external name decrements the refcount of
that name and, should it reach zero, does RCU-delayed call that will
free both the dentry and external name. Otherwise it does what it
used to do, except that __d_free() doesn't even look at ->d_name.name;
it simply frees the dentry.
All non-RCU accesses to dentry external name are safe wrt freeing since they
all should happen before free_dentry() is called. RCU accesses might run
into a dentry seen by free_dentry() or into an old name that got already
dropped by __d_move(); however, in both cases dentry must have been
alive and refer to that name at some point after we'd done rcu_read_lock(),
which means that any freeing must be still pending.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2014-09-29 18:54:27 +00:00
|
|
|
size_t size = offsetof(struct external_name, name[1]);
|
2018-10-26 22:05:41 +00:00
|
|
|
struct external_name *p = kmalloc(size + name->len,
|
|
|
|
GFP_KERNEL_ACCOUNT |
|
|
|
|
__GFP_RECLAIMABLE);
|
|
|
|
if (!p) {
|
2005-04-16 22:20:36 +00:00
|
|
|
kmem_cache_free(dentry_cache, dentry);
|
|
|
|
return NULL;
|
|
|
|
}
|
2018-10-26 22:05:41 +00:00
|
|
|
atomic_set(&p->u.count, 1);
|
|
|
|
dname = p->name;
|
2005-04-16 22:20:36 +00:00
|
|
|
} else {
|
|
|
|
dname = dentry->d_iname;
|
|
|
|
}
|
|
|
|
|
|
|
|
dentry->d_name.len = name->len;
|
|
|
|
dentry->d_name.hash = name->hash;
|
|
|
|
memcpy(dname, name->name, name->len);
|
|
|
|
dname[name->len] = 0;
|
|
|
|
|
2012-05-21 23:14:04 +00:00
|
|
|
/* Make sure we always see the terminating NUL character */
|
2017-10-09 17:04:27 +00:00
|
|
|
smp_store_release(&dentry->d_name.name, dname); /* ^^^ */
|
2012-05-21 23:14:04 +00:00
|
|
|
|
2013-08-29 01:24:59 +00:00
|
|
|
dentry->d_lockref.count = 1;
|
vfs: get rid of insane dentry hashing rules
The dentry hashing rules have been really quite complicated for a long
while, in odd ways. That made functions like __d_drop() very fragile
and non-obvious.
In particular, whether a dentry was hashed or not was indicated with an
explicit DCACHE_UNHASHED bit. That's despite the fact that the hash
abstraction that the dentries use actually have a 'is this entry hashed
or not' model (which is a simple test of the 'pprev' pointer).
The reason that was done is because we used the normal 'is this entry
unhashed' model to mark whether the dentry had _ever_ been hashed in the
dentry hash tables, and that logic goes back many years (commit
b3423415fbc2: "dcache: avoid RCU for never-hashed dentries").
That, in turn, meant that __d_drop had totally different unhashing logic
for the dentry hash table case and for the anonymous dcache case,
because in order to use the "is this dentry hashed" logic as a flag for
whether it had ever been on the RCU hash table, we had to unhash such a
dentry differently so that we'd never think that it wasn't 'unhashed'
and wouldn't be free'd correctly.
That's just insane. It made the logic really hard to follow, when there
were two different kinds of "unhashed" states, and one of them (the one
that used "list_bl_unhashed()") really had nothing at all to do with
being unhashed per se, but with a very subtle lifetime rule instead.
So turn all of it around, and make it logical.
Instead of having a DENTRY_UNHASHED bit in d_flags to indicate whether
the dentry is on the hash chains or not, use the hash chain unhashed
logic for that. Suddenly "d_unhashed()" just uses "list_bl_unhashed()",
and everything makes sense.
And for the lifetime rule, just use an explicit DENTRY_RCUACCEES bit.
If we ever insert the dentry into the dentry hash table so that it is
visible to RCU lookup, we mark it DENTRY_RCUACCESS to show that it now
needs the RCU lifetime rules. Now suddently that test at dentry free
time makes sense too.
And because unhashing now is sane and doesn't depend on where the dentry
got unhashed from (because the dentry hash chain details doesn't have
some subtle side effects), we can re-unify the __d_drop() logic and use
common code for the unhashing.
Also fix one more open-coded hash chain bit_spin_lock() that I missed in
the previous chain locking cleanup commit.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-04-24 14:58:46 +00:00
|
|
|
dentry->d_flags = 0;
|
2005-04-16 22:20:36 +00:00
|
|
|
spin_lock_init(&dentry->d_lock);
|
2020-07-20 15:55:24 +00:00
|
|
|
seqcount_spinlock_init(&dentry->d_seq, &dentry->d_lock);
|
2005-04-16 22:20:36 +00:00
|
|
|
dentry->d_inode = NULL;
|
2011-07-07 19:03:58 +00:00
|
|
|
dentry->d_parent = dentry;
|
|
|
|
dentry->d_sb = sb;
|
2005-04-16 22:20:36 +00:00
|
|
|
dentry->d_op = NULL;
|
|
|
|
dentry->d_fsdata = NULL;
|
2011-01-07 06:50:05 +00:00
|
|
|
INIT_HLIST_BL_NODE(&dentry->d_hash);
|
2005-04-16 22:20:36 +00:00
|
|
|
INIT_LIST_HEAD(&dentry->d_lru);
|
2023-11-07 07:00:39 +00:00
|
|
|
INIT_HLIST_HEAD(&dentry->d_children);
|
2014-10-26 23:19:16 +00:00
|
|
|
INIT_HLIST_NODE(&dentry->d_u.d_alias);
|
2023-11-07 07:00:39 +00:00
|
|
|
INIT_HLIST_NODE(&dentry->d_sib);
|
2011-07-07 19:03:58 +00:00
|
|
|
d_set_d_op(dentry, dentry->d_sb->s_d_op);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2016-06-28 09:47:32 +00:00
|
|
|
if (dentry->d_op && dentry->d_op->d_init) {
|
|
|
|
err = dentry->d_op->d_init(dentry);
|
|
|
|
if (err) {
|
|
|
|
if (dname_external(dentry))
|
|
|
|
kfree(external_name(dentry));
|
|
|
|
kmem_cache_free(dentry_cache, dentry);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
fs: use fast counters for vfs caches
percpu_counter library generates quite nasty code, so unless you need
to dynamically allocate counters or take fast approximate value, a
simple per cpu set of counters is much better.
The percpu_counter can never be made to work as well, because it has an
indirection from pointer to percpu memory, and it can't use direct
this_cpu_inc interfaces because it doesn't use static PER_CPU data, so
code will always be worse.
In the fastpath, it is the difference between this:
incl %gs:nr_dentry # nr_dentry
and this:
movl percpu_counter_batch(%rip), %edx # percpu_counter_batch,
movl $1, %esi #,
movq $nr_dentry, %rdi #,
call __percpu_counter_add # (plus I clobber registers)
__percpu_counter_add:
pushq %rbp #
movq %rsp, %rbp #,
subq $32, %rsp #,
movq %rbx, -24(%rbp) #,
movq %r12, -16(%rbp) #,
movq %r13, -8(%rbp) #,
movq %rdi, %rbx # fbc, fbc
#APP
# 216 "/home/npiggin/usr/src/linux-2.6/arch/x86/include/asm/thread_info.h" 1
movq %gs:kernel_stack,%rax #, pfo_ret__
# 0 "" 2
#NO_APP
incl -8124(%rax) # <variable>.preempt_count
movq 32(%rdi), %r12 # <variable>.counters, tcp_ptr__
#APP
# 78 "lib/percpu_counter.c" 1
add %gs:this_cpu_off, %r12 # this_cpu_off, tcp_ptr__
# 0 "" 2
#NO_APP
movslq (%r12),%r13 #* tcp_ptr__, tmp73
movslq %edx,%rax # batch, batch
addq %rsi, %r13 # amount, count
cmpq %rax, %r13 # batch, count
jge .L27 #,
negl %edx # tmp76
movslq %edx,%rdx # tmp76, tmp77
cmpq %rdx, %r13 # tmp77, count
jg .L28 #,
.L27:
movq %rbx, %rdi # fbc,
call _raw_spin_lock #
addq %r13, 8(%rbx) # count, <variable>.count
movq %rbx, %rdi # fbc,
movl $0, (%r12) #,* tcp_ptr__
call _raw_spin_unlock #
.L29:
#APP
# 216 "/home/npiggin/usr/src/linux-2.6/arch/x86/include/asm/thread_info.h" 1
movq %gs:kernel_stack,%rax #, pfo_ret__
# 0 "" 2
#NO_APP
decl -8124(%rax) # <variable>.preempt_count
movq -8136(%rax), %rax #, D.14625
testb $8, %al #, D.14625
jne .L32 #,
.L31:
movq -24(%rbp), %rbx #,
movq -16(%rbp), %r12 #,
movq -8(%rbp), %r13 #,
leave
ret
.p2align 4,,10
.p2align 3
.L28:
movl %r13d, (%r12) # count,*
jmp .L29 #
.L32:
call preempt_schedule #
.p2align 4,,6
jmp .L31 #
.size __percpu_counter_add, .-__percpu_counter_add
.p2align 4,,15
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:19 +00:00
|
|
|
this_cpu_inc(nr_dentry);
|
2010-10-10 09:36:23 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
return dentry;
|
|
|
|
}
|
2011-07-07 19:03:58 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* d_alloc - allocate a dcache entry
|
|
|
|
* @parent: parent of entry to allocate
|
|
|
|
* @name: qstr of the name
|
|
|
|
*
|
|
|
|
* Allocates a dentry. It returns %NULL if there is insufficient memory
|
|
|
|
* available. On a success the dentry is returned. The name passed in is
|
|
|
|
* copied and the copy passed in may be reused after this call.
|
|
|
|
*/
|
|
|
|
struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
|
|
|
|
{
|
|
|
|
struct dentry *dentry = __d_alloc(parent->d_sb, name);
|
|
|
|
if (!dentry)
|
|
|
|
return NULL;
|
|
|
|
spin_lock(&parent->d_lock);
|
|
|
|
/*
|
|
|
|
* don't need child lock because it is not subject
|
|
|
|
* to concurrency here
|
|
|
|
*/
|
2023-11-06 13:44:17 +00:00
|
|
|
dentry->d_parent = dget_dlock(parent);
|
2023-11-07 07:00:39 +00:00
|
|
|
hlist_add_head(&dentry->d_sib, &parent->d_children);
|
2011-07-07 19:03:58 +00:00
|
|
|
spin_unlock(&parent->d_lock);
|
|
|
|
|
|
|
|
return dentry;
|
|
|
|
}
|
2010-01-05 20:45:18 +00:00
|
|
|
EXPORT_SYMBOL(d_alloc);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2018-01-19 10:39:52 +00:00
|
|
|
struct dentry *d_alloc_anon(struct super_block *sb)
|
|
|
|
{
|
|
|
|
return __d_alloc(sb, NULL);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(d_alloc_anon);
|
|
|
|
|
2016-06-10 15:32:47 +00:00
|
|
|
struct dentry *d_alloc_cursor(struct dentry * parent)
|
|
|
|
{
|
2018-01-19 10:39:52 +00:00
|
|
|
struct dentry *dentry = d_alloc_anon(parent->d_sb);
|
2016-06-10 15:32:47 +00:00
|
|
|
if (dentry) {
|
dcache: sort the freeing-without-RCU-delay mess for good.
For lockless accesses to dentries we don't have pinned we rely
(among other things) upon having an RCU delay between dropping
the last reference and actually freeing the memory.
On the other hand, for things like pipes and sockets we neither
do that kind of lockless access, nor want to deal with the
overhead of an RCU delay every time a socket gets closed.
So delay was made optional - setting DCACHE_RCUACCESS in ->d_flags
made sure it would happen. We tried to avoid setting it unless
we knew we need it. Unfortunately, that had led to recurring
class of bugs, in which we missed the need to set it.
We only really need it for dentries that are created by
d_alloc_pseudo(), so let's not bother with trying to be smart -
just make having an RCU delay the default. The ones that do
*not* get it set the replacement flag (DCACHE_NORCU) and we'd
better use that sparingly. d_alloc_pseudo() is the only
such user right now.
FWIW, the race that finally prompted that switch had been
between __lock_parent() of immediate subdirectory of what's
currently the root of a disconnected tree (e.g. from
open-by-handle in progress) racing with d_splice_alias()
elsewhere picking another alias for the same inode, either
on outright corrupted fs image, or (in case of open-by-handle
on NFS) that subdirectory having been just moved on server.
It's not easy to hit, so the sky is not falling, but that's
not the first race on similar missed cases and the logics
for settinf DCACHE_RCUACCESS has gotten ridiculously
convoluted.
Cc: stable@vger.kernel.org
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2019-03-16 02:23:19 +00:00
|
|
|
dentry->d_flags |= DCACHE_DENTRY_CURSOR;
|
2016-06-10 15:32:47 +00:00
|
|
|
dentry->d_parent = dget(parent);
|
|
|
|
}
|
|
|
|
return dentry;
|
|
|
|
}
|
|
|
|
|
2012-06-29 20:20:47 +00:00
|
|
|
/**
|
|
|
|
* d_alloc_pseudo - allocate a dentry (for lookup-less filesystems)
|
|
|
|
* @sb: the superblock
|
|
|
|
* @name: qstr of the name
|
|
|
|
*
|
|
|
|
* For a filesystem that just pins its dentries in memory and never
|
|
|
|
* performs lookups at all, return an unhashed IS_ROOT dentry.
|
dcache: sort the freeing-without-RCU-delay mess for good.
For lockless accesses to dentries we don't have pinned we rely
(among other things) upon having an RCU delay between dropping
the last reference and actually freeing the memory.
On the other hand, for things like pipes and sockets we neither
do that kind of lockless access, nor want to deal with the
overhead of an RCU delay every time a socket gets closed.
So delay was made optional - setting DCACHE_RCUACCESS in ->d_flags
made sure it would happen. We tried to avoid setting it unless
we knew we need it. Unfortunately, that had led to recurring
class of bugs, in which we missed the need to set it.
We only really need it for dentries that are created by
d_alloc_pseudo(), so let's not bother with trying to be smart -
just make having an RCU delay the default. The ones that do
*not* get it set the replacement flag (DCACHE_NORCU) and we'd
better use that sparingly. d_alloc_pseudo() is the only
such user right now.
FWIW, the race that finally prompted that switch had been
between __lock_parent() of immediate subdirectory of what's
currently the root of a disconnected tree (e.g. from
open-by-handle in progress) racing with d_splice_alias()
elsewhere picking another alias for the same inode, either
on outright corrupted fs image, or (in case of open-by-handle
on NFS) that subdirectory having been just moved on server.
It's not easy to hit, so the sky is not falling, but that's
not the first race on similar missed cases and the logics
for settinf DCACHE_RCUACCESS has gotten ridiculously
convoluted.
Cc: stable@vger.kernel.org
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2019-03-16 02:23:19 +00:00
|
|
|
* This is used for pipes, sockets et.al. - the stuff that should
|
|
|
|
* never be anyone's children or parents. Unlike all other
|
|
|
|
* dentries, these will not have RCU delay between dropping the
|
|
|
|
* last reference and freeing them.
|
2019-03-16 02:58:11 +00:00
|
|
|
*
|
|
|
|
* The only user is alloc_file_pseudo() and that's what should
|
|
|
|
* be considered a public interface. Don't use directly.
|
2012-06-29 20:20:47 +00:00
|
|
|
*/
|
2011-01-07 06:50:07 +00:00
|
|
|
struct dentry *d_alloc_pseudo(struct super_block *sb, const struct qstr *name)
|
|
|
|
{
|
2023-11-12 05:04:46 +00:00
|
|
|
static const struct dentry_operations anon_ops = {
|
|
|
|
.d_dname = simple_dname
|
|
|
|
};
|
dcache: sort the freeing-without-RCU-delay mess for good.
For lockless accesses to dentries we don't have pinned we rely
(among other things) upon having an RCU delay between dropping
the last reference and actually freeing the memory.
On the other hand, for things like pipes and sockets we neither
do that kind of lockless access, nor want to deal with the
overhead of an RCU delay every time a socket gets closed.
So delay was made optional - setting DCACHE_RCUACCESS in ->d_flags
made sure it would happen. We tried to avoid setting it unless
we knew we need it. Unfortunately, that had led to recurring
class of bugs, in which we missed the need to set it.
We only really need it for dentries that are created by
d_alloc_pseudo(), so let's not bother with trying to be smart -
just make having an RCU delay the default. The ones that do
*not* get it set the replacement flag (DCACHE_NORCU) and we'd
better use that sparingly. d_alloc_pseudo() is the only
such user right now.
FWIW, the race that finally prompted that switch had been
between __lock_parent() of immediate subdirectory of what's
currently the root of a disconnected tree (e.g. from
open-by-handle in progress) racing with d_splice_alias()
elsewhere picking another alias for the same inode, either
on outright corrupted fs image, or (in case of open-by-handle
on NFS) that subdirectory having been just moved on server.
It's not easy to hit, so the sky is not falling, but that's
not the first race on similar missed cases and the logics
for settinf DCACHE_RCUACCESS has gotten ridiculously
convoluted.
Cc: stable@vger.kernel.org
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2019-03-16 02:23:19 +00:00
|
|
|
struct dentry *dentry = __d_alloc(sb, name);
|
2023-11-12 05:04:46 +00:00
|
|
|
if (likely(dentry)) {
|
dcache: sort the freeing-without-RCU-delay mess for good.
For lockless accesses to dentries we don't have pinned we rely
(among other things) upon having an RCU delay between dropping
the last reference and actually freeing the memory.
On the other hand, for things like pipes and sockets we neither
do that kind of lockless access, nor want to deal with the
overhead of an RCU delay every time a socket gets closed.
So delay was made optional - setting DCACHE_RCUACCESS in ->d_flags
made sure it would happen. We tried to avoid setting it unless
we knew we need it. Unfortunately, that had led to recurring
class of bugs, in which we missed the need to set it.
We only really need it for dentries that are created by
d_alloc_pseudo(), so let's not bother with trying to be smart -
just make having an RCU delay the default. The ones that do
*not* get it set the replacement flag (DCACHE_NORCU) and we'd
better use that sparingly. d_alloc_pseudo() is the only
such user right now.
FWIW, the race that finally prompted that switch had been
between __lock_parent() of immediate subdirectory of what's
currently the root of a disconnected tree (e.g. from
open-by-handle in progress) racing with d_splice_alias()
elsewhere picking another alias for the same inode, either
on outright corrupted fs image, or (in case of open-by-handle
on NFS) that subdirectory having been just moved on server.
It's not easy to hit, so the sky is not falling, but that's
not the first race on similar missed cases and the logics
for settinf DCACHE_RCUACCESS has gotten ridiculously
convoluted.
Cc: stable@vger.kernel.org
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2019-03-16 02:23:19 +00:00
|
|
|
dentry->d_flags |= DCACHE_NORCU;
|
2023-11-12 05:04:46 +00:00
|
|
|
if (!sb->s_d_op)
|
|
|
|
d_set_d_op(dentry, &anon_ops);
|
|
|
|
}
|
dcache: sort the freeing-without-RCU-delay mess for good.
For lockless accesses to dentries we don't have pinned we rely
(among other things) upon having an RCU delay between dropping
the last reference and actually freeing the memory.
On the other hand, for things like pipes and sockets we neither
do that kind of lockless access, nor want to deal with the
overhead of an RCU delay every time a socket gets closed.
So delay was made optional - setting DCACHE_RCUACCESS in ->d_flags
made sure it would happen. We tried to avoid setting it unless
we knew we need it. Unfortunately, that had led to recurring
class of bugs, in which we missed the need to set it.
We only really need it for dentries that are created by
d_alloc_pseudo(), so let's not bother with trying to be smart -
just make having an RCU delay the default. The ones that do
*not* get it set the replacement flag (DCACHE_NORCU) and we'd
better use that sparingly. d_alloc_pseudo() is the only
such user right now.
FWIW, the race that finally prompted that switch had been
between __lock_parent() of immediate subdirectory of what's
currently the root of a disconnected tree (e.g. from
open-by-handle in progress) racing with d_splice_alias()
elsewhere picking another alias for the same inode, either
on outright corrupted fs image, or (in case of open-by-handle
on NFS) that subdirectory having been just moved on server.
It's not easy to hit, so the sky is not falling, but that's
not the first race on similar missed cases and the logics
for settinf DCACHE_RCUACCESS has gotten ridiculously
convoluted.
Cc: stable@vger.kernel.org
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2019-03-16 02:23:19 +00:00
|
|
|
return dentry;
|
2011-01-07 06:50:07 +00:00
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
struct dentry *d_alloc_name(struct dentry *parent, const char *name)
|
|
|
|
{
|
|
|
|
struct qstr q;
|
|
|
|
|
|
|
|
q.name = name;
|
2016-06-10 14:51:30 +00:00
|
|
|
q.hash_len = hashlen_string(parent, name);
|
2005-04-16 22:20:36 +00:00
|
|
|
return d_alloc(parent, &q);
|
|
|
|
}
|
2009-09-30 00:09:42 +00:00
|
|
|
EXPORT_SYMBOL(d_alloc_name);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2011-01-07 06:49:55 +00:00
|
|
|
void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
|
|
|
|
{
|
2011-01-14 21:26:18 +00:00
|
|
|
WARN_ON_ONCE(dentry->d_op);
|
|
|
|
WARN_ON_ONCE(dentry->d_flags & (DCACHE_OP_HASH |
|
2011-01-07 06:49:55 +00:00
|
|
|
DCACHE_OP_COMPARE |
|
|
|
|
DCACHE_OP_REVALIDATE |
|
2013-02-20 16:19:05 +00:00
|
|
|
DCACHE_OP_WEAK_REVALIDATE |
|
2015-06-18 13:32:31 +00:00
|
|
|
DCACHE_OP_DELETE |
|
2016-03-26 20:14:37 +00:00
|
|
|
DCACHE_OP_REAL));
|
2011-01-07 06:49:55 +00:00
|
|
|
dentry->d_op = op;
|
|
|
|
if (!op)
|
|
|
|
return;
|
|
|
|
if (op->d_hash)
|
|
|
|
dentry->d_flags |= DCACHE_OP_HASH;
|
|
|
|
if (op->d_compare)
|
|
|
|
dentry->d_flags |= DCACHE_OP_COMPARE;
|
|
|
|
if (op->d_revalidate)
|
|
|
|
dentry->d_flags |= DCACHE_OP_REVALIDATE;
|
2013-02-20 16:19:05 +00:00
|
|
|
if (op->d_weak_revalidate)
|
|
|
|
dentry->d_flags |= DCACHE_OP_WEAK_REVALIDATE;
|
2011-01-07 06:49:55 +00:00
|
|
|
if (op->d_delete)
|
|
|
|
dentry->d_flags |= DCACHE_OP_DELETE;
|
2011-10-28 17:02:42 +00:00
|
|
|
if (op->d_prune)
|
|
|
|
dentry->d_flags |= DCACHE_OP_PRUNE;
|
2016-03-26 20:14:37 +00:00
|
|
|
if (op->d_real)
|
|
|
|
dentry->d_flags |= DCACHE_OP_REAL;
|
2011-01-07 06:49:55 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(d_set_d_op);
|
|
|
|
|
2013-09-12 18:22:53 +00:00
|
|
|
static unsigned d_flags_for_inode(struct inode *inode)
|
|
|
|
{
|
2015-01-29 12:02:29 +00:00
|
|
|
unsigned add_flags = DCACHE_REGULAR_TYPE;
|
2013-09-12 18:22:53 +00:00
|
|
|
|
|
|
|
if (!inode)
|
|
|
|
return DCACHE_MISS_TYPE;
|
|
|
|
|
|
|
|
if (S_ISDIR(inode->i_mode)) {
|
|
|
|
add_flags = DCACHE_DIRECTORY_TYPE;
|
|
|
|
if (unlikely(!(inode->i_opflags & IOP_LOOKUP))) {
|
|
|
|
if (unlikely(!inode->i_op->lookup))
|
|
|
|
add_flags = DCACHE_AUTODIR_TYPE;
|
|
|
|
else
|
|
|
|
inode->i_opflags |= IOP_LOOKUP;
|
|
|
|
}
|
2015-01-29 12:02:29 +00:00
|
|
|
goto type_determined;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (unlikely(!(inode->i_opflags & IOP_NOFOLLOW))) {
|
2015-11-17 15:20:54 +00:00
|
|
|
if (unlikely(inode->i_op->get_link)) {
|
2013-09-12 18:22:53 +00:00
|
|
|
add_flags = DCACHE_SYMLINK_TYPE;
|
2015-01-29 12:02:29 +00:00
|
|
|
goto type_determined;
|
|
|
|
}
|
|
|
|
inode->i_opflags |= IOP_NOFOLLOW;
|
2013-09-12 18:22:53 +00:00
|
|
|
}
|
|
|
|
|
2015-01-29 12:02:29 +00:00
|
|
|
if (unlikely(!S_ISREG(inode->i_mode)))
|
|
|
|
add_flags = DCACHE_SPECIAL_TYPE;
|
|
|
|
|
|
|
|
type_determined:
|
2013-09-12 18:22:53 +00:00
|
|
|
if (unlikely(IS_AUTOMOUNT(inode)))
|
|
|
|
add_flags |= DCACHE_NEED_AUTOMOUNT;
|
|
|
|
return add_flags;
|
|
|
|
}
|
|
|
|
|
2008-10-15 22:50:28 +00:00
|
|
|
static void __d_instantiate(struct dentry *dentry, struct inode *inode)
|
|
|
|
{
|
2013-09-12 18:22:53 +00:00
|
|
|
unsigned add_flags = d_flags_for_inode(inode);
|
2016-04-14 23:52:13 +00:00
|
|
|
WARN_ON(d_in_lookup(dentry));
|
2013-09-12 18:22:53 +00:00
|
|
|
|
2011-01-07 06:49:35 +00:00
|
|
|
spin_lock(&dentry->d_lock);
|
2019-01-30 18:52:38 +00:00
|
|
|
/*
|
vfs: don't mod negative dentry count when on shrinker list
The nr_dentry_negative counter is intended to only account negative
dentries that are present on the superblock LRU. Therefore, the LRU
add, remove and isolate helpers modify the counter based on whether
the dentry is negative, but the shrinker list related helpers do not
modify the counter, and the paths that change a dentry between
positive and negative only do so if DCACHE_LRU_LIST is set.
The problem with this is that a dentry on a shrinker list still has
DCACHE_LRU_LIST set to indicate ->d_lru is in use. The additional
DCACHE_SHRINK_LIST flag denotes whether the dentry is on LRU or a
shrink related list. Therefore if a relevant operation (i.e. unlink)
occurs while a dentry is present on a shrinker list, and the
associated codepath only checks for DCACHE_LRU_LIST, then it is
technically possible to modify the negative dentry count for a
dentry that is off the LRU. Since the shrinker list related helpers
do not modify the negative dentry count (because non-LRU dentries
should not be included in the count) when the dentry is ultimately
removed from the shrinker list, this can cause the negative dentry
count to become permanently inaccurate.
This problem can be reproduced via a heavy file create/unlink vs.
drop_caches workload. On an 80xcpu system, I start 80 tasks each
running a 1k file create/delete loop, and one task spinning on
drop_caches. After 10 minutes or so of runtime, the idle/clean cache
negative dentry count increases from somewhere in the range of 5-10
entries to several hundred (and increasingly grows beyond
nr_dentry_unused).
Tweak the logic in the paths that turn a dentry negative or positive
to filter out the case where the dentry is present on a shrink
related list. This allows the above workload to maintain an accurate
negative dentry count.
Fixes: af0c9af1b3f6 ("fs/dcache: Track & report number of negative dentries")
Signed-off-by: Brian Foster <bfoster@redhat.com>
Link: https://lore.kernel.org/r/20240703121301.247680-1-bfoster@redhat.com
Acked-by: Ian Kent <ikent@redhat.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: Waiman Long <longman@redhat.com>
Signed-off-by: Christian Brauner <brauner@kernel.org>
2024-07-03 12:13:01 +00:00
|
|
|
* The negative counter only tracks dentries on the LRU. Don't dec if
|
|
|
|
* d_lru is on another list.
|
2019-01-30 18:52:38 +00:00
|
|
|
*/
|
vfs: don't mod negative dentry count when on shrinker list
The nr_dentry_negative counter is intended to only account negative
dentries that are present on the superblock LRU. Therefore, the LRU
add, remove and isolate helpers modify the counter based on whether
the dentry is negative, but the shrinker list related helpers do not
modify the counter, and the paths that change a dentry between
positive and negative only do so if DCACHE_LRU_LIST is set.
The problem with this is that a dentry on a shrinker list still has
DCACHE_LRU_LIST set to indicate ->d_lru is in use. The additional
DCACHE_SHRINK_LIST flag denotes whether the dentry is on LRU or a
shrink related list. Therefore if a relevant operation (i.e. unlink)
occurs while a dentry is present on a shrinker list, and the
associated codepath only checks for DCACHE_LRU_LIST, then it is
technically possible to modify the negative dentry count for a
dentry that is off the LRU. Since the shrinker list related helpers
do not modify the negative dentry count (because non-LRU dentries
should not be included in the count) when the dentry is ultimately
removed from the shrinker list, this can cause the negative dentry
count to become permanently inaccurate.
This problem can be reproduced via a heavy file create/unlink vs.
drop_caches workload. On an 80xcpu system, I start 80 tasks each
running a 1k file create/delete loop, and one task spinning on
drop_caches. After 10 minutes or so of runtime, the idle/clean cache
negative dentry count increases from somewhere in the range of 5-10
entries to several hundred (and increasingly grows beyond
nr_dentry_unused).
Tweak the logic in the paths that turn a dentry negative or positive
to filter out the case where the dentry is present on a shrink
related list. This allows the above workload to maintain an accurate
negative dentry count.
Fixes: af0c9af1b3f6 ("fs/dcache: Track & report number of negative dentries")
Signed-off-by: Brian Foster <bfoster@redhat.com>
Link: https://lore.kernel.org/r/20240703121301.247680-1-bfoster@redhat.com
Acked-by: Ian Kent <ikent@redhat.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: Waiman Long <longman@redhat.com>
Signed-off-by: Christian Brauner <brauner@kernel.org>
2024-07-03 12:13:01 +00:00
|
|
|
if ((dentry->d_flags &
|
|
|
|
(DCACHE_LRU_LIST|DCACHE_SHRINK_LIST)) == DCACHE_LRU_LIST)
|
2019-01-30 18:52:38 +00:00
|
|
|
this_cpu_dec(nr_dentry_negative);
|
2016-03-09 23:05:42 +00:00
|
|
|
hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry);
|
2016-02-29 17:12:46 +00:00
|
|
|
raw_write_seqcount_begin(&dentry->d_seq);
|
2015-03-05 14:09:22 +00:00
|
|
|
__d_set_inode_and_type(dentry, inode, add_flags);
|
2016-02-29 17:12:46 +00:00
|
|
|
raw_write_seqcount_end(&dentry->d_seq);
|
2016-05-29 22:35:12 +00:00
|
|
|
fsnotify_update_flags(dentry);
|
2011-01-07 06:49:35 +00:00
|
|
|
spin_unlock(&dentry->d_lock);
|
2008-10-15 22:50:28 +00:00
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/**
|
|
|
|
* d_instantiate - fill in inode information for a dentry
|
|
|
|
* @entry: dentry to complete
|
|
|
|
* @inode: inode to attach to this dentry
|
|
|
|
*
|
|
|
|
* Fill in inode information in the entry.
|
|
|
|
*
|
|
|
|
* This turns negative dentries into productive full members
|
|
|
|
* of society.
|
|
|
|
*
|
|
|
|
* NOTE! This assumes that the inode count has been incremented
|
|
|
|
* (or otherwise set) by the caller to indicate that it is now
|
|
|
|
* in use by the dcache.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void d_instantiate(struct dentry *entry, struct inode * inode)
|
|
|
|
{
|
2014-10-26 23:19:16 +00:00
|
|
|
BUG_ON(!hlist_unhashed(&entry->d_u.d_alias));
|
2016-03-09 23:05:42 +00:00
|
|
|
if (inode) {
|
2016-04-11 04:53:26 +00:00
|
|
|
security_d_instantiate(entry, inode);
|
2011-01-07 06:50:06 +00:00
|
|
|
spin_lock(&inode->i_lock);
|
2016-03-09 23:05:42 +00:00
|
|
|
__d_instantiate(entry, inode);
|
2011-01-07 06:50:06 +00:00
|
|
|
spin_unlock(&inode->i_lock);
|
2016-03-09 23:05:42 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2010-01-05 20:45:18 +00:00
|
|
|
EXPORT_SYMBOL(d_instantiate);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2018-05-04 12:23:01 +00:00
|
|
|
/*
|
|
|
|
* This should be equivalent to d_instantiate() + unlock_new_inode(),
|
|
|
|
* with lockdep-related part of unlock_new_inode() done before
|
|
|
|
* anything else. Use that instead of open-coding d_instantiate()/
|
|
|
|
* unlock_new_inode() combinations.
|
|
|
|
*/
|
|
|
|
void d_instantiate_new(struct dentry *entry, struct inode *inode)
|
|
|
|
{
|
|
|
|
BUG_ON(!hlist_unhashed(&entry->d_u.d_alias));
|
|
|
|
BUG_ON(!inode);
|
|
|
|
lockdep_annotate_inode_mutex_key(inode);
|
|
|
|
security_d_instantiate(entry, inode);
|
|
|
|
spin_lock(&inode->i_lock);
|
|
|
|
__d_instantiate(entry, inode);
|
|
|
|
WARN_ON(!(inode->i_state & I_NEW));
|
2018-06-28 19:53:17 +00:00
|
|
|
inode->i_state &= ~I_NEW & ~I_CREATING;
|
2024-08-23 12:47:38 +00:00
|
|
|
/*
|
|
|
|
* Pairs with the barrier in prepare_to_wait_event() to make sure
|
|
|
|
* ___wait_var_event() either sees the bit cleared or
|
|
|
|
* waitqueue_active() check in wake_up_var() sees the waiter.
|
|
|
|
*/
|
2018-05-04 12:23:01 +00:00
|
|
|
smp_mb();
|
2024-08-23 12:47:38 +00:00
|
|
|
inode_wake_up_bit(inode, __I_NEW);
|
2018-05-04 12:23:01 +00:00
|
|
|
spin_unlock(&inode->i_lock);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(d_instantiate_new);
|
|
|
|
|
2012-01-08 21:49:21 +00:00
|
|
|
struct dentry *d_make_root(struct inode *root_inode)
|
|
|
|
{
|
|
|
|
struct dentry *res = NULL;
|
|
|
|
|
|
|
|
if (root_inode) {
|
2018-01-19 10:39:52 +00:00
|
|
|
res = d_alloc_anon(root_inode->i_sb);
|
dcache: sort the freeing-without-RCU-delay mess for good.
For lockless accesses to dentries we don't have pinned we rely
(among other things) upon having an RCU delay between dropping
the last reference and actually freeing the memory.
On the other hand, for things like pipes and sockets we neither
do that kind of lockless access, nor want to deal with the
overhead of an RCU delay every time a socket gets closed.
So delay was made optional - setting DCACHE_RCUACCESS in ->d_flags
made sure it would happen. We tried to avoid setting it unless
we knew we need it. Unfortunately, that had led to recurring
class of bugs, in which we missed the need to set it.
We only really need it for dentries that are created by
d_alloc_pseudo(), so let's not bother with trying to be smart -
just make having an RCU delay the default. The ones that do
*not* get it set the replacement flag (DCACHE_NORCU) and we'd
better use that sparingly. d_alloc_pseudo() is the only
such user right now.
FWIW, the race that finally prompted that switch had been
between __lock_parent() of immediate subdirectory of what's
currently the root of a disconnected tree (e.g. from
open-by-handle in progress) racing with d_splice_alias()
elsewhere picking another alias for the same inode, either
on outright corrupted fs image, or (in case of open-by-handle
on NFS) that subdirectory having been just moved on server.
It's not easy to hit, so the sky is not falling, but that's
not the first race on similar missed cases and the logics
for settinf DCACHE_RCUACCESS has gotten ridiculously
convoluted.
Cc: stable@vger.kernel.org
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2019-03-16 02:23:19 +00:00
|
|
|
if (res)
|
2012-01-08 21:49:21 +00:00
|
|
|
d_instantiate(res, root_inode);
|
dcache: sort the freeing-without-RCU-delay mess for good.
For lockless accesses to dentries we don't have pinned we rely
(among other things) upon having an RCU delay between dropping
the last reference and actually freeing the memory.
On the other hand, for things like pipes and sockets we neither
do that kind of lockless access, nor want to deal with the
overhead of an RCU delay every time a socket gets closed.
So delay was made optional - setting DCACHE_RCUACCESS in ->d_flags
made sure it would happen. We tried to avoid setting it unless
we knew we need it. Unfortunately, that had led to recurring
class of bugs, in which we missed the need to set it.
We only really need it for dentries that are created by
d_alloc_pseudo(), so let's not bother with trying to be smart -
just make having an RCU delay the default. The ones that do
*not* get it set the replacement flag (DCACHE_NORCU) and we'd
better use that sparingly. d_alloc_pseudo() is the only
such user right now.
FWIW, the race that finally prompted that switch had been
between __lock_parent() of immediate subdirectory of what's
currently the root of a disconnected tree (e.g. from
open-by-handle in progress) racing with d_splice_alias()
elsewhere picking another alias for the same inode, either
on outright corrupted fs image, or (in case of open-by-handle
on NFS) that subdirectory having been just moved on server.
It's not easy to hit, so the sky is not falling, but that's
not the first race on similar missed cases and the logics
for settinf DCACHE_RCUACCESS has gotten ridiculously
convoluted.
Cc: stable@vger.kernel.org
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2019-03-16 02:23:19 +00:00
|
|
|
else
|
2012-01-08 21:49:21 +00:00
|
|
|
iput(root_inode);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(d_make_root);
|
|
|
|
|
2018-01-19 10:39:52 +00:00
|
|
|
static struct dentry *__d_obtain_alias(struct inode *inode, bool disconnected)
|
|
|
|
{
|
2023-11-18 21:42:43 +00:00
|
|
|
struct super_block *sb;
|
|
|
|
struct dentry *new, *res;
|
2018-01-19 10:39:52 +00:00
|
|
|
|
|
|
|
if (!inode)
|
|
|
|
return ERR_PTR(-ESTALE);
|
|
|
|
if (IS_ERR(inode))
|
|
|
|
return ERR_CAST(inode);
|
|
|
|
|
2023-11-18 21:42:43 +00:00
|
|
|
sb = inode->i_sb;
|
|
|
|
|
|
|
|
res = d_find_any_alias(inode); /* existing alias? */
|
2018-01-19 10:39:52 +00:00
|
|
|
if (res)
|
2023-11-18 21:42:43 +00:00
|
|
|
goto out;
|
2018-01-19 10:39:52 +00:00
|
|
|
|
2023-11-18 21:42:43 +00:00
|
|
|
new = d_alloc_anon(sb);
|
|
|
|
if (!new) {
|
2018-01-19 10:39:52 +00:00
|
|
|
res = ERR_PTR(-ENOMEM);
|
2023-11-18 21:42:43 +00:00
|
|
|
goto out;
|
2018-01-19 10:39:52 +00:00
|
|
|
}
|
|
|
|
|
2023-11-18 21:42:43 +00:00
|
|
|
security_d_instantiate(new, inode);
|
|
|
|
spin_lock(&inode->i_lock);
|
|
|
|
res = __d_find_any_alias(inode); /* recheck under lock */
|
|
|
|
if (likely(!res)) { /* still no alias, attach a disconnected dentry */
|
|
|
|
unsigned add_flags = d_flags_for_inode(inode);
|
|
|
|
|
|
|
|
if (disconnected)
|
|
|
|
add_flags |= DCACHE_DISCONNECTED;
|
2018-01-19 10:39:52 +00:00
|
|
|
|
2023-11-18 21:42:43 +00:00
|
|
|
spin_lock(&new->d_lock);
|
|
|
|
__d_set_inode_and_type(new, inode, add_flags);
|
|
|
|
hlist_add_head(&new->d_u.d_alias, &inode->i_dentry);
|
|
|
|
if (!disconnected) {
|
|
|
|
hlist_bl_lock(&sb->s_roots);
|
|
|
|
hlist_bl_add_head(&new->d_hash, &sb->s_roots);
|
|
|
|
hlist_bl_unlock(&sb->s_roots);
|
|
|
|
}
|
|
|
|
spin_unlock(&new->d_lock);
|
|
|
|
spin_unlock(&inode->i_lock);
|
|
|
|
inode = NULL; /* consumed by new->d_inode */
|
|
|
|
res = new;
|
|
|
|
} else {
|
|
|
|
spin_unlock(&inode->i_lock);
|
|
|
|
dput(new);
|
|
|
|
}
|
2018-01-19 10:39:52 +00:00
|
|
|
|
2023-11-18 21:42:43 +00:00
|
|
|
out:
|
2018-01-19 10:39:52 +00:00
|
|
|
iput(inode);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2014-02-14 22:35:37 +00:00
|
|
|
/**
|
|
|
|
* d_obtain_alias - find or allocate a DISCONNECTED dentry for a given inode
|
|
|
|
* @inode: inode to allocate the dentry for
|
|
|
|
*
|
|
|
|
* Obtain a dentry for an inode resulting from NFS filehandle conversion or
|
|
|
|
* similar open by handle operations. The returned dentry may be anonymous,
|
|
|
|
* or may have a full name (if the inode was already in the cache).
|
|
|
|
*
|
|
|
|
* When called on a directory inode, we must ensure that the inode only ever
|
|
|
|
* has one dentry. If a dentry is found, that is returned instead of
|
|
|
|
* allocating a new one.
|
|
|
|
*
|
|
|
|
* On successful return, the reference to the inode has been transferred
|
|
|
|
* to the dentry. In case of an error the reference on the inode is released.
|
|
|
|
* To make it easier to use in export operations a %NULL or IS_ERR inode may
|
|
|
|
* be passed in and the error will be propagated to the return value,
|
|
|
|
* with a %NULL @inode replaced by ERR_PTR(-ESTALE).
|
|
|
|
*/
|
|
|
|
struct dentry *d_obtain_alias(struct inode *inode)
|
|
|
|
{
|
2018-01-19 10:39:52 +00:00
|
|
|
return __d_obtain_alias(inode, true);
|
2014-02-14 22:35:37 +00:00
|
|
|
}
|
2009-02-27 22:02:59 +00:00
|
|
|
EXPORT_SYMBOL(d_obtain_alias);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2014-02-14 22:35:37 +00:00
|
|
|
/**
|
|
|
|
* d_obtain_root - find or allocate a dentry for a given inode
|
|
|
|
* @inode: inode to allocate the dentry for
|
|
|
|
*
|
|
|
|
* Obtain an IS_ROOT dentry for the root of a filesystem.
|
|
|
|
*
|
|
|
|
* We must ensure that directory inodes only ever have one dentry. If a
|
|
|
|
* dentry is found, that is returned instead of allocating a new one.
|
|
|
|
*
|
|
|
|
* On successful return, the reference to the inode has been transferred
|
|
|
|
* to the dentry. In case of an error the reference on the inode is
|
|
|
|
* released. A %NULL or IS_ERR inode may be passed in and will be the
|
|
|
|
* error will be propagate to the return value, with a %NULL @inode
|
|
|
|
* replaced by ERR_PTR(-ESTALE).
|
|
|
|
*/
|
|
|
|
struct dentry *d_obtain_root(struct inode *inode)
|
|
|
|
{
|
2018-01-19 10:39:52 +00:00
|
|
|
return __d_obtain_alias(inode, false);
|
2014-02-14 22:35:37 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(d_obtain_root);
|
|
|
|
|
2008-05-21 06:50:46 +00:00
|
|
|
/**
|
|
|
|
* d_add_ci - lookup or allocate new dentry with case-exact name
|
|
|
|
* @inode: the inode case-insensitive lookup has found
|
|
|
|
* @dentry: the negative dentry that was passed to the parent's lookup func
|
|
|
|
* @name: the case-exact name to be associated with the returned dentry
|
|
|
|
*
|
|
|
|
* This is to avoid filling the dcache with case-insensitive names to the
|
|
|
|
* same inode, only the actual correct case is stored in the dcache for
|
|
|
|
* case-insensitive filesystems.
|
|
|
|
*
|
2021-02-24 20:00:48 +00:00
|
|
|
* For a case-insensitive lookup match and if the case-exact dentry
|
|
|
|
* already exists in the dcache, use it and return it.
|
2008-05-21 06:50:46 +00:00
|
|
|
*
|
|
|
|
* If no entry exists with the exact case name, allocate new dentry with
|
|
|
|
* the exact case, and return the spliced entry.
|
|
|
|
*/
|
2008-08-07 21:49:07 +00:00
|
|
|
struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode,
|
2008-05-21 06:50:46 +00:00
|
|
|
struct qstr *name)
|
|
|
|
{
|
2016-04-15 07:33:13 +00:00
|
|
|
struct dentry *found, *res;
|
2008-05-21 06:50:46 +00:00
|
|
|
|
2009-01-05 18:10:37 +00:00
|
|
|
/*
|
|
|
|
* First check if a dentry matching the name already exists,
|
|
|
|
* if not go ahead and create it now.
|
|
|
|
*/
|
2008-05-21 06:50:46 +00:00
|
|
|
found = d_hash_and_lookup(dentry->d_parent, name);
|
2016-04-15 07:33:13 +00:00
|
|
|
if (found) {
|
|
|
|
iput(inode);
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
if (d_in_lookup(dentry)) {
|
|
|
|
found = d_alloc_parallel(dentry->d_parent, name,
|
|
|
|
dentry->d_wait);
|
|
|
|
if (IS_ERR(found) || !d_in_lookup(found)) {
|
|
|
|
iput(inode);
|
|
|
|
return found;
|
2008-05-21 06:50:46 +00:00
|
|
|
}
|
2016-04-15 07:33:13 +00:00
|
|
|
} else {
|
|
|
|
found = d_alloc(dentry->d_parent, name);
|
|
|
|
if (!found) {
|
|
|
|
iput(inode);
|
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
res = d_splice_alias(inode, found);
|
|
|
|
if (res) {
|
2022-07-30 04:29:05 +00:00
|
|
|
d_lookup_done(found);
|
2016-04-15 07:33:13 +00:00
|
|
|
dput(found);
|
|
|
|
return res;
|
2008-05-21 06:50:46 +00:00
|
|
|
}
|
2013-02-12 04:20:37 +00:00
|
|
|
return found;
|
2008-05-21 06:50:46 +00:00
|
|
|
}
|
2010-01-05 20:45:18 +00:00
|
|
|
EXPORT_SYMBOL(d_add_ci);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2022-05-16 03:23:19 +00:00
|
|
|
/**
|
|
|
|
* d_same_name - compare dentry name with case-exact name
|
|
|
|
* @parent: parent dentry
|
|
|
|
* @dentry: the negative dentry that was passed to the parent's lookup func
|
|
|
|
* @name: the case-exact name to be associated with the returned dentry
|
|
|
|
*
|
|
|
|
* Return: true if names are same, or false
|
|
|
|
*/
|
|
|
|
bool d_same_name(const struct dentry *dentry, const struct dentry *parent,
|
|
|
|
const struct qstr *name)
|
vfs: clean up __d_lookup_rcu() and dentry_cmp() interfaces
The calling conventions for __d_lookup_rcu() and dentry_cmp() are
annoying in different ways, and there is actually one single underlying
reason for both of the annoyances.
The fundamental reason is that we do the returned dentry sequence number
check inside __d_lookup_rcu() instead of doing it in the caller. This
results in two annoyances:
- __d_lookup_rcu() now not only needs to return the dentry and the
sequence number that goes along with the lookup, it also needs to
return the inode pointer that was validated by that sequence number
check.
- and because we did the sequence number check early (to validate the
name pointer and length) we also couldn't just pass the dentry itself
to dentry_cmp(), we had to pass the counted string that contained the
name.
So that sequence number decision caused two separate ugly calling
conventions.
Both of these problems would be solved if we just did the sequence
number check in the caller instead. There's only one caller, and that
caller already has to do the sequence number check for the parent
anyway, so just do that.
That allows us to stop returning the dentry->d_inode in that in-out
argument (pointer-to-pointer-to-inode), so we can make the inode
argument just a regular input inode pointer. The caller can just load
the inode from dentry->d_inode, and then do the sequence number check
after that to make sure that it's synchronized with the name we looked
up.
And it allows us to just pass in the dentry to dentry_cmp(), which is
what all the callers really wanted. Sure, dentry_cmp() has to be a bit
careful about the dentry (which is not stable during RCU lookup), but
that's actually very simple.
And now that dentry_cmp() can clearly see that the first string argument
is a dentry, we can use the direct word access for that, instead of the
careful unaligned zero-padding. The dentry name is always properly
aligned, since it is a single path component that is either embedded
into the dentry itself, or was allocated with kmalloc() (see __d_alloc).
Finally, this also uninlines the nasty slow-case for dentry comparisons:
that one *does* need to do a sequence number check, since it will call
in to the low-level filesystems, and we want to give those a stable
inode pointer and path component length/start arguments. Doing an extra
sequence check for that slow case is not a problem, though.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-05-04 21:59:14 +00:00
|
|
|
{
|
2016-06-26 03:33:49 +00:00
|
|
|
if (likely(!(parent->d_flags & DCACHE_OP_COMPARE))) {
|
|
|
|
if (dentry->d_name.len != name->len)
|
|
|
|
return false;
|
|
|
|
return dentry_cmp(dentry, name->name, name->len) == 0;
|
vfs: clean up __d_lookup_rcu() and dentry_cmp() interfaces
The calling conventions for __d_lookup_rcu() and dentry_cmp() are
annoying in different ways, and there is actually one single underlying
reason for both of the annoyances.
The fundamental reason is that we do the returned dentry sequence number
check inside __d_lookup_rcu() instead of doing it in the caller. This
results in two annoyances:
- __d_lookup_rcu() now not only needs to return the dentry and the
sequence number that goes along with the lookup, it also needs to
return the inode pointer that was validated by that sequence number
check.
- and because we did the sequence number check early (to validate the
name pointer and length) we also couldn't just pass the dentry itself
to dentry_cmp(), we had to pass the counted string that contained the
name.
So that sequence number decision caused two separate ugly calling
conventions.
Both of these problems would be solved if we just did the sequence
number check in the caller instead. There's only one caller, and that
caller already has to do the sequence number check for the parent
anyway, so just do that.
That allows us to stop returning the dentry->d_inode in that in-out
argument (pointer-to-pointer-to-inode), so we can make the inode
argument just a regular input inode pointer. The caller can just load
the inode from dentry->d_inode, and then do the sequence number check
after that to make sure that it's synchronized with the name we looked
up.
And it allows us to just pass in the dentry to dentry_cmp(), which is
what all the callers really wanted. Sure, dentry_cmp() has to be a bit
careful about the dentry (which is not stable during RCU lookup), but
that's actually very simple.
And now that dentry_cmp() can clearly see that the first string argument
is a dentry, we can use the direct word access for that, instead of the
careful unaligned zero-padding. The dentry name is always properly
aligned, since it is a single path component that is either embedded
into the dentry itself, or was allocated with kmalloc() (see __d_alloc).
Finally, this also uninlines the nasty slow-case for dentry comparisons:
that one *does* need to do a sequence number check, since it will call
in to the low-level filesystems, and we want to give those a stable
inode pointer and path component length/start arguments. Doing an extra
sequence check for that slow case is not a problem, though.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-05-04 21:59:14 +00:00
|
|
|
}
|
2016-07-31 20:37:25 +00:00
|
|
|
return parent->d_op->d_compare(dentry,
|
2016-06-26 03:33:49 +00:00
|
|
|
dentry->d_name.len, dentry->d_name.name,
|
|
|
|
name) == 0;
|
vfs: clean up __d_lookup_rcu() and dentry_cmp() interfaces
The calling conventions for __d_lookup_rcu() and dentry_cmp() are
annoying in different ways, and there is actually one single underlying
reason for both of the annoyances.
The fundamental reason is that we do the returned dentry sequence number
check inside __d_lookup_rcu() instead of doing it in the caller. This
results in two annoyances:
- __d_lookup_rcu() now not only needs to return the dentry and the
sequence number that goes along with the lookup, it also needs to
return the inode pointer that was validated by that sequence number
check.
- and because we did the sequence number check early (to validate the
name pointer and length) we also couldn't just pass the dentry itself
to dentry_cmp(), we had to pass the counted string that contained the
name.
So that sequence number decision caused two separate ugly calling
conventions.
Both of these problems would be solved if we just did the sequence
number check in the caller instead. There's only one caller, and that
caller already has to do the sequence number check for the parent
anyway, so just do that.
That allows us to stop returning the dentry->d_inode in that in-out
argument (pointer-to-pointer-to-inode), so we can make the inode
argument just a regular input inode pointer. The caller can just load
the inode from dentry->d_inode, and then do the sequence number check
after that to make sure that it's synchronized with the name we looked
up.
And it allows us to just pass in the dentry to dentry_cmp(), which is
what all the callers really wanted. Sure, dentry_cmp() has to be a bit
careful about the dentry (which is not stable during RCU lookup), but
that's actually very simple.
And now that dentry_cmp() can clearly see that the first string argument
is a dentry, we can use the direct word access for that, instead of the
careful unaligned zero-padding. The dentry name is always properly
aligned, since it is a single path component that is either embedded
into the dentry itself, or was allocated with kmalloc() (see __d_alloc).
Finally, this also uninlines the nasty slow-case for dentry comparisons:
that one *does* need to do a sequence number check, since it will call
in to the low-level filesystems, and we want to give those a stable
inode pointer and path component length/start arguments. Doing an extra
sequence check for that slow case is not a problem, though.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-05-04 21:59:14 +00:00
|
|
|
}
|
2022-05-16 03:23:19 +00:00
|
|
|
EXPORT_SYMBOL_GPL(d_same_name);
|
vfs: clean up __d_lookup_rcu() and dentry_cmp() interfaces
The calling conventions for __d_lookup_rcu() and dentry_cmp() are
annoying in different ways, and there is actually one single underlying
reason for both of the annoyances.
The fundamental reason is that we do the returned dentry sequence number
check inside __d_lookup_rcu() instead of doing it in the caller. This
results in two annoyances:
- __d_lookup_rcu() now not only needs to return the dentry and the
sequence number that goes along with the lookup, it also needs to
return the inode pointer that was validated by that sequence number
check.
- and because we did the sequence number check early (to validate the
name pointer and length) we also couldn't just pass the dentry itself
to dentry_cmp(), we had to pass the counted string that contained the
name.
So that sequence number decision caused two separate ugly calling
conventions.
Both of these problems would be solved if we just did the sequence
number check in the caller instead. There's only one caller, and that
caller already has to do the sequence number check for the parent
anyway, so just do that.
That allows us to stop returning the dentry->d_inode in that in-out
argument (pointer-to-pointer-to-inode), so we can make the inode
argument just a regular input inode pointer. The caller can just load
the inode from dentry->d_inode, and then do the sequence number check
after that to make sure that it's synchronized with the name we looked
up.
And it allows us to just pass in the dentry to dentry_cmp(), which is
what all the callers really wanted. Sure, dentry_cmp() has to be a bit
careful about the dentry (which is not stable during RCU lookup), but
that's actually very simple.
And now that dentry_cmp() can clearly see that the first string argument
is a dentry, we can use the direct word access for that, instead of the
careful unaligned zero-padding. The dentry name is always properly
aligned, since it is a single path component that is either embedded
into the dentry itself, or was allocated with kmalloc() (see __d_alloc).
Finally, this also uninlines the nasty slow-case for dentry comparisons:
that one *does* need to do a sequence number check, since it will call
in to the low-level filesystems, and we want to give those a stable
inode pointer and path component length/start arguments. Doing an extra
sequence check for that slow case is not a problem, though.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-05-04 21:59:14 +00:00
|
|
|
|
2022-08-11 22:29:46 +00:00
|
|
|
/*
|
|
|
|
* This is __d_lookup_rcu() when the parent dentry has
|
|
|
|
* DCACHE_OP_COMPARE, which makes things much nastier.
|
|
|
|
*/
|
|
|
|
static noinline struct dentry *__d_lookup_rcu_op_compare(
|
|
|
|
const struct dentry *parent,
|
|
|
|
const struct qstr *name,
|
|
|
|
unsigned *seqp)
|
|
|
|
{
|
|
|
|
u64 hashlen = name->hash_len;
|
vfs: dcache: move hashlen_hash() from callers into d_hash()
Both __d_lookup_rcu() and __d_lookup_rcu_op_compare() have the full
'name_hash' value of the qstr that they want to look up, and mask it off
to just the low 32-bit hash before calling down to d_hash().
Other callers just load the 32-bit hash and pass it as the argument.
If we move the masking into d_hash() itself, it simplifies the two
callers that currently do the masking, and is a no-op for the other
cases. It doesn't actually change the generated code since the compiler
will inline d_hash() and see that the end result is the same.
[ Technically, since the parse tree changes, the code generation may not
be 100% the same, and for me on x86-64, this does result in gcc
switching the operands around for one 'cmpl' instruction. So not
necessarily the exact same code generation, but equivalent ]
However, this does encapsulate the 'd_hash()' operation more, and makes
the shift operation in particular be a "shift 32 bits right, return full
word". Which matches the instruction semantics on both x86-64 and arm64
better, since a 32-bit shift will clear the upper bits.
That makes the next step of introducing a "shift by runtime constant"
more obvious and generates the shift with no extraneous type masking.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2024-06-10 18:47:06 +00:00
|
|
|
struct hlist_bl_head *b = d_hash(hashlen);
|
2022-08-11 22:29:46 +00:00
|
|
|
struct hlist_bl_node *node;
|
|
|
|
struct dentry *dentry;
|
|
|
|
|
|
|
|
hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) {
|
|
|
|
int tlen;
|
|
|
|
const char *tname;
|
|
|
|
unsigned seq;
|
|
|
|
|
|
|
|
seqretry:
|
|
|
|
seq = raw_seqcount_begin(&dentry->d_seq);
|
|
|
|
if (dentry->d_parent != parent)
|
|
|
|
continue;
|
|
|
|
if (d_unhashed(dentry))
|
|
|
|
continue;
|
|
|
|
if (dentry->d_name.hash != hashlen_hash(hashlen))
|
|
|
|
continue;
|
|
|
|
tlen = dentry->d_name.len;
|
|
|
|
tname = dentry->d_name.name;
|
|
|
|
/* we want a consistent (name,len) pair */
|
|
|
|
if (read_seqcount_retry(&dentry->d_seq, seq)) {
|
|
|
|
cpu_relax();
|
|
|
|
goto seqretry;
|
|
|
|
}
|
|
|
|
if (parent->d_op->d_compare(dentry, tlen, tname, name) != 0)
|
|
|
|
continue;
|
|
|
|
*seqp = seq;
|
|
|
|
return dentry;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
fs: rcu-walk for path lookup
Perform common cases of path lookups without any stores or locking in the
ancestor dentry elements. This is called rcu-walk, as opposed to the current
algorithm which is a refcount based walk, or ref-walk.
This results in far fewer atomic operations on every path element,
significantly improving path lookup performance. It also avoids cacheline
bouncing on common dentries, significantly improving scalability.
The overall design is like this:
* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
* Take the RCU lock for the entire path walk, starting with the acquiring
of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
not required for dentry persistence.
* synchronize_rcu is called when unregistering a filesystem, so we can
access d_ops and i_ops during rcu-walk.
* Similarly take the vfsmount lock for the entire path walk. So now mnt
refcounts are not required for persistence. Also we are free to perform mount
lookups, and to assume dentry mount points and mount roots are stable up and
down the path.
* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
so we can load this tuple atomically, and also check whether any of its
members have changed.
* Dentry lookups (based on parent, candidate string tuple) recheck the parent
sequence after the child is found in case anything changed in the parent
during the path walk.
* inode is also RCU protected so we can load d_inode and use the inode for
limited things.
* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
* i_op can be loaded.
When we reach the destination dentry, we lock it, recheck lookup sequence,
and increment its refcount and mountpoint refcount. RCU and vfsmount locks
are dropped. This is termed "dropping rcu-walk". If the dentry refcount does
not match, we can not drop rcu-walk gracefully at the current point in the
lokup, so instead return -ECHILD (for want of a better errno). This signals the
path walking code to re-do the entire lookup with a ref-walk.
Aside from the final dentry, there are other situations that may be encounted
where we cannot continue rcu-walk. In that case, we drop rcu-walk (ie. take
a reference on the last good dentry) and continue with a ref-walk. Again, if
we can drop rcu-walk gracefully, we return -ECHILD and do the whole lookup
using ref-walk. But it is very important that we can continue with ref-walk
for most cases, particularly to avoid the overhead of double lookups, and to
gain the scalability advantages on common path elements (like cwd and root).
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links
In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:52 +00:00
|
|
|
/**
|
|
|
|
* __d_lookup_rcu - search for a dentry (racy, store-free)
|
|
|
|
* @parent: parent dentry
|
|
|
|
* @name: qstr of name we wish to find
|
2012-03-19 04:23:05 +00:00
|
|
|
* @seqp: returns d_seq value at the point where the dentry was found
|
fs: rcu-walk for path lookup
Perform common cases of path lookups without any stores or locking in the
ancestor dentry elements. This is called rcu-walk, as opposed to the current
algorithm which is a refcount based walk, or ref-walk.
This results in far fewer atomic operations on every path element,
significantly improving path lookup performance. It also avoids cacheline
bouncing on common dentries, significantly improving scalability.
The overall design is like this:
* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
* Take the RCU lock for the entire path walk, starting with the acquiring
of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
not required for dentry persistence.
* synchronize_rcu is called when unregistering a filesystem, so we can
access d_ops and i_ops during rcu-walk.
* Similarly take the vfsmount lock for the entire path walk. So now mnt
refcounts are not required for persistence. Also we are free to perform mount
lookups, and to assume dentry mount points and mount roots are stable up and
down the path.
* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
so we can load this tuple atomically, and also check whether any of its
members have changed.
* Dentry lookups (based on parent, candidate string tuple) recheck the parent
sequence after the child is found in case anything changed in the parent
during the path walk.
* inode is also RCU protected so we can load d_inode and use the inode for
limited things.
* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
* i_op can be loaded.
When we reach the destination dentry, we lock it, recheck lookup sequence,
and increment its refcount and mountpoint refcount. RCU and vfsmount locks
are dropped. This is termed "dropping rcu-walk". If the dentry refcount does
not match, we can not drop rcu-walk gracefully at the current point in the
lokup, so instead return -ECHILD (for want of a better errno). This signals the
path walking code to re-do the entire lookup with a ref-walk.
Aside from the final dentry, there are other situations that may be encounted
where we cannot continue rcu-walk. In that case, we drop rcu-walk (ie. take
a reference on the last good dentry) and continue with a ref-walk. Again, if
we can drop rcu-walk gracefully, we return -ECHILD and do the whole lookup
using ref-walk. But it is very important that we can continue with ref-walk
for most cases, particularly to avoid the overhead of double lookups, and to
gain the scalability advantages on common path elements (like cwd and root).
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links
In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:52 +00:00
|
|
|
* Returns: dentry, or NULL
|
|
|
|
*
|
|
|
|
* __d_lookup_rcu is the dcache lookup function for rcu-walk name
|
|
|
|
* resolution (store-free path walking) design described in
|
|
|
|
* Documentation/filesystems/path-lookup.txt.
|
|
|
|
*
|
|
|
|
* This is not to be used outside core vfs.
|
|
|
|
*
|
|
|
|
* __d_lookup_rcu must only be used in rcu-walk mode, ie. with vfsmount lock
|
|
|
|
* held, and rcu_read_lock held. The returned dentry must not be stored into
|
|
|
|
* without taking d_lock and checking d_seq sequence count against @seq
|
|
|
|
* returned here.
|
|
|
|
*
|
|
|
|
* Alternatively, __d_lookup_rcu may be called again to look up the child of
|
|
|
|
* the returned dentry, so long as its parent's seqlock is checked after the
|
|
|
|
* child is looked up. Thus, an interlocking stepping of sequence lock checks
|
|
|
|
* is formed, giving integrity down the path walk.
|
vfs: clean up __d_lookup_rcu() and dentry_cmp() interfaces
The calling conventions for __d_lookup_rcu() and dentry_cmp() are
annoying in different ways, and there is actually one single underlying
reason for both of the annoyances.
The fundamental reason is that we do the returned dentry sequence number
check inside __d_lookup_rcu() instead of doing it in the caller. This
results in two annoyances:
- __d_lookup_rcu() now not only needs to return the dentry and the
sequence number that goes along with the lookup, it also needs to
return the inode pointer that was validated by that sequence number
check.
- and because we did the sequence number check early (to validate the
name pointer and length) we also couldn't just pass the dentry itself
to dentry_cmp(), we had to pass the counted string that contained the
name.
So that sequence number decision caused two separate ugly calling
conventions.
Both of these problems would be solved if we just did the sequence
number check in the caller instead. There's only one caller, and that
caller already has to do the sequence number check for the parent
anyway, so just do that.
That allows us to stop returning the dentry->d_inode in that in-out
argument (pointer-to-pointer-to-inode), so we can make the inode
argument just a regular input inode pointer. The caller can just load
the inode from dentry->d_inode, and then do the sequence number check
after that to make sure that it's synchronized with the name we looked
up.
And it allows us to just pass in the dentry to dentry_cmp(), which is
what all the callers really wanted. Sure, dentry_cmp() has to be a bit
careful about the dentry (which is not stable during RCU lookup), but
that's actually very simple.
And now that dentry_cmp() can clearly see that the first string argument
is a dentry, we can use the direct word access for that, instead of the
careful unaligned zero-padding. The dentry name is always properly
aligned, since it is a single path component that is either embedded
into the dentry itself, or was allocated with kmalloc() (see __d_alloc).
Finally, this also uninlines the nasty slow-case for dentry comparisons:
that one *does* need to do a sequence number check, since it will call
in to the low-level filesystems, and we want to give those a stable
inode pointer and path component length/start arguments. Doing an extra
sequence check for that slow case is not a problem, though.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-05-04 21:59:14 +00:00
|
|
|
*
|
|
|
|
* NOTE! The caller *has* to check the resulting dentry against the sequence
|
|
|
|
* number we've returned before using any of the resulting dentry state!
|
fs: rcu-walk for path lookup
Perform common cases of path lookups without any stores or locking in the
ancestor dentry elements. This is called rcu-walk, as opposed to the current
algorithm which is a refcount based walk, or ref-walk.
This results in far fewer atomic operations on every path element,
significantly improving path lookup performance. It also avoids cacheline
bouncing on common dentries, significantly improving scalability.
The overall design is like this:
* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
* Take the RCU lock for the entire path walk, starting with the acquiring
of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
not required for dentry persistence.
* synchronize_rcu is called when unregistering a filesystem, so we can
access d_ops and i_ops during rcu-walk.
* Similarly take the vfsmount lock for the entire path walk. So now mnt
refcounts are not required for persistence. Also we are free to perform mount
lookups, and to assume dentry mount points and mount roots are stable up and
down the path.
* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
so we can load this tuple atomically, and also check whether any of its
members have changed.
* Dentry lookups (based on parent, candidate string tuple) recheck the parent
sequence after the child is found in case anything changed in the parent
during the path walk.
* inode is also RCU protected so we can load d_inode and use the inode for
limited things.
* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
* i_op can be loaded.
When we reach the destination dentry, we lock it, recheck lookup sequence,
and increment its refcount and mountpoint refcount. RCU and vfsmount locks
are dropped. This is termed "dropping rcu-walk". If the dentry refcount does
not match, we can not drop rcu-walk gracefully at the current point in the
lokup, so instead return -ECHILD (for want of a better errno). This signals the
path walking code to re-do the entire lookup with a ref-walk.
Aside from the final dentry, there are other situations that may be encounted
where we cannot continue rcu-walk. In that case, we drop rcu-walk (ie. take
a reference on the last good dentry) and continue with a ref-walk. Again, if
we can drop rcu-walk gracefully, we return -ECHILD and do the whole lookup
using ref-walk. But it is very important that we can continue with ref-walk
for most cases, particularly to avoid the overhead of double lookups, and to
gain the scalability advantages on common path elements (like cwd and root).
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links
In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:52 +00:00
|
|
|
*/
|
2012-03-02 22:23:30 +00:00
|
|
|
struct dentry *__d_lookup_rcu(const struct dentry *parent,
|
|
|
|
const struct qstr *name,
|
2013-05-21 22:22:44 +00:00
|
|
|
unsigned *seqp)
|
fs: rcu-walk for path lookup
Perform common cases of path lookups without any stores or locking in the
ancestor dentry elements. This is called rcu-walk, as opposed to the current
algorithm which is a refcount based walk, or ref-walk.
This results in far fewer atomic operations on every path element,
significantly improving path lookup performance. It also avoids cacheline
bouncing on common dentries, significantly improving scalability.
The overall design is like this:
* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
* Take the RCU lock for the entire path walk, starting with the acquiring
of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
not required for dentry persistence.
* synchronize_rcu is called when unregistering a filesystem, so we can
access d_ops and i_ops during rcu-walk.
* Similarly take the vfsmount lock for the entire path walk. So now mnt
refcounts are not required for persistence. Also we are free to perform mount
lookups, and to assume dentry mount points and mount roots are stable up and
down the path.
* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
so we can load this tuple atomically, and also check whether any of its
members have changed.
* Dentry lookups (based on parent, candidate string tuple) recheck the parent
sequence after the child is found in case anything changed in the parent
during the path walk.
* inode is also RCU protected so we can load d_inode and use the inode for
limited things.
* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
* i_op can be loaded.
When we reach the destination dentry, we lock it, recheck lookup sequence,
and increment its refcount and mountpoint refcount. RCU and vfsmount locks
are dropped. This is termed "dropping rcu-walk". If the dentry refcount does
not match, we can not drop rcu-walk gracefully at the current point in the
lokup, so instead return -ECHILD (for want of a better errno). This signals the
path walking code to re-do the entire lookup with a ref-walk.
Aside from the final dentry, there are other situations that may be encounted
where we cannot continue rcu-walk. In that case, we drop rcu-walk (ie. take
a reference on the last good dentry) and continue with a ref-walk. Again, if
we can drop rcu-walk gracefully, we return -ECHILD and do the whole lookup
using ref-walk. But it is very important that we can continue with ref-walk
for most cases, particularly to avoid the overhead of double lookups, and to
gain the scalability advantages on common path elements (like cwd and root).
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links
In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:52 +00:00
|
|
|
{
|
2012-05-10 20:14:12 +00:00
|
|
|
u64 hashlen = name->hash_len;
|
fs: rcu-walk for path lookup
Perform common cases of path lookups without any stores or locking in the
ancestor dentry elements. This is called rcu-walk, as opposed to the current
algorithm which is a refcount based walk, or ref-walk.
This results in far fewer atomic operations on every path element,
significantly improving path lookup performance. It also avoids cacheline
bouncing on common dentries, significantly improving scalability.
The overall design is like this:
* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
* Take the RCU lock for the entire path walk, starting with the acquiring
of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
not required for dentry persistence.
* synchronize_rcu is called when unregistering a filesystem, so we can
access d_ops and i_ops during rcu-walk.
* Similarly take the vfsmount lock for the entire path walk. So now mnt
refcounts are not required for persistence. Also we are free to perform mount
lookups, and to assume dentry mount points and mount roots are stable up and
down the path.
* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
so we can load this tuple atomically, and also check whether any of its
members have changed.
* Dentry lookups (based on parent, candidate string tuple) recheck the parent
sequence after the child is found in case anything changed in the parent
during the path walk.
* inode is also RCU protected so we can load d_inode and use the inode for
limited things.
* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
* i_op can be loaded.
When we reach the destination dentry, we lock it, recheck lookup sequence,
and increment its refcount and mountpoint refcount. RCU and vfsmount locks
are dropped. This is termed "dropping rcu-walk". If the dentry refcount does
not match, we can not drop rcu-walk gracefully at the current point in the
lokup, so instead return -ECHILD (for want of a better errno). This signals the
path walking code to re-do the entire lookup with a ref-walk.
Aside from the final dentry, there are other situations that may be encounted
where we cannot continue rcu-walk. In that case, we drop rcu-walk (ie. take
a reference on the last good dentry) and continue with a ref-walk. Again, if
we can drop rcu-walk gracefully, we return -ECHILD and do the whole lookup
using ref-walk. But it is very important that we can continue with ref-walk
for most cases, particularly to avoid the overhead of double lookups, and to
gain the scalability advantages on common path elements (like cwd and root).
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links
In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:52 +00:00
|
|
|
const unsigned char *str = name->name;
|
vfs: dcache: move hashlen_hash() from callers into d_hash()
Both __d_lookup_rcu() and __d_lookup_rcu_op_compare() have the full
'name_hash' value of the qstr that they want to look up, and mask it off
to just the low 32-bit hash before calling down to d_hash().
Other callers just load the 32-bit hash and pass it as the argument.
If we move the masking into d_hash() itself, it simplifies the two
callers that currently do the masking, and is a no-op for the other
cases. It doesn't actually change the generated code since the compiler
will inline d_hash() and see that the end result is the same.
[ Technically, since the parse tree changes, the code generation may not
be 100% the same, and for me on x86-64, this does result in gcc
switching the operands around for one 'cmpl' instruction. So not
necessarily the exact same code generation, but equivalent ]
However, this does encapsulate the 'd_hash()' operation more, and makes
the shift operation in particular be a "shift 32 bits right, return full
word". Which matches the instruction semantics on both x86-64 and arm64
better, since a 32-bit shift will clear the upper bits.
That makes the next step of introducing a "shift by runtime constant"
more obvious and generates the shift with no extraneous type masking.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2024-06-10 18:47:06 +00:00
|
|
|
struct hlist_bl_head *b = d_hash(hashlen);
|
2011-01-07 06:50:05 +00:00
|
|
|
struct hlist_bl_node *node;
|
fs: rcu-walk for path lookup
Perform common cases of path lookups without any stores or locking in the
ancestor dentry elements. This is called rcu-walk, as opposed to the current
algorithm which is a refcount based walk, or ref-walk.
This results in far fewer atomic operations on every path element,
significantly improving path lookup performance. It also avoids cacheline
bouncing on common dentries, significantly improving scalability.
The overall design is like this:
* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
* Take the RCU lock for the entire path walk, starting with the acquiring
of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
not required for dentry persistence.
* synchronize_rcu is called when unregistering a filesystem, so we can
access d_ops and i_ops during rcu-walk.
* Similarly take the vfsmount lock for the entire path walk. So now mnt
refcounts are not required for persistence. Also we are free to perform mount
lookups, and to assume dentry mount points and mount roots are stable up and
down the path.
* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
so we can load this tuple atomically, and also check whether any of its
members have changed.
* Dentry lookups (based on parent, candidate string tuple) recheck the parent
sequence after the child is found in case anything changed in the parent
during the path walk.
* inode is also RCU protected so we can load d_inode and use the inode for
limited things.
* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
* i_op can be loaded.
When we reach the destination dentry, we lock it, recheck lookup sequence,
and increment its refcount and mountpoint refcount. RCU and vfsmount locks
are dropped. This is termed "dropping rcu-walk". If the dentry refcount does
not match, we can not drop rcu-walk gracefully at the current point in the
lokup, so instead return -ECHILD (for want of a better errno). This signals the
path walking code to re-do the entire lookup with a ref-walk.
Aside from the final dentry, there are other situations that may be encounted
where we cannot continue rcu-walk. In that case, we drop rcu-walk (ie. take
a reference on the last good dentry) and continue with a ref-walk. Again, if
we can drop rcu-walk gracefully, we return -ECHILD and do the whole lookup
using ref-walk. But it is very important that we can continue with ref-walk
for most cases, particularly to avoid the overhead of double lookups, and to
gain the scalability advantages on common path elements (like cwd and root).
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links
In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:52 +00:00
|
|
|
struct dentry *dentry;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Note: There is significant duplication with __d_lookup_rcu which is
|
|
|
|
* required to prevent single threaded performance regressions
|
|
|
|
* especially on architectures where smp_rmb (in seqcounts) are costly.
|
|
|
|
* Keep the two functions in sync.
|
|
|
|
*/
|
|
|
|
|
2022-08-11 22:29:46 +00:00
|
|
|
if (unlikely(parent->d_flags & DCACHE_OP_COMPARE))
|
|
|
|
return __d_lookup_rcu_op_compare(parent, name, seqp);
|
|
|
|
|
fs: rcu-walk for path lookup
Perform common cases of path lookups without any stores or locking in the
ancestor dentry elements. This is called rcu-walk, as opposed to the current
algorithm which is a refcount based walk, or ref-walk.
This results in far fewer atomic operations on every path element,
significantly improving path lookup performance. It also avoids cacheline
bouncing on common dentries, significantly improving scalability.
The overall design is like this:
* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
* Take the RCU lock for the entire path walk, starting with the acquiring
of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
not required for dentry persistence.
* synchronize_rcu is called when unregistering a filesystem, so we can
access d_ops and i_ops during rcu-walk.
* Similarly take the vfsmount lock for the entire path walk. So now mnt
refcounts are not required for persistence. Also we are free to perform mount
lookups, and to assume dentry mount points and mount roots are stable up and
down the path.
* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
so we can load this tuple atomically, and also check whether any of its
members have changed.
* Dentry lookups (based on parent, candidate string tuple) recheck the parent
sequence after the child is found in case anything changed in the parent
during the path walk.
* inode is also RCU protected so we can load d_inode and use the inode for
limited things.
* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
* i_op can be loaded.
When we reach the destination dentry, we lock it, recheck lookup sequence,
and increment its refcount and mountpoint refcount. RCU and vfsmount locks
are dropped. This is termed "dropping rcu-walk". If the dentry refcount does
not match, we can not drop rcu-walk gracefully at the current point in the
lokup, so instead return -ECHILD (for want of a better errno). This signals the
path walking code to re-do the entire lookup with a ref-walk.
Aside from the final dentry, there are other situations that may be encounted
where we cannot continue rcu-walk. In that case, we drop rcu-walk (ie. take
a reference on the last good dentry) and continue with a ref-walk. Again, if
we can drop rcu-walk gracefully, we return -ECHILD and do the whole lookup
using ref-walk. But it is very important that we can continue with ref-walk
for most cases, particularly to avoid the overhead of double lookups, and to
gain the scalability advantages on common path elements (like cwd and root).
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links
In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:52 +00:00
|
|
|
/*
|
|
|
|
* The hash list is protected using RCU.
|
|
|
|
*
|
|
|
|
* Carefully use d_seq when comparing a candidate dentry, to avoid
|
|
|
|
* races with d_move().
|
|
|
|
*
|
|
|
|
* It is possible that concurrent renames can mess up our list
|
|
|
|
* walk here and result in missing our dentry, resulting in the
|
|
|
|
* false-negative result. d_lookup() protects against concurrent
|
|
|
|
* renames using rename_lock seqlock.
|
|
|
|
*
|
2011-01-22 06:31:32 +00:00
|
|
|
* See Documentation/filesystems/path-lookup.txt for more details.
|
fs: rcu-walk for path lookup
Perform common cases of path lookups without any stores or locking in the
ancestor dentry elements. This is called rcu-walk, as opposed to the current
algorithm which is a refcount based walk, or ref-walk.
This results in far fewer atomic operations on every path element,
significantly improving path lookup performance. It also avoids cacheline
bouncing on common dentries, significantly improving scalability.
The overall design is like this:
* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
* Take the RCU lock for the entire path walk, starting with the acquiring
of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
not required for dentry persistence.
* synchronize_rcu is called when unregistering a filesystem, so we can
access d_ops and i_ops during rcu-walk.
* Similarly take the vfsmount lock for the entire path walk. So now mnt
refcounts are not required for persistence. Also we are free to perform mount
lookups, and to assume dentry mount points and mount roots are stable up and
down the path.
* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
so we can load this tuple atomically, and also check whether any of its
members have changed.
* Dentry lookups (based on parent, candidate string tuple) recheck the parent
sequence after the child is found in case anything changed in the parent
during the path walk.
* inode is also RCU protected so we can load d_inode and use the inode for
limited things.
* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
* i_op can be loaded.
When we reach the destination dentry, we lock it, recheck lookup sequence,
and increment its refcount and mountpoint refcount. RCU and vfsmount locks
are dropped. This is termed "dropping rcu-walk". If the dentry refcount does
not match, we can not drop rcu-walk gracefully at the current point in the
lokup, so instead return -ECHILD (for want of a better errno). This signals the
path walking code to re-do the entire lookup with a ref-walk.
Aside from the final dentry, there are other situations that may be encounted
where we cannot continue rcu-walk. In that case, we drop rcu-walk (ie. take
a reference on the last good dentry) and continue with a ref-walk. Again, if
we can drop rcu-walk gracefully, we return -ECHILD and do the whole lookup
using ref-walk. But it is very important that we can continue with ref-walk
for most cases, particularly to avoid the overhead of double lookups, and to
gain the scalability advantages on common path elements (like cwd and root).
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links
In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:52 +00:00
|
|
|
*/
|
2011-04-24 05:32:03 +00:00
|
|
|
hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) {
|
2012-03-02 22:23:30 +00:00
|
|
|
unsigned seq;
|
fs: rcu-walk for path lookup
Perform common cases of path lookups without any stores or locking in the
ancestor dentry elements. This is called rcu-walk, as opposed to the current
algorithm which is a refcount based walk, or ref-walk.
This results in far fewer atomic operations on every path element,
significantly improving path lookup performance. It also avoids cacheline
bouncing on common dentries, significantly improving scalability.
The overall design is like this:
* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
* Take the RCU lock for the entire path walk, starting with the acquiring
of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
not required for dentry persistence.
* synchronize_rcu is called when unregistering a filesystem, so we can
access d_ops and i_ops during rcu-walk.
* Similarly take the vfsmount lock for the entire path walk. So now mnt
refcounts are not required for persistence. Also we are free to perform mount
lookups, and to assume dentry mount points and mount roots are stable up and
down the path.
* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
so we can load this tuple atomically, and also check whether any of its
members have changed.
* Dentry lookups (based on parent, candidate string tuple) recheck the parent
sequence after the child is found in case anything changed in the parent
during the path walk.
* inode is also RCU protected so we can load d_inode and use the inode for
limited things.
* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
* i_op can be loaded.
When we reach the destination dentry, we lock it, recheck lookup sequence,
and increment its refcount and mountpoint refcount. RCU and vfsmount locks
are dropped. This is termed "dropping rcu-walk". If the dentry refcount does
not match, we can not drop rcu-walk gracefully at the current point in the
lokup, so instead return -ECHILD (for want of a better errno). This signals the
path walking code to re-do the entire lookup with a ref-walk.
Aside from the final dentry, there are other situations that may be encounted
where we cannot continue rcu-walk. In that case, we drop rcu-walk (ie. take
a reference on the last good dentry) and continue with a ref-walk. Again, if
we can drop rcu-walk gracefully, we return -ECHILD and do the whole lookup
using ref-walk. But it is very important that we can continue with ref-walk
for most cases, particularly to avoid the overhead of double lookups, and to
gain the scalability advantages on common path elements (like cwd and root).
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links
In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:52 +00:00
|
|
|
|
vfs: clean up __d_lookup_rcu() and dentry_cmp() interfaces
The calling conventions for __d_lookup_rcu() and dentry_cmp() are
annoying in different ways, and there is actually one single underlying
reason for both of the annoyances.
The fundamental reason is that we do the returned dentry sequence number
check inside __d_lookup_rcu() instead of doing it in the caller. This
results in two annoyances:
- __d_lookup_rcu() now not only needs to return the dentry and the
sequence number that goes along with the lookup, it also needs to
return the inode pointer that was validated by that sequence number
check.
- and because we did the sequence number check early (to validate the
name pointer and length) we also couldn't just pass the dentry itself
to dentry_cmp(), we had to pass the counted string that contained the
name.
So that sequence number decision caused two separate ugly calling
conventions.
Both of these problems would be solved if we just did the sequence
number check in the caller instead. There's only one caller, and that
caller already has to do the sequence number check for the parent
anyway, so just do that.
That allows us to stop returning the dentry->d_inode in that in-out
argument (pointer-to-pointer-to-inode), so we can make the inode
argument just a regular input inode pointer. The caller can just load
the inode from dentry->d_inode, and then do the sequence number check
after that to make sure that it's synchronized with the name we looked
up.
And it allows us to just pass in the dentry to dentry_cmp(), which is
what all the callers really wanted. Sure, dentry_cmp() has to be a bit
careful about the dentry (which is not stable during RCU lookup), but
that's actually very simple.
And now that dentry_cmp() can clearly see that the first string argument
is a dentry, we can use the direct word access for that, instead of the
careful unaligned zero-padding. The dentry name is always properly
aligned, since it is a single path component that is either embedded
into the dentry itself, or was allocated with kmalloc() (see __d_alloc).
Finally, this also uninlines the nasty slow-case for dentry comparisons:
that one *does* need to do a sequence number check, since it will call
in to the low-level filesystems, and we want to give those a stable
inode pointer and path component length/start arguments. Doing an extra
sequence check for that slow case is not a problem, though.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-05-04 21:59:14 +00:00
|
|
|
/*
|
|
|
|
* The dentry sequence count protects us from concurrent
|
2013-05-21 22:22:44 +00:00
|
|
|
* renames, and thus protects parent and name fields.
|
vfs: clean up __d_lookup_rcu() and dentry_cmp() interfaces
The calling conventions for __d_lookup_rcu() and dentry_cmp() are
annoying in different ways, and there is actually one single underlying
reason for both of the annoyances.
The fundamental reason is that we do the returned dentry sequence number
check inside __d_lookup_rcu() instead of doing it in the caller. This
results in two annoyances:
- __d_lookup_rcu() now not only needs to return the dentry and the
sequence number that goes along with the lookup, it also needs to
return the inode pointer that was validated by that sequence number
check.
- and because we did the sequence number check early (to validate the
name pointer and length) we also couldn't just pass the dentry itself
to dentry_cmp(), we had to pass the counted string that contained the
name.
So that sequence number decision caused two separate ugly calling
conventions.
Both of these problems would be solved if we just did the sequence
number check in the caller instead. There's only one caller, and that
caller already has to do the sequence number check for the parent
anyway, so just do that.
That allows us to stop returning the dentry->d_inode in that in-out
argument (pointer-to-pointer-to-inode), so we can make the inode
argument just a regular input inode pointer. The caller can just load
the inode from dentry->d_inode, and then do the sequence number check
after that to make sure that it's synchronized with the name we looked
up.
And it allows us to just pass in the dentry to dentry_cmp(), which is
what all the callers really wanted. Sure, dentry_cmp() has to be a bit
careful about the dentry (which is not stable during RCU lookup), but
that's actually very simple.
And now that dentry_cmp() can clearly see that the first string argument
is a dentry, we can use the direct word access for that, instead of the
careful unaligned zero-padding. The dentry name is always properly
aligned, since it is a single path component that is either embedded
into the dentry itself, or was allocated with kmalloc() (see __d_alloc).
Finally, this also uninlines the nasty slow-case for dentry comparisons:
that one *does* need to do a sequence number check, since it will call
in to the low-level filesystems, and we want to give those a stable
inode pointer and path component length/start arguments. Doing an extra
sequence check for that slow case is not a problem, though.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-05-04 21:59:14 +00:00
|
|
|
*
|
|
|
|
* The caller must perform a seqcount check in order
|
2013-05-21 22:22:44 +00:00
|
|
|
* to do anything useful with the returned dentry.
|
vfs: clean up __d_lookup_rcu() and dentry_cmp() interfaces
The calling conventions for __d_lookup_rcu() and dentry_cmp() are
annoying in different ways, and there is actually one single underlying
reason for both of the annoyances.
The fundamental reason is that we do the returned dentry sequence number
check inside __d_lookup_rcu() instead of doing it in the caller. This
results in two annoyances:
- __d_lookup_rcu() now not only needs to return the dentry and the
sequence number that goes along with the lookup, it also needs to
return the inode pointer that was validated by that sequence number
check.
- and because we did the sequence number check early (to validate the
name pointer and length) we also couldn't just pass the dentry itself
to dentry_cmp(), we had to pass the counted string that contained the
name.
So that sequence number decision caused two separate ugly calling
conventions.
Both of these problems would be solved if we just did the sequence
number check in the caller instead. There's only one caller, and that
caller already has to do the sequence number check for the parent
anyway, so just do that.
That allows us to stop returning the dentry->d_inode in that in-out
argument (pointer-to-pointer-to-inode), so we can make the inode
argument just a regular input inode pointer. The caller can just load
the inode from dentry->d_inode, and then do the sequence number check
after that to make sure that it's synchronized with the name we looked
up.
And it allows us to just pass in the dentry to dentry_cmp(), which is
what all the callers really wanted. Sure, dentry_cmp() has to be a bit
careful about the dentry (which is not stable during RCU lookup), but
that's actually very simple.
And now that dentry_cmp() can clearly see that the first string argument
is a dentry, we can use the direct word access for that, instead of the
careful unaligned zero-padding. The dentry name is always properly
aligned, since it is a single path component that is either embedded
into the dentry itself, or was allocated with kmalloc() (see __d_alloc).
Finally, this also uninlines the nasty slow-case for dentry comparisons:
that one *does* need to do a sequence number check, since it will call
in to the low-level filesystems, and we want to give those a stable
inode pointer and path component length/start arguments. Doing an extra
sequence check for that slow case is not a problem, though.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-05-04 21:59:14 +00:00
|
|
|
*
|
|
|
|
* NOTE! We do a "raw" seqcount_begin here. That means that
|
|
|
|
* we don't wait for the sequence count to stabilize if it
|
|
|
|
* is in the middle of a sequence change. If we do the slow
|
|
|
|
* dentry compare, we will do seqretries until it is stable,
|
|
|
|
* and if we end up with a successful lookup, we actually
|
|
|
|
* want to exit RCU lookup anyway.
|
2016-06-26 03:33:49 +00:00
|
|
|
*
|
|
|
|
* Note that raw_seqcount_begin still *does* smp_rmb(), so
|
|
|
|
* we are still guaranteed NUL-termination of ->d_name.name.
|
vfs: clean up __d_lookup_rcu() and dentry_cmp() interfaces
The calling conventions for __d_lookup_rcu() and dentry_cmp() are
annoying in different ways, and there is actually one single underlying
reason for both of the annoyances.
The fundamental reason is that we do the returned dentry sequence number
check inside __d_lookup_rcu() instead of doing it in the caller. This
results in two annoyances:
- __d_lookup_rcu() now not only needs to return the dentry and the
sequence number that goes along with the lookup, it also needs to
return the inode pointer that was validated by that sequence number
check.
- and because we did the sequence number check early (to validate the
name pointer and length) we also couldn't just pass the dentry itself
to dentry_cmp(), we had to pass the counted string that contained the
name.
So that sequence number decision caused two separate ugly calling
conventions.
Both of these problems would be solved if we just did the sequence
number check in the caller instead. There's only one caller, and that
caller already has to do the sequence number check for the parent
anyway, so just do that.
That allows us to stop returning the dentry->d_inode in that in-out
argument (pointer-to-pointer-to-inode), so we can make the inode
argument just a regular input inode pointer. The caller can just load
the inode from dentry->d_inode, and then do the sequence number check
after that to make sure that it's synchronized with the name we looked
up.
And it allows us to just pass in the dentry to dentry_cmp(), which is
what all the callers really wanted. Sure, dentry_cmp() has to be a bit
careful about the dentry (which is not stable during RCU lookup), but
that's actually very simple.
And now that dentry_cmp() can clearly see that the first string argument
is a dentry, we can use the direct word access for that, instead of the
careful unaligned zero-padding. The dentry name is always properly
aligned, since it is a single path component that is either embedded
into the dentry itself, or was allocated with kmalloc() (see __d_alloc).
Finally, this also uninlines the nasty slow-case for dentry comparisons:
that one *does* need to do a sequence number check, since it will call
in to the low-level filesystems, and we want to give those a stable
inode pointer and path component length/start arguments. Doing an extra
sequence check for that slow case is not a problem, though.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-05-04 21:59:14 +00:00
|
|
|
*/
|
|
|
|
seq = raw_seqcount_begin(&dentry->d_seq);
|
fs: rcu-walk for path lookup
Perform common cases of path lookups without any stores or locking in the
ancestor dentry elements. This is called rcu-walk, as opposed to the current
algorithm which is a refcount based walk, or ref-walk.
This results in far fewer atomic operations on every path element,
significantly improving path lookup performance. It also avoids cacheline
bouncing on common dentries, significantly improving scalability.
The overall design is like this:
* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
* Take the RCU lock for the entire path walk, starting with the acquiring
of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
not required for dentry persistence.
* synchronize_rcu is called when unregistering a filesystem, so we can
access d_ops and i_ops during rcu-walk.
* Similarly take the vfsmount lock for the entire path walk. So now mnt
refcounts are not required for persistence. Also we are free to perform mount
lookups, and to assume dentry mount points and mount roots are stable up and
down the path.
* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
so we can load this tuple atomically, and also check whether any of its
members have changed.
* Dentry lookups (based on parent, candidate string tuple) recheck the parent
sequence after the child is found in case anything changed in the parent
during the path walk.
* inode is also RCU protected so we can load d_inode and use the inode for
limited things.
* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
* i_op can be loaded.
When we reach the destination dentry, we lock it, recheck lookup sequence,
and increment its refcount and mountpoint refcount. RCU and vfsmount locks
are dropped. This is termed "dropping rcu-walk". If the dentry refcount does
not match, we can not drop rcu-walk gracefully at the current point in the
lokup, so instead return -ECHILD (for want of a better errno). This signals the
path walking code to re-do the entire lookup with a ref-walk.
Aside from the final dentry, there are other situations that may be encounted
where we cannot continue rcu-walk. In that case, we drop rcu-walk (ie. take
a reference on the last good dentry) and continue with a ref-walk. Again, if
we can drop rcu-walk gracefully, we return -ECHILD and do the whole lookup
using ref-walk. But it is very important that we can continue with ref-walk
for most cases, particularly to avoid the overhead of double lookups, and to
gain the scalability advantages on common path elements (like cwd and root).
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links
In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:52 +00:00
|
|
|
if (dentry->d_parent != parent)
|
|
|
|
continue;
|
2012-05-22 01:48:10 +00:00
|
|
|
if (d_unhashed(dentry))
|
|
|
|
continue;
|
2022-08-11 22:29:46 +00:00
|
|
|
if (dentry->d_name.hash_len != hashlen)
|
|
|
|
continue;
|
|
|
|
if (dentry_cmp(dentry, str, hashlen_len(hashlen)) != 0)
|
|
|
|
continue;
|
2013-05-21 22:22:44 +00:00
|
|
|
*seqp = seq;
|
2016-06-26 03:33:49 +00:00
|
|
|
return dentry;
|
fs: rcu-walk for path lookup
Perform common cases of path lookups without any stores or locking in the
ancestor dentry elements. This is called rcu-walk, as opposed to the current
algorithm which is a refcount based walk, or ref-walk.
This results in far fewer atomic operations on every path element,
significantly improving path lookup performance. It also avoids cacheline
bouncing on common dentries, significantly improving scalability.
The overall design is like this:
* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
* Take the RCU lock for the entire path walk, starting with the acquiring
of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
not required for dentry persistence.
* synchronize_rcu is called when unregistering a filesystem, so we can
access d_ops and i_ops during rcu-walk.
* Similarly take the vfsmount lock for the entire path walk. So now mnt
refcounts are not required for persistence. Also we are free to perform mount
lookups, and to assume dentry mount points and mount roots are stable up and
down the path.
* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
so we can load this tuple atomically, and also check whether any of its
members have changed.
* Dentry lookups (based on parent, candidate string tuple) recheck the parent
sequence after the child is found in case anything changed in the parent
during the path walk.
* inode is also RCU protected so we can load d_inode and use the inode for
limited things.
* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
* i_op can be loaded.
When we reach the destination dentry, we lock it, recheck lookup sequence,
and increment its refcount and mountpoint refcount. RCU and vfsmount locks
are dropped. This is termed "dropping rcu-walk". If the dentry refcount does
not match, we can not drop rcu-walk gracefully at the current point in the
lokup, so instead return -ECHILD (for want of a better errno). This signals the
path walking code to re-do the entire lookup with a ref-walk.
Aside from the final dentry, there are other situations that may be encounted
where we cannot continue rcu-walk. In that case, we drop rcu-walk (ie. take
a reference on the last good dentry) and continue with a ref-walk. Again, if
we can drop rcu-walk gracefully, we return -ECHILD and do the whole lookup
using ref-walk. But it is very important that we can continue with ref-walk
for most cases, particularly to avoid the overhead of double lookups, and to
gain the scalability advantages on common path elements (like cwd and root).
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links
In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:52 +00:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/**
|
|
|
|
* d_lookup - search for a dentry
|
|
|
|
* @parent: parent dentry
|
|
|
|
* @name: qstr of name we wish to find
|
fs: remove extra lookup in __lookup_hash
fs: remove extra lookup in __lookup_hash
Optimize lookup for create operations, where no dentry should often be
common-case. In cases where it is not, such as unlink, the added overhead
is much smaller than the removed.
Also, move comments about __d_lookup racyness to the __d_lookup call site.
d_lookup is intuitive; __d_lookup is what needs commenting. So in that same
vein, add kerneldoc comments to __d_lookup and clean up some of the comments:
- We are interested in how the RCU lookup works here, particularly with
renames. Make that explicit, and point to the document where it is explained
in more detail.
- RCU is pretty standard now, and macros make implementations pretty mindless.
If we want to know about RCU barrier details, we look in RCU code.
- Delete some boring legacy comments because we don't care much about how the
code used to work, more about the interesting parts of how it works now. So
comments about lazy LRU may be interesting, but would better be done in the
LRU or refcount management code.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2010-08-17 18:37:34 +00:00
|
|
|
* Returns: dentry, or NULL
|
2005-04-16 22:20:36 +00:00
|
|
|
*
|
fs: remove extra lookup in __lookup_hash
fs: remove extra lookup in __lookup_hash
Optimize lookup for create operations, where no dentry should often be
common-case. In cases where it is not, such as unlink, the added overhead
is much smaller than the removed.
Also, move comments about __d_lookup racyness to the __d_lookup call site.
d_lookup is intuitive; __d_lookup is what needs commenting. So in that same
vein, add kerneldoc comments to __d_lookup and clean up some of the comments:
- We are interested in how the RCU lookup works here, particularly with
renames. Make that explicit, and point to the document where it is explained
in more detail.
- RCU is pretty standard now, and macros make implementations pretty mindless.
If we want to know about RCU barrier details, we look in RCU code.
- Delete some boring legacy comments because we don't care much about how the
code used to work, more about the interesting parts of how it works now. So
comments about lazy LRU may be interesting, but would better be done in the
LRU or refcount management code.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2010-08-17 18:37:34 +00:00
|
|
|
* d_lookup searches the children of the parent dentry for the name in
|
|
|
|
* question. If the dentry is found its reference count is incremented and the
|
|
|
|
* dentry is returned. The caller must use dput to free the entry when it has
|
|
|
|
* finished using it. %NULL is returned if the dentry does not exist.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2013-01-24 23:29:34 +00:00
|
|
|
struct dentry *d_lookup(const struct dentry *parent, const struct qstr *name)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
fs: rcu-walk for path lookup
Perform common cases of path lookups without any stores or locking in the
ancestor dentry elements. This is called rcu-walk, as opposed to the current
algorithm which is a refcount based walk, or ref-walk.
This results in far fewer atomic operations on every path element,
significantly improving path lookup performance. It also avoids cacheline
bouncing on common dentries, significantly improving scalability.
The overall design is like this:
* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
* Take the RCU lock for the entire path walk, starting with the acquiring
of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
not required for dentry persistence.
* synchronize_rcu is called when unregistering a filesystem, so we can
access d_ops and i_ops during rcu-walk.
* Similarly take the vfsmount lock for the entire path walk. So now mnt
refcounts are not required for persistence. Also we are free to perform mount
lookups, and to assume dentry mount points and mount roots are stable up and
down the path.
* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
so we can load this tuple atomically, and also check whether any of its
members have changed.
* Dentry lookups (based on parent, candidate string tuple) recheck the parent
sequence after the child is found in case anything changed in the parent
during the path walk.
* inode is also RCU protected so we can load d_inode and use the inode for
limited things.
* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
* i_op can be loaded.
When we reach the destination dentry, we lock it, recheck lookup sequence,
and increment its refcount and mountpoint refcount. RCU and vfsmount locks
are dropped. This is termed "dropping rcu-walk". If the dentry refcount does
not match, we can not drop rcu-walk gracefully at the current point in the
lokup, so instead return -ECHILD (for want of a better errno). This signals the
path walking code to re-do the entire lookup with a ref-walk.
Aside from the final dentry, there are other situations that may be encounted
where we cannot continue rcu-walk. In that case, we drop rcu-walk (ie. take
a reference on the last good dentry) and continue with a ref-walk. Again, if
we can drop rcu-walk gracefully, we return -ECHILD and do the whole lookup
using ref-walk. But it is very important that we can continue with ref-walk
for most cases, particularly to avoid the overhead of double lookups, and to
gain the scalability advantages on common path elements (like cwd and root).
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links
In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:52 +00:00
|
|
|
struct dentry *dentry;
|
2011-01-07 06:49:37 +00:00
|
|
|
unsigned seq;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2014-08-11 02:46:53 +00:00
|
|
|
do {
|
|
|
|
seq = read_seqbegin(&rename_lock);
|
|
|
|
dentry = __d_lookup(parent, name);
|
|
|
|
if (dentry)
|
2005-04-16 22:20:36 +00:00
|
|
|
break;
|
|
|
|
} while (read_seqretry(&rename_lock, seq));
|
|
|
|
return dentry;
|
|
|
|
}
|
2010-01-05 20:45:18 +00:00
|
|
|
EXPORT_SYMBOL(d_lookup);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
fs: rcu-walk for path lookup
Perform common cases of path lookups without any stores or locking in the
ancestor dentry elements. This is called rcu-walk, as opposed to the current
algorithm which is a refcount based walk, or ref-walk.
This results in far fewer atomic operations on every path element,
significantly improving path lookup performance. It also avoids cacheline
bouncing on common dentries, significantly improving scalability.
The overall design is like this:
* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
* Take the RCU lock for the entire path walk, starting with the acquiring
of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
not required for dentry persistence.
* synchronize_rcu is called when unregistering a filesystem, so we can
access d_ops and i_ops during rcu-walk.
* Similarly take the vfsmount lock for the entire path walk. So now mnt
refcounts are not required for persistence. Also we are free to perform mount
lookups, and to assume dentry mount points and mount roots are stable up and
down the path.
* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
so we can load this tuple atomically, and also check whether any of its
members have changed.
* Dentry lookups (based on parent, candidate string tuple) recheck the parent
sequence after the child is found in case anything changed in the parent
during the path walk.
* inode is also RCU protected so we can load d_inode and use the inode for
limited things.
* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
* i_op can be loaded.
When we reach the destination dentry, we lock it, recheck lookup sequence,
and increment its refcount and mountpoint refcount. RCU and vfsmount locks
are dropped. This is termed "dropping rcu-walk". If the dentry refcount does
not match, we can not drop rcu-walk gracefully at the current point in the
lokup, so instead return -ECHILD (for want of a better errno). This signals the
path walking code to re-do the entire lookup with a ref-walk.
Aside from the final dentry, there are other situations that may be encounted
where we cannot continue rcu-walk. In that case, we drop rcu-walk (ie. take
a reference on the last good dentry) and continue with a ref-walk. Again, if
we can drop rcu-walk gracefully, we return -ECHILD and do the whole lookup
using ref-walk. But it is very important that we can continue with ref-walk
for most cases, particularly to avoid the overhead of double lookups, and to
gain the scalability advantages on common path elements (like cwd and root).
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links
In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:52 +00:00
|
|
|
/**
|
fs: remove extra lookup in __lookup_hash
fs: remove extra lookup in __lookup_hash
Optimize lookup for create operations, where no dentry should often be
common-case. In cases where it is not, such as unlink, the added overhead
is much smaller than the removed.
Also, move comments about __d_lookup racyness to the __d_lookup call site.
d_lookup is intuitive; __d_lookup is what needs commenting. So in that same
vein, add kerneldoc comments to __d_lookup and clean up some of the comments:
- We are interested in how the RCU lookup works here, particularly with
renames. Make that explicit, and point to the document where it is explained
in more detail.
- RCU is pretty standard now, and macros make implementations pretty mindless.
If we want to know about RCU barrier details, we look in RCU code.
- Delete some boring legacy comments because we don't care much about how the
code used to work, more about the interesting parts of how it works now. So
comments about lazy LRU may be interesting, but would better be done in the
LRU or refcount management code.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2010-08-17 18:37:34 +00:00
|
|
|
* __d_lookup - search for a dentry (racy)
|
|
|
|
* @parent: parent dentry
|
|
|
|
* @name: qstr of name we wish to find
|
|
|
|
* Returns: dentry, or NULL
|
|
|
|
*
|
|
|
|
* __d_lookup is like d_lookup, however it may (rarely) return a
|
|
|
|
* false-negative result due to unrelated rename activity.
|
|
|
|
*
|
|
|
|
* __d_lookup is slightly faster by avoiding rename_lock read seqlock,
|
|
|
|
* however it must be used carefully, eg. with a following d_lookup in
|
|
|
|
* the case of failure.
|
|
|
|
*
|
|
|
|
* __d_lookup callers must be commented.
|
|
|
|
*/
|
2013-01-24 23:27:00 +00:00
|
|
|
struct dentry *__d_lookup(const struct dentry *parent, const struct qstr *name)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
unsigned int hash = name->hash;
|
2016-06-10 14:51:30 +00:00
|
|
|
struct hlist_bl_head *b = d_hash(hash);
|
2011-01-07 06:50:05 +00:00
|
|
|
struct hlist_bl_node *node;
|
fs: rcu-walk for path lookup
Perform common cases of path lookups without any stores or locking in the
ancestor dentry elements. This is called rcu-walk, as opposed to the current
algorithm which is a refcount based walk, or ref-walk.
This results in far fewer atomic operations on every path element,
significantly improving path lookup performance. It also avoids cacheline
bouncing on common dentries, significantly improving scalability.
The overall design is like this:
* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
* Take the RCU lock for the entire path walk, starting with the acquiring
of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
not required for dentry persistence.
* synchronize_rcu is called when unregistering a filesystem, so we can
access d_ops and i_ops during rcu-walk.
* Similarly take the vfsmount lock for the entire path walk. So now mnt
refcounts are not required for persistence. Also we are free to perform mount
lookups, and to assume dentry mount points and mount roots are stable up and
down the path.
* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
so we can load this tuple atomically, and also check whether any of its
members have changed.
* Dentry lookups (based on parent, candidate string tuple) recheck the parent
sequence after the child is found in case anything changed in the parent
during the path walk.
* inode is also RCU protected so we can load d_inode and use the inode for
limited things.
* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
* i_op can be loaded.
When we reach the destination dentry, we lock it, recheck lookup sequence,
and increment its refcount and mountpoint refcount. RCU and vfsmount locks
are dropped. This is termed "dropping rcu-walk". If the dentry refcount does
not match, we can not drop rcu-walk gracefully at the current point in the
lokup, so instead return -ECHILD (for want of a better errno). This signals the
path walking code to re-do the entire lookup with a ref-walk.
Aside from the final dentry, there are other situations that may be encounted
where we cannot continue rcu-walk. In that case, we drop rcu-walk (ie. take
a reference on the last good dentry) and continue with a ref-walk. Again, if
we can drop rcu-walk gracefully, we return -ECHILD and do the whole lookup
using ref-walk. But it is very important that we can continue with ref-walk
for most cases, particularly to avoid the overhead of double lookups, and to
gain the scalability advantages on common path elements (like cwd and root).
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links
In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:52 +00:00
|
|
|
struct dentry *found = NULL;
|
2005-11-07 08:59:17 +00:00
|
|
|
struct dentry *dentry;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
fs: rcu-walk for path lookup
Perform common cases of path lookups without any stores or locking in the
ancestor dentry elements. This is called rcu-walk, as opposed to the current
algorithm which is a refcount based walk, or ref-walk.
This results in far fewer atomic operations on every path element,
significantly improving path lookup performance. It also avoids cacheline
bouncing on common dentries, significantly improving scalability.
The overall design is like this:
* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
* Take the RCU lock for the entire path walk, starting with the acquiring
of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
not required for dentry persistence.
* synchronize_rcu is called when unregistering a filesystem, so we can
access d_ops and i_ops during rcu-walk.
* Similarly take the vfsmount lock for the entire path walk. So now mnt
refcounts are not required for persistence. Also we are free to perform mount
lookups, and to assume dentry mount points and mount roots are stable up and
down the path.
* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
so we can load this tuple atomically, and also check whether any of its
members have changed.
* Dentry lookups (based on parent, candidate string tuple) recheck the parent
sequence after the child is found in case anything changed in the parent
during the path walk.
* inode is also RCU protected so we can load d_inode and use the inode for
limited things.
* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
* i_op can be loaded.
When we reach the destination dentry, we lock it, recheck lookup sequence,
and increment its refcount and mountpoint refcount. RCU and vfsmount locks
are dropped. This is termed "dropping rcu-walk". If the dentry refcount does
not match, we can not drop rcu-walk gracefully at the current point in the
lokup, so instead return -ECHILD (for want of a better errno). This signals the
path walking code to re-do the entire lookup with a ref-walk.
Aside from the final dentry, there are other situations that may be encounted
where we cannot continue rcu-walk. In that case, we drop rcu-walk (ie. take
a reference on the last good dentry) and continue with a ref-walk. Again, if
we can drop rcu-walk gracefully, we return -ECHILD and do the whole lookup
using ref-walk. But it is very important that we can continue with ref-walk
for most cases, particularly to avoid the overhead of double lookups, and to
gain the scalability advantages on common path elements (like cwd and root).
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links
In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:52 +00:00
|
|
|
/*
|
|
|
|
* Note: There is significant duplication with __d_lookup_rcu which is
|
|
|
|
* required to prevent single threaded performance regressions
|
|
|
|
* especially on architectures where smp_rmb (in seqcounts) are costly.
|
|
|
|
* Keep the two functions in sync.
|
|
|
|
*/
|
|
|
|
|
fs: remove extra lookup in __lookup_hash
fs: remove extra lookup in __lookup_hash
Optimize lookup for create operations, where no dentry should often be
common-case. In cases where it is not, such as unlink, the added overhead
is much smaller than the removed.
Also, move comments about __d_lookup racyness to the __d_lookup call site.
d_lookup is intuitive; __d_lookup is what needs commenting. So in that same
vein, add kerneldoc comments to __d_lookup and clean up some of the comments:
- We are interested in how the RCU lookup works here, particularly with
renames. Make that explicit, and point to the document where it is explained
in more detail.
- RCU is pretty standard now, and macros make implementations pretty mindless.
If we want to know about RCU barrier details, we look in RCU code.
- Delete some boring legacy comments because we don't care much about how the
code used to work, more about the interesting parts of how it works now. So
comments about lazy LRU may be interesting, but would better be done in the
LRU or refcount management code.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2010-08-17 18:37:34 +00:00
|
|
|
/*
|
|
|
|
* The hash list is protected using RCU.
|
|
|
|
*
|
|
|
|
* Take d_lock when comparing a candidate dentry, to avoid races
|
|
|
|
* with d_move().
|
|
|
|
*
|
|
|
|
* It is possible that concurrent renames can mess up our list
|
|
|
|
* walk here and result in missing our dentry, resulting in the
|
|
|
|
* false-negative result. d_lookup() protects against concurrent
|
|
|
|
* renames using rename_lock seqlock.
|
|
|
|
*
|
2011-01-22 06:31:32 +00:00
|
|
|
* See Documentation/filesystems/path-lookup.txt for more details.
|
fs: remove extra lookup in __lookup_hash
fs: remove extra lookup in __lookup_hash
Optimize lookup for create operations, where no dentry should often be
common-case. In cases where it is not, such as unlink, the added overhead
is much smaller than the removed.
Also, move comments about __d_lookup racyness to the __d_lookup call site.
d_lookup is intuitive; __d_lookup is what needs commenting. So in that same
vein, add kerneldoc comments to __d_lookup and clean up some of the comments:
- We are interested in how the RCU lookup works here, particularly with
renames. Make that explicit, and point to the document where it is explained
in more detail.
- RCU is pretty standard now, and macros make implementations pretty mindless.
If we want to know about RCU barrier details, we look in RCU code.
- Delete some boring legacy comments because we don't care much about how the
code used to work, more about the interesting parts of how it works now. So
comments about lazy LRU may be interesting, but would better be done in the
LRU or refcount management code.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2010-08-17 18:37:34 +00:00
|
|
|
*/
|
2005-04-16 22:20:36 +00:00
|
|
|
rcu_read_lock();
|
|
|
|
|
2011-04-24 05:32:03 +00:00
|
|
|
hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) {
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
if (dentry->d_name.hash != hash)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
spin_lock(&dentry->d_lock);
|
|
|
|
if (dentry->d_parent != parent)
|
|
|
|
goto next;
|
Fix NULL pointer dereference in proc_sys_compare
The VFS interface for the 'd_compare()' is a bit special (read: 'odd'),
because it really just essentially replaces a memcmp(). The filesystem
is supposed to just compare the two names with whatever case-independent
or other function.
And when I say 'is supposed to', I obviously mean that 'procfs does odd
things, and actually looks at the dentry that we don't even pass down,
rather than just the name'. Which results in problems, because we
actually call d_compare before we have even verified that the dentry is
still hashed at all.
And that causes a problm since the inode that procfs looks at may have
been free'd and the d_inode pointer is NULL. procfs just assumes that
all dentries are positive, since procfs itself never generates a
negative one. But memory pressure will still result in the dentry
getting torn down, and as it is removed by RCU, it still remains visible
on some lists - and to d_compare.
If the filesystem just did a name comparison, we wouldn't care. And we
could just fix procfs to know about negative dentries too. But rather
than have the low-level filesystems know about internal VFS details,
just move the check for a unhashed dentry up a bit, so that we will only
call d_compare on dentries that are still active.
The actual oops this caused didn't look like a NULL pointer dereference
because procfs did a 'container_of(inode, struct proc_inode, vfs_inode)'
to get at its internal proc_inode information from the inode pointer,
and accessed a field below the inode. So the oops would look something
like
BUG: unable to handle kernel paging request at fffffffffffffff0
IP: [<ffffffff802bc6c6>] proc_sys_compare+0x36/0x50
and was seen on both x86-64 (Alexey Dobriyan and Hugh Dickins) and
ppc64 (Hugh Dickins).
Reported-by: Alexey Dobriyan <adobriyan@gmail.com>
Acked-by: Hugh Dickins <hugh@veritas.com>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
Reviewed-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-of-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-09-29 14:42:57 +00:00
|
|
|
if (d_unhashed(dentry))
|
|
|
|
goto next;
|
|
|
|
|
2016-06-26 03:33:49 +00:00
|
|
|
if (!d_same_name(dentry, parent, name))
|
|
|
|
goto next;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2013-08-29 01:24:59 +00:00
|
|
|
dentry->d_lockref.count++;
|
Fix NULL pointer dereference in proc_sys_compare
The VFS interface for the 'd_compare()' is a bit special (read: 'odd'),
because it really just essentially replaces a memcmp(). The filesystem
is supposed to just compare the two names with whatever case-independent
or other function.
And when I say 'is supposed to', I obviously mean that 'procfs does odd
things, and actually looks at the dentry that we don't even pass down,
rather than just the name'. Which results in problems, because we
actually call d_compare before we have even verified that the dentry is
still hashed at all.
And that causes a problm since the inode that procfs looks at may have
been free'd and the d_inode pointer is NULL. procfs just assumes that
all dentries are positive, since procfs itself never generates a
negative one. But memory pressure will still result in the dentry
getting torn down, and as it is removed by RCU, it still remains visible
on some lists - and to d_compare.
If the filesystem just did a name comparison, we wouldn't care. And we
could just fix procfs to know about negative dentries too. But rather
than have the low-level filesystems know about internal VFS details,
just move the check for a unhashed dentry up a bit, so that we will only
call d_compare on dentries that are still active.
The actual oops this caused didn't look like a NULL pointer dereference
because procfs did a 'container_of(inode, struct proc_inode, vfs_inode)'
to get at its internal proc_inode information from the inode pointer,
and accessed a field below the inode. So the oops would look something
like
BUG: unable to handle kernel paging request at fffffffffffffff0
IP: [<ffffffff802bc6c6>] proc_sys_compare+0x36/0x50
and was seen on both x86-64 (Alexey Dobriyan and Hugh Dickins) and
ppc64 (Hugh Dickins).
Reported-by: Alexey Dobriyan <adobriyan@gmail.com>
Acked-by: Hugh Dickins <hugh@veritas.com>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
Reviewed-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-of-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-09-29 14:42:57 +00:00
|
|
|
found = dentry;
|
2005-04-16 22:20:36 +00:00
|
|
|
spin_unlock(&dentry->d_lock);
|
|
|
|
break;
|
|
|
|
next:
|
|
|
|
spin_unlock(&dentry->d_lock);
|
|
|
|
}
|
|
|
|
rcu_read_unlock();
|
|
|
|
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
2006-03-31 10:31:43 +00:00
|
|
|
/**
|
|
|
|
* d_hash_and_lookup - hash the qstr then search for a dentry
|
|
|
|
* @dir: Directory to search in
|
|
|
|
* @name: qstr of name we wish to find
|
|
|
|
*
|
2013-02-12 04:20:37 +00:00
|
|
|
* On lookup failure NULL is returned; on bad name - ERR_PTR(-error)
|
2006-03-31 10:31:43 +00:00
|
|
|
*/
|
|
|
|
struct dentry *d_hash_and_lookup(struct dentry *dir, struct qstr *name)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Check for a fs-specific hash function. Note that we must
|
|
|
|
* calculate the standard hash first, as the d_op->d_hash()
|
|
|
|
* routine may choose to leave the hash value unchanged.
|
|
|
|
*/
|
2016-06-10 14:51:30 +00:00
|
|
|
name->hash = full_name_hash(dir, name->name, name->len);
|
2011-01-07 06:49:55 +00:00
|
|
|
if (dir->d_flags & DCACHE_OP_HASH) {
|
2013-05-21 22:22:44 +00:00
|
|
|
int err = dir->d_op->d_hash(dir, name);
|
2013-02-12 04:20:37 +00:00
|
|
|
if (unlikely(err < 0))
|
|
|
|
return ERR_PTR(err);
|
2006-03-31 10:31:43 +00:00
|
|
|
}
|
2013-02-12 04:20:37 +00:00
|
|
|
return d_lookup(dir, name);
|
2006-03-31 10:31:43 +00:00
|
|
|
}
|
2013-02-12 04:20:37 +00:00
|
|
|
EXPORT_SYMBOL(d_hash_and_lookup);
|
2006-03-31 10:31:43 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* When a file is deleted, we have two options:
|
|
|
|
* - turn this dentry into a negative dentry
|
|
|
|
* - unhash this dentry and free it.
|
|
|
|
*
|
|
|
|
* Usually, we want to just turn this into
|
2024-05-29 16:39:34 +00:00
|
|
|
* a negative dentry, but if anybody else is
|
|
|
|
* currently using the dentry or the inode
|
|
|
|
* we can't do that and we fall back on removing
|
|
|
|
* it from the hash queues and waiting for
|
|
|
|
* it to be deleted later when it has no users
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* d_delete - delete a dentry
|
|
|
|
* @dentry: The dentry to delete
|
|
|
|
*
|
2024-05-29 16:39:34 +00:00
|
|
|
* Turn the dentry into a negative dentry if possible, otherwise
|
|
|
|
* remove it from the hash queues so it can be deleted later
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
void d_delete(struct dentry * dentry)
|
|
|
|
{
|
2018-02-24 02:02:31 +00:00
|
|
|
struct inode *inode = dentry->d_inode;
|
|
|
|
|
|
|
|
spin_lock(&inode->i_lock);
|
|
|
|
spin_lock(&dentry->d_lock);
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* Are we the only user?
|
|
|
|
*/
|
2013-08-29 01:24:59 +00:00
|
|
|
if (dentry->d_lockref.count == 1) {
|
2010-05-21 20:11:04 +00:00
|
|
|
dentry->d_flags &= ~DCACHE_CANT_MOUNT;
|
fs: rcu-walk for path lookup
Perform common cases of path lookups without any stores or locking in the
ancestor dentry elements. This is called rcu-walk, as opposed to the current
algorithm which is a refcount based walk, or ref-walk.
This results in far fewer atomic operations on every path element,
significantly improving path lookup performance. It also avoids cacheline
bouncing on common dentries, significantly improving scalability.
The overall design is like this:
* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
* Take the RCU lock for the entire path walk, starting with the acquiring
of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
not required for dentry persistence.
* synchronize_rcu is called when unregistering a filesystem, so we can
access d_ops and i_ops during rcu-walk.
* Similarly take the vfsmount lock for the entire path walk. So now mnt
refcounts are not required for persistence. Also we are free to perform mount
lookups, and to assume dentry mount points and mount roots are stable up and
down the path.
* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
so we can load this tuple atomically, and also check whether any of its
members have changed.
* Dentry lookups (based on parent, candidate string tuple) recheck the parent
sequence after the child is found in case anything changed in the parent
during the path walk.
* inode is also RCU protected so we can load d_inode and use the inode for
limited things.
* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
* i_op can be loaded.
When we reach the destination dentry, we lock it, recheck lookup sequence,
and increment its refcount and mountpoint refcount. RCU and vfsmount locks
are dropped. This is termed "dropping rcu-walk". If the dentry refcount does
not match, we can not drop rcu-walk gracefully at the current point in the
lokup, so instead return -ECHILD (for want of a better errno). This signals the
path walking code to re-do the entire lookup with a ref-walk.
Aside from the final dentry, there are other situations that may be encounted
where we cannot continue rcu-walk. In that case, we drop rcu-walk (ie. take
a reference on the last good dentry) and continue with a ref-walk. Again, if
we can drop rcu-walk gracefully, we return -ECHILD and do the whole lookup
using ref-walk. But it is very important that we can continue with ref-walk
for most cases, particularly to avoid the overhead of double lookups, and to
gain the scalability advantages on common path elements (like cwd and root).
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links
In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:52 +00:00
|
|
|
dentry_unlink_inode(dentry);
|
2018-02-24 02:02:31 +00:00
|
|
|
} else {
|
2024-05-29 16:39:34 +00:00
|
|
|
__d_drop(dentry);
|
2018-02-24 02:02:31 +00:00
|
|
|
spin_unlock(&dentry->d_lock);
|
|
|
|
spin_unlock(&inode->i_lock);
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2010-01-05 20:45:18 +00:00
|
|
|
EXPORT_SYMBOL(d_delete);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2016-07-29 21:45:21 +00:00
|
|
|
static void __d_rehash(struct dentry *entry)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2016-07-29 21:45:21 +00:00
|
|
|
struct hlist_bl_head *b = d_hash(entry->d_name.hash);
|
2017-11-10 04:45:41 +00:00
|
|
|
|
2011-04-25 18:01:36 +00:00
|
|
|
hlist_bl_lock(b);
|
2011-04-24 05:32:03 +00:00
|
|
|
hlist_bl_add_head_rcu(&entry->d_hash, b);
|
2011-04-25 18:01:36 +00:00
|
|
|
hlist_bl_unlock(b);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* d_rehash - add an entry back to the hash
|
|
|
|
* @entry: dentry to add to the hash
|
|
|
|
*
|
|
|
|
* Adds a dentry to the hash according to its name.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void d_rehash(struct dentry * entry)
|
|
|
|
{
|
|
|
|
spin_lock(&entry->d_lock);
|
2016-07-29 21:45:21 +00:00
|
|
|
__d_rehash(entry);
|
2005-04-16 22:20:36 +00:00
|
|
|
spin_unlock(&entry->d_lock);
|
|
|
|
}
|
2010-01-05 20:45:18 +00:00
|
|
|
EXPORT_SYMBOL(d_rehash);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
parallel lookups machinery, part 2
We'll need to verify that there's neither a hashed nor in-lookup
dentry with desired parent/name before adding to in-lookup set.
One possible solution would be to hold the parent's ->d_lock through
both checks, but while the in-lookup set is relatively small at any
time, dcache is not. And holding the parent's ->d_lock through
something like __d_lookup_rcu() would suck too badly.
So we leave the parent's ->d_lock alone, which means that we watch
out for the following scenario:
* we verify that there's no hashed match
* existing in-lookup match gets hashed by another process
* we verify that there's no in-lookup matches and decide
that everything's fine.
Solution: per-directory kinda-sorta seqlock, bumped around the times
we hash something that used to be in-lookup or move (and hash)
something in place of in-lookup. Then the above would turn into
* read the counter
* do dcache lookup
* if no matches found, check for in-lookup matches
* if there had been none of those either, check if the
counter has changed; repeat if it has.
The "kinda-sorta" part is due to the fact that we don't have much spare
space in inode. There is a spare word (shared with i_bdev/i_cdev/i_pipe),
so the counter part is not a problem, but spinlock is a different story.
We could use the parent's ->d_lock, and it would be less painful in
terms of contention, for __d_add() it would be rather inconvenient to
grab; we could do that (using lock_parent()), but...
Fortunately, we can get serialization on the counter itself, and it
might be a good idea in general; we can use cmpxchg() in a loop to
get from even to odd and smp_store_release() from odd to even.
This commit adds the counter and updating logics; the readers will be
added in the next commit.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2016-04-15 04:58:55 +00:00
|
|
|
static inline unsigned start_dir_add(struct inode *dir)
|
|
|
|
{
|
2022-08-25 16:41:25 +00:00
|
|
|
preempt_disable_nested();
|
parallel lookups machinery, part 2
We'll need to verify that there's neither a hashed nor in-lookup
dentry with desired parent/name before adding to in-lookup set.
One possible solution would be to hold the parent's ->d_lock through
both checks, but while the in-lookup set is relatively small at any
time, dcache is not. And holding the parent's ->d_lock through
something like __d_lookup_rcu() would suck too badly.
So we leave the parent's ->d_lock alone, which means that we watch
out for the following scenario:
* we verify that there's no hashed match
* existing in-lookup match gets hashed by another process
* we verify that there's no in-lookup matches and decide
that everything's fine.
Solution: per-directory kinda-sorta seqlock, bumped around the times
we hash something that used to be in-lookup or move (and hash)
something in place of in-lookup. Then the above would turn into
* read the counter
* do dcache lookup
* if no matches found, check for in-lookup matches
* if there had been none of those either, check if the
counter has changed; repeat if it has.
The "kinda-sorta" part is due to the fact that we don't have much spare
space in inode. There is a spare word (shared with i_bdev/i_cdev/i_pipe),
so the counter part is not a problem, but spinlock is a different story.
We could use the parent's ->d_lock, and it would be less painful in
terms of contention, for __d_add() it would be rather inconvenient to
grab; we could do that (using lock_parent()), but...
Fortunately, we can get serialization on the counter itself, and it
might be a good idea in general; we can use cmpxchg() in a loop to
get from even to odd and smp_store_release() from odd to even.
This commit adds the counter and updating logics; the readers will be
added in the next commit.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2016-04-15 04:58:55 +00:00
|
|
|
for (;;) {
|
|
|
|
unsigned n = dir->i_dir_seq;
|
|
|
|
if (!(n & 1) && cmpxchg(&dir->i_dir_seq, n, n + 1) == n)
|
|
|
|
return n;
|
|
|
|
cpu_relax();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-27 11:49:04 +00:00
|
|
|
static inline void end_dir_add(struct inode *dir, unsigned int n,
|
|
|
|
wait_queue_head_t *d_wait)
|
parallel lookups machinery, part 2
We'll need to verify that there's neither a hashed nor in-lookup
dentry with desired parent/name before adding to in-lookup set.
One possible solution would be to hold the parent's ->d_lock through
both checks, but while the in-lookup set is relatively small at any
time, dcache is not. And holding the parent's ->d_lock through
something like __d_lookup_rcu() would suck too badly.
So we leave the parent's ->d_lock alone, which means that we watch
out for the following scenario:
* we verify that there's no hashed match
* existing in-lookup match gets hashed by another process
* we verify that there's no in-lookup matches and decide
that everything's fine.
Solution: per-directory kinda-sorta seqlock, bumped around the times
we hash something that used to be in-lookup or move (and hash)
something in place of in-lookup. Then the above would turn into
* read the counter
* do dcache lookup
* if no matches found, check for in-lookup matches
* if there had been none of those either, check if the
counter has changed; repeat if it has.
The "kinda-sorta" part is due to the fact that we don't have much spare
space in inode. There is a spare word (shared with i_bdev/i_cdev/i_pipe),
so the counter part is not a problem, but spinlock is a different story.
We could use the parent's ->d_lock, and it would be less painful in
terms of contention, for __d_add() it would be rather inconvenient to
grab; we could do that (using lock_parent()), but...
Fortunately, we can get serialization on the counter itself, and it
might be a good idea in general; we can use cmpxchg() in a loop to
get from even to odd and smp_store_release() from odd to even.
This commit adds the counter and updating logics; the readers will be
added in the next commit.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2016-04-15 04:58:55 +00:00
|
|
|
{
|
|
|
|
smp_store_release(&dir->i_dir_seq, n + 2);
|
2022-08-25 16:41:25 +00:00
|
|
|
preempt_enable_nested();
|
2022-07-27 11:49:04 +00:00
|
|
|
wake_up_all(d_wait);
|
parallel lookups machinery, part 2
We'll need to verify that there's neither a hashed nor in-lookup
dentry with desired parent/name before adding to in-lookup set.
One possible solution would be to hold the parent's ->d_lock through
both checks, but while the in-lookup set is relatively small at any
time, dcache is not. And holding the parent's ->d_lock through
something like __d_lookup_rcu() would suck too badly.
So we leave the parent's ->d_lock alone, which means that we watch
out for the following scenario:
* we verify that there's no hashed match
* existing in-lookup match gets hashed by another process
* we verify that there's no in-lookup matches and decide
that everything's fine.
Solution: per-directory kinda-sorta seqlock, bumped around the times
we hash something that used to be in-lookup or move (and hash)
something in place of in-lookup. Then the above would turn into
* read the counter
* do dcache lookup
* if no matches found, check for in-lookup matches
* if there had been none of those either, check if the
counter has changed; repeat if it has.
The "kinda-sorta" part is due to the fact that we don't have much spare
space in inode. There is a spare word (shared with i_bdev/i_cdev/i_pipe),
so the counter part is not a problem, but spinlock is a different story.
We could use the parent's ->d_lock, and it would be less painful in
terms of contention, for __d_add() it would be rather inconvenient to
grab; we could do that (using lock_parent()), but...
Fortunately, we can get serialization on the counter itself, and it
might be a good idea in general; we can use cmpxchg() in a loop to
get from even to odd and smp_store_release() from odd to even.
This commit adds the counter and updating logics; the readers will be
added in the next commit.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2016-04-15 04:58:55 +00:00
|
|
|
}
|
|
|
|
|
2016-04-15 07:33:13 +00:00
|
|
|
static void d_wait_lookup(struct dentry *dentry)
|
|
|
|
{
|
|
|
|
if (d_in_lookup(dentry)) {
|
|
|
|
DECLARE_WAITQUEUE(wait, current);
|
|
|
|
add_wait_queue(dentry->d_wait, &wait);
|
|
|
|
do {
|
|
|
|
set_current_state(TASK_UNINTERRUPTIBLE);
|
|
|
|
spin_unlock(&dentry->d_lock);
|
|
|
|
schedule();
|
|
|
|
spin_lock(&dentry->d_lock);
|
|
|
|
} while (d_in_lookup(dentry));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-15 06:42:04 +00:00
|
|
|
struct dentry *d_alloc_parallel(struct dentry *parent,
|
2016-04-15 07:33:13 +00:00
|
|
|
const struct qstr *name,
|
|
|
|
wait_queue_head_t *wq)
|
2016-04-15 06:42:04 +00:00
|
|
|
{
|
|
|
|
unsigned int hash = name->hash;
|
|
|
|
struct hlist_bl_head *b = in_lookup_hash(parent, hash);
|
|
|
|
struct hlist_bl_node *node;
|
|
|
|
struct dentry *new = d_alloc(parent, name);
|
|
|
|
struct dentry *dentry;
|
|
|
|
unsigned seq, r_seq, d_seq;
|
|
|
|
|
|
|
|
if (unlikely(!new))
|
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
|
|
|
retry:
|
|
|
|
rcu_read_lock();
|
2018-02-19 14:55:54 +00:00
|
|
|
seq = smp_load_acquire(&parent->d_inode->i_dir_seq);
|
2016-04-15 06:42:04 +00:00
|
|
|
r_seq = read_seqbegin(&rename_lock);
|
|
|
|
dentry = __d_lookup_rcu(parent, name, &d_seq);
|
|
|
|
if (unlikely(dentry)) {
|
|
|
|
if (!lockref_get_not_dead(&dentry->d_lockref)) {
|
|
|
|
rcu_read_unlock();
|
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
if (read_seqcount_retry(&dentry->d_seq, d_seq)) {
|
|
|
|
rcu_read_unlock();
|
|
|
|
dput(dentry);
|
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
rcu_read_unlock();
|
|
|
|
dput(new);
|
|
|
|
return dentry;
|
|
|
|
}
|
|
|
|
if (unlikely(read_seqretry(&rename_lock, r_seq))) {
|
|
|
|
rcu_read_unlock();
|
|
|
|
goto retry;
|
|
|
|
}
|
2018-02-19 14:55:54 +00:00
|
|
|
|
|
|
|
if (unlikely(seq & 1)) {
|
|
|
|
rcu_read_unlock();
|
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
|
2016-04-15 06:42:04 +00:00
|
|
|
hlist_bl_lock(b);
|
2018-02-19 14:55:55 +00:00
|
|
|
if (unlikely(READ_ONCE(parent->d_inode->i_dir_seq) != seq)) {
|
2016-04-15 06:42:04 +00:00
|
|
|
hlist_bl_unlock(b);
|
|
|
|
rcu_read_unlock();
|
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* No changes for the parent since the beginning of d_lookup().
|
|
|
|
* Since all removals from the chain happen with hlist_bl_lock(),
|
|
|
|
* any potential in-lookup matches are going to stay here until
|
|
|
|
* we unlock the chain. All fields are stable in everything
|
|
|
|
* we encounter.
|
|
|
|
*/
|
|
|
|
hlist_bl_for_each_entry(dentry, node, b, d_u.d_in_lookup_hash) {
|
|
|
|
if (dentry->d_name.hash != hash)
|
|
|
|
continue;
|
|
|
|
if (dentry->d_parent != parent)
|
|
|
|
continue;
|
2016-06-26 03:33:49 +00:00
|
|
|
if (!d_same_name(dentry, parent, name))
|
|
|
|
continue;
|
2016-04-15 06:42:04 +00:00
|
|
|
hlist_bl_unlock(b);
|
2016-06-20 05:35:59 +00:00
|
|
|
/* now we can try to grab a reference */
|
|
|
|
if (!lockref_get_not_dead(&dentry->d_lockref)) {
|
|
|
|
rcu_read_unlock();
|
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
|
|
|
|
rcu_read_unlock();
|
|
|
|
/*
|
|
|
|
* somebody is likely to be still doing lookup for it;
|
|
|
|
* wait for them to finish
|
|
|
|
*/
|
2016-04-15 07:33:13 +00:00
|
|
|
spin_lock(&dentry->d_lock);
|
|
|
|
d_wait_lookup(dentry);
|
|
|
|
/*
|
|
|
|
* it's not in-lookup anymore; in principle we should repeat
|
|
|
|
* everything from dcache lookup, but it's likely to be what
|
|
|
|
* d_lookup() would've found anyway. If it is, just return it;
|
|
|
|
* otherwise we really have to repeat the whole thing.
|
|
|
|
*/
|
|
|
|
if (unlikely(dentry->d_name.hash != hash))
|
|
|
|
goto mismatch;
|
|
|
|
if (unlikely(dentry->d_parent != parent))
|
|
|
|
goto mismatch;
|
|
|
|
if (unlikely(d_unhashed(dentry)))
|
|
|
|
goto mismatch;
|
2016-06-26 03:33:49 +00:00
|
|
|
if (unlikely(!d_same_name(dentry, parent, name)))
|
|
|
|
goto mismatch;
|
2016-04-15 07:33:13 +00:00
|
|
|
/* OK, it *is* a hashed match; return it */
|
|
|
|
spin_unlock(&dentry->d_lock);
|
2016-04-15 06:42:04 +00:00
|
|
|
dput(new);
|
|
|
|
return dentry;
|
|
|
|
}
|
2016-06-20 05:35:59 +00:00
|
|
|
rcu_read_unlock();
|
2016-04-15 06:42:04 +00:00
|
|
|
/* we can't take ->d_lock here; it's OK, though. */
|
|
|
|
new->d_flags |= DCACHE_PAR_LOOKUP;
|
2016-04-15 07:33:13 +00:00
|
|
|
new->d_wait = wq;
|
2023-11-12 05:38:02 +00:00
|
|
|
hlist_bl_add_head(&new->d_u.d_in_lookup_hash, b);
|
2016-04-15 06:42:04 +00:00
|
|
|
hlist_bl_unlock(b);
|
|
|
|
return new;
|
2016-04-15 07:33:13 +00:00
|
|
|
mismatch:
|
|
|
|
spin_unlock(&dentry->d_lock);
|
|
|
|
dput(dentry);
|
|
|
|
goto retry;
|
2016-04-15 06:42:04 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(d_alloc_parallel);
|
|
|
|
|
fs/dcache: Move the wakeup from __d_lookup_done() to the caller.
__d_lookup_done() wakes waiters on dentry->d_wait. On PREEMPT_RT we are
not allowed to do that with preemption disabled, since the wakeup
acquired wait_queue_head::lock, which is a "sleeping" spinlock on RT.
Calling it under dentry->d_lock is not a problem, since that is also a
"sleeping" spinlock on the same configs. Unfortunately, two of its
callers (__d_add() and __d_move()) are holding more than just ->d_lock
and that needs to be dealt with.
The key observation is that wakeup can be moved to any point before
dropping ->d_lock.
As a first step to solve this, move the wake up outside of the
hlist_bl_lock() held section.
This is safe because:
Waiters get inserted into ->d_wait only after they'd taken ->d_lock
and observed DCACHE_PAR_LOOKUP in flags. As long as they are
woken up (and evicted from the queue) between the moment __d_lookup_done()
has removed DCACHE_PAR_LOOKUP and dropping ->d_lock, we are safe,
since the waitqueue ->d_wait points to won't get destroyed without
having __d_lookup_done(dentry) called (under ->d_lock).
->d_wait is set only by d_alloc_parallel() and only in case when
it returns a freshly allocated in-lookup dentry. Whenever that happens,
we are guaranteed that __d_lookup_done() will be called for resulting
dentry (under ->d_lock) before the wq in question gets destroyed.
With two exceptions wq lives in call frame of the caller of
d_alloc_parallel() and we have an explicit d_lookup_done() on the
resulting in-lookup dentry before we leave that frame.
One of those exceptions is nfs_call_unlink(), where wq is embedded into
(dynamically allocated) struct nfs_unlinkdata. It is destroyed in
nfs_async_unlink_release() after an explicit d_lookup_done() on the
dentry wq went into.
Remaining exception is d_add_ci(). There wq is what we'd found in
->d_wait of d_add_ci() argument. Callers of d_add_ci() are two
instances of ->d_lookup() and they must have been given an in-lookup
dentry. Which means that they'd been called by __lookup_slow() or
lookup_open(), with wq in the call frame of one of those.
Result of d_alloc_parallel() in d_add_ci() is fed to
d_splice_alias(), which either returns non-NULL (and d_add_ci() does
d_lookup_done()) or feeds dentry to __d_add() that will do
__d_lookup_done() under ->d_lock. That concludes the analysis.
Let __d_lookup_unhash():
1) Lock the lookup hash and clear DCACHE_PAR_LOOKUP
2) Unhash the dentry
3) Retrieve and clear dentry::d_wait
4) Unlock the hash and return the retrieved waitqueue head pointer
5) Let the caller handle the wake up.
6) Rename __d_lookup_done() to __d_lookup_unhash_wake() to enforce
build failures for OOT code that used __d_lookup_done() and is not
aware of the new return value.
This does not yet solve the PREEMPT_RT problem completely because
preemption is still disabled due to i_dir_seq being held for write. This
will be addressed in subsequent steps.
An alternative solution would be to switch the waitqueue to a simple
waitqueue, but aside of Linus not being a fan of them, moving the wake up
closer to the place where dentry::lock is unlocked reduces lock contention
time for the woken up waiter.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Link: https://lkml.kernel.org/r/20220613140712.77932-3-bigeasy@linutronix.de
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2022-07-27 11:49:03 +00:00
|
|
|
/*
|
|
|
|
* - Unhash the dentry
|
|
|
|
* - Retrieve and clear the waitqueue head in dentry
|
|
|
|
* - Return the waitqueue head
|
|
|
|
*/
|
|
|
|
static wait_queue_head_t *__d_lookup_unhash(struct dentry *dentry)
|
2016-04-14 23:52:13 +00:00
|
|
|
{
|
fs/dcache: Move the wakeup from __d_lookup_done() to the caller.
__d_lookup_done() wakes waiters on dentry->d_wait. On PREEMPT_RT we are
not allowed to do that with preemption disabled, since the wakeup
acquired wait_queue_head::lock, which is a "sleeping" spinlock on RT.
Calling it under dentry->d_lock is not a problem, since that is also a
"sleeping" spinlock on the same configs. Unfortunately, two of its
callers (__d_add() and __d_move()) are holding more than just ->d_lock
and that needs to be dealt with.
The key observation is that wakeup can be moved to any point before
dropping ->d_lock.
As a first step to solve this, move the wake up outside of the
hlist_bl_lock() held section.
This is safe because:
Waiters get inserted into ->d_wait only after they'd taken ->d_lock
and observed DCACHE_PAR_LOOKUP in flags. As long as they are
woken up (and evicted from the queue) between the moment __d_lookup_done()
has removed DCACHE_PAR_LOOKUP and dropping ->d_lock, we are safe,
since the waitqueue ->d_wait points to won't get destroyed without
having __d_lookup_done(dentry) called (under ->d_lock).
->d_wait is set only by d_alloc_parallel() and only in case when
it returns a freshly allocated in-lookup dentry. Whenever that happens,
we are guaranteed that __d_lookup_done() will be called for resulting
dentry (under ->d_lock) before the wq in question gets destroyed.
With two exceptions wq lives in call frame of the caller of
d_alloc_parallel() and we have an explicit d_lookup_done() on the
resulting in-lookup dentry before we leave that frame.
One of those exceptions is nfs_call_unlink(), where wq is embedded into
(dynamically allocated) struct nfs_unlinkdata. It is destroyed in
nfs_async_unlink_release() after an explicit d_lookup_done() on the
dentry wq went into.
Remaining exception is d_add_ci(). There wq is what we'd found in
->d_wait of d_add_ci() argument. Callers of d_add_ci() are two
instances of ->d_lookup() and they must have been given an in-lookup
dentry. Which means that they'd been called by __lookup_slow() or
lookup_open(), with wq in the call frame of one of those.
Result of d_alloc_parallel() in d_add_ci() is fed to
d_splice_alias(), which either returns non-NULL (and d_add_ci() does
d_lookup_done()) or feeds dentry to __d_add() that will do
__d_lookup_done() under ->d_lock. That concludes the analysis.
Let __d_lookup_unhash():
1) Lock the lookup hash and clear DCACHE_PAR_LOOKUP
2) Unhash the dentry
3) Retrieve and clear dentry::d_wait
4) Unlock the hash and return the retrieved waitqueue head pointer
5) Let the caller handle the wake up.
6) Rename __d_lookup_done() to __d_lookup_unhash_wake() to enforce
build failures for OOT code that used __d_lookup_done() and is not
aware of the new return value.
This does not yet solve the PREEMPT_RT problem completely because
preemption is still disabled due to i_dir_seq being held for write. This
will be addressed in subsequent steps.
An alternative solution would be to switch the waitqueue to a simple
waitqueue, but aside of Linus not being a fan of them, moving the wake up
closer to the place where dentry::lock is unlocked reduces lock contention
time for the woken up waiter.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Link: https://lkml.kernel.org/r/20220613140712.77932-3-bigeasy@linutronix.de
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2022-07-27 11:49:03 +00:00
|
|
|
wait_queue_head_t *d_wait;
|
|
|
|
struct hlist_bl_head *b;
|
|
|
|
|
|
|
|
lockdep_assert_held(&dentry->d_lock);
|
|
|
|
|
|
|
|
b = in_lookup_hash(dentry->d_parent, dentry->d_name.hash);
|
2016-04-15 06:42:04 +00:00
|
|
|
hlist_bl_lock(b);
|
2016-04-14 23:52:13 +00:00
|
|
|
dentry->d_flags &= ~DCACHE_PAR_LOOKUP;
|
2016-04-15 06:42:04 +00:00
|
|
|
__hlist_bl_del(&dentry->d_u.d_in_lookup_hash);
|
fs/dcache: Move the wakeup from __d_lookup_done() to the caller.
__d_lookup_done() wakes waiters on dentry->d_wait. On PREEMPT_RT we are
not allowed to do that with preemption disabled, since the wakeup
acquired wait_queue_head::lock, which is a "sleeping" spinlock on RT.
Calling it under dentry->d_lock is not a problem, since that is also a
"sleeping" spinlock on the same configs. Unfortunately, two of its
callers (__d_add() and __d_move()) are holding more than just ->d_lock
and that needs to be dealt with.
The key observation is that wakeup can be moved to any point before
dropping ->d_lock.
As a first step to solve this, move the wake up outside of the
hlist_bl_lock() held section.
This is safe because:
Waiters get inserted into ->d_wait only after they'd taken ->d_lock
and observed DCACHE_PAR_LOOKUP in flags. As long as they are
woken up (and evicted from the queue) between the moment __d_lookup_done()
has removed DCACHE_PAR_LOOKUP and dropping ->d_lock, we are safe,
since the waitqueue ->d_wait points to won't get destroyed without
having __d_lookup_done(dentry) called (under ->d_lock).
->d_wait is set only by d_alloc_parallel() and only in case when
it returns a freshly allocated in-lookup dentry. Whenever that happens,
we are guaranteed that __d_lookup_done() will be called for resulting
dentry (under ->d_lock) before the wq in question gets destroyed.
With two exceptions wq lives in call frame of the caller of
d_alloc_parallel() and we have an explicit d_lookup_done() on the
resulting in-lookup dentry before we leave that frame.
One of those exceptions is nfs_call_unlink(), where wq is embedded into
(dynamically allocated) struct nfs_unlinkdata. It is destroyed in
nfs_async_unlink_release() after an explicit d_lookup_done() on the
dentry wq went into.
Remaining exception is d_add_ci(). There wq is what we'd found in
->d_wait of d_add_ci() argument. Callers of d_add_ci() are two
instances of ->d_lookup() and they must have been given an in-lookup
dentry. Which means that they'd been called by __lookup_slow() or
lookup_open(), with wq in the call frame of one of those.
Result of d_alloc_parallel() in d_add_ci() is fed to
d_splice_alias(), which either returns non-NULL (and d_add_ci() does
d_lookup_done()) or feeds dentry to __d_add() that will do
__d_lookup_done() under ->d_lock. That concludes the analysis.
Let __d_lookup_unhash():
1) Lock the lookup hash and clear DCACHE_PAR_LOOKUP
2) Unhash the dentry
3) Retrieve and clear dentry::d_wait
4) Unlock the hash and return the retrieved waitqueue head pointer
5) Let the caller handle the wake up.
6) Rename __d_lookup_done() to __d_lookup_unhash_wake() to enforce
build failures for OOT code that used __d_lookup_done() and is not
aware of the new return value.
This does not yet solve the PREEMPT_RT problem completely because
preemption is still disabled due to i_dir_seq being held for write. This
will be addressed in subsequent steps.
An alternative solution would be to switch the waitqueue to a simple
waitqueue, but aside of Linus not being a fan of them, moving the wake up
closer to the place where dentry::lock is unlocked reduces lock contention
time for the woken up waiter.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Link: https://lkml.kernel.org/r/20220613140712.77932-3-bigeasy@linutronix.de
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2022-07-27 11:49:03 +00:00
|
|
|
d_wait = dentry->d_wait;
|
2016-04-15 07:33:13 +00:00
|
|
|
dentry->d_wait = NULL;
|
2016-04-15 06:42:04 +00:00
|
|
|
hlist_bl_unlock(b);
|
|
|
|
INIT_HLIST_NODE(&dentry->d_u.d_alias);
|
2016-04-15 07:33:13 +00:00
|
|
|
INIT_LIST_HEAD(&dentry->d_lru);
|
fs/dcache: Move the wakeup from __d_lookup_done() to the caller.
__d_lookup_done() wakes waiters on dentry->d_wait. On PREEMPT_RT we are
not allowed to do that with preemption disabled, since the wakeup
acquired wait_queue_head::lock, which is a "sleeping" spinlock on RT.
Calling it under dentry->d_lock is not a problem, since that is also a
"sleeping" spinlock on the same configs. Unfortunately, two of its
callers (__d_add() and __d_move()) are holding more than just ->d_lock
and that needs to be dealt with.
The key observation is that wakeup can be moved to any point before
dropping ->d_lock.
As a first step to solve this, move the wake up outside of the
hlist_bl_lock() held section.
This is safe because:
Waiters get inserted into ->d_wait only after they'd taken ->d_lock
and observed DCACHE_PAR_LOOKUP in flags. As long as they are
woken up (and evicted from the queue) between the moment __d_lookup_done()
has removed DCACHE_PAR_LOOKUP and dropping ->d_lock, we are safe,
since the waitqueue ->d_wait points to won't get destroyed without
having __d_lookup_done(dentry) called (under ->d_lock).
->d_wait is set only by d_alloc_parallel() and only in case when
it returns a freshly allocated in-lookup dentry. Whenever that happens,
we are guaranteed that __d_lookup_done() will be called for resulting
dentry (under ->d_lock) before the wq in question gets destroyed.
With two exceptions wq lives in call frame of the caller of
d_alloc_parallel() and we have an explicit d_lookup_done() on the
resulting in-lookup dentry before we leave that frame.
One of those exceptions is nfs_call_unlink(), where wq is embedded into
(dynamically allocated) struct nfs_unlinkdata. It is destroyed in
nfs_async_unlink_release() after an explicit d_lookup_done() on the
dentry wq went into.
Remaining exception is d_add_ci(). There wq is what we'd found in
->d_wait of d_add_ci() argument. Callers of d_add_ci() are two
instances of ->d_lookup() and they must have been given an in-lookup
dentry. Which means that they'd been called by __lookup_slow() or
lookup_open(), with wq in the call frame of one of those.
Result of d_alloc_parallel() in d_add_ci() is fed to
d_splice_alias(), which either returns non-NULL (and d_add_ci() does
d_lookup_done()) or feeds dentry to __d_add() that will do
__d_lookup_done() under ->d_lock. That concludes the analysis.
Let __d_lookup_unhash():
1) Lock the lookup hash and clear DCACHE_PAR_LOOKUP
2) Unhash the dentry
3) Retrieve and clear dentry::d_wait
4) Unlock the hash and return the retrieved waitqueue head pointer
5) Let the caller handle the wake up.
6) Rename __d_lookup_done() to __d_lookup_unhash_wake() to enforce
build failures for OOT code that used __d_lookup_done() and is not
aware of the new return value.
This does not yet solve the PREEMPT_RT problem completely because
preemption is still disabled due to i_dir_seq being held for write. This
will be addressed in subsequent steps.
An alternative solution would be to switch the waitqueue to a simple
waitqueue, but aside of Linus not being a fan of them, moving the wake up
closer to the place where dentry::lock is unlocked reduces lock contention
time for the woken up waiter.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Link: https://lkml.kernel.org/r/20220613140712.77932-3-bigeasy@linutronix.de
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2022-07-27 11:49:03 +00:00
|
|
|
return d_wait;
|
|
|
|
}
|
|
|
|
|
|
|
|
void __d_lookup_unhash_wake(struct dentry *dentry)
|
|
|
|
{
|
|
|
|
spin_lock(&dentry->d_lock);
|
|
|
|
wake_up_all(__d_lookup_unhash(dentry));
|
|
|
|
spin_unlock(&dentry->d_lock);
|
2016-04-14 23:52:13 +00:00
|
|
|
}
|
fs/dcache: Move the wakeup from __d_lookup_done() to the caller.
__d_lookup_done() wakes waiters on dentry->d_wait. On PREEMPT_RT we are
not allowed to do that with preemption disabled, since the wakeup
acquired wait_queue_head::lock, which is a "sleeping" spinlock on RT.
Calling it under dentry->d_lock is not a problem, since that is also a
"sleeping" spinlock on the same configs. Unfortunately, two of its
callers (__d_add() and __d_move()) are holding more than just ->d_lock
and that needs to be dealt with.
The key observation is that wakeup can be moved to any point before
dropping ->d_lock.
As a first step to solve this, move the wake up outside of the
hlist_bl_lock() held section.
This is safe because:
Waiters get inserted into ->d_wait only after they'd taken ->d_lock
and observed DCACHE_PAR_LOOKUP in flags. As long as they are
woken up (and evicted from the queue) between the moment __d_lookup_done()
has removed DCACHE_PAR_LOOKUP and dropping ->d_lock, we are safe,
since the waitqueue ->d_wait points to won't get destroyed without
having __d_lookup_done(dentry) called (under ->d_lock).
->d_wait is set only by d_alloc_parallel() and only in case when
it returns a freshly allocated in-lookup dentry. Whenever that happens,
we are guaranteed that __d_lookup_done() will be called for resulting
dentry (under ->d_lock) before the wq in question gets destroyed.
With two exceptions wq lives in call frame of the caller of
d_alloc_parallel() and we have an explicit d_lookup_done() on the
resulting in-lookup dentry before we leave that frame.
One of those exceptions is nfs_call_unlink(), where wq is embedded into
(dynamically allocated) struct nfs_unlinkdata. It is destroyed in
nfs_async_unlink_release() after an explicit d_lookup_done() on the
dentry wq went into.
Remaining exception is d_add_ci(). There wq is what we'd found in
->d_wait of d_add_ci() argument. Callers of d_add_ci() are two
instances of ->d_lookup() and they must have been given an in-lookup
dentry. Which means that they'd been called by __lookup_slow() or
lookup_open(), with wq in the call frame of one of those.
Result of d_alloc_parallel() in d_add_ci() is fed to
d_splice_alias(), which either returns non-NULL (and d_add_ci() does
d_lookup_done()) or feeds dentry to __d_add() that will do
__d_lookup_done() under ->d_lock. That concludes the analysis.
Let __d_lookup_unhash():
1) Lock the lookup hash and clear DCACHE_PAR_LOOKUP
2) Unhash the dentry
3) Retrieve and clear dentry::d_wait
4) Unlock the hash and return the retrieved waitqueue head pointer
5) Let the caller handle the wake up.
6) Rename __d_lookup_done() to __d_lookup_unhash_wake() to enforce
build failures for OOT code that used __d_lookup_done() and is not
aware of the new return value.
This does not yet solve the PREEMPT_RT problem completely because
preemption is still disabled due to i_dir_seq being held for write. This
will be addressed in subsequent steps.
An alternative solution would be to switch the waitqueue to a simple
waitqueue, but aside of Linus not being a fan of them, moving the wake up
closer to the place where dentry::lock is unlocked reduces lock contention
time for the woken up waiter.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Link: https://lkml.kernel.org/r/20220613140712.77932-3-bigeasy@linutronix.de
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2022-07-27 11:49:03 +00:00
|
|
|
EXPORT_SYMBOL(__d_lookup_unhash_wake);
|
2016-03-10 00:52:39 +00:00
|
|
|
|
|
|
|
/* inode->i_lock held if inode is non-NULL */
|
|
|
|
|
|
|
|
static inline void __d_add(struct dentry *dentry, struct inode *inode)
|
|
|
|
{
|
fs/dcache: Move the wakeup from __d_lookup_done() to the caller.
__d_lookup_done() wakes waiters on dentry->d_wait. On PREEMPT_RT we are
not allowed to do that with preemption disabled, since the wakeup
acquired wait_queue_head::lock, which is a "sleeping" spinlock on RT.
Calling it under dentry->d_lock is not a problem, since that is also a
"sleeping" spinlock on the same configs. Unfortunately, two of its
callers (__d_add() and __d_move()) are holding more than just ->d_lock
and that needs to be dealt with.
The key observation is that wakeup can be moved to any point before
dropping ->d_lock.
As a first step to solve this, move the wake up outside of the
hlist_bl_lock() held section.
This is safe because:
Waiters get inserted into ->d_wait only after they'd taken ->d_lock
and observed DCACHE_PAR_LOOKUP in flags. As long as they are
woken up (and evicted from the queue) between the moment __d_lookup_done()
has removed DCACHE_PAR_LOOKUP and dropping ->d_lock, we are safe,
since the waitqueue ->d_wait points to won't get destroyed without
having __d_lookup_done(dentry) called (under ->d_lock).
->d_wait is set only by d_alloc_parallel() and only in case when
it returns a freshly allocated in-lookup dentry. Whenever that happens,
we are guaranteed that __d_lookup_done() will be called for resulting
dentry (under ->d_lock) before the wq in question gets destroyed.
With two exceptions wq lives in call frame of the caller of
d_alloc_parallel() and we have an explicit d_lookup_done() on the
resulting in-lookup dentry before we leave that frame.
One of those exceptions is nfs_call_unlink(), where wq is embedded into
(dynamically allocated) struct nfs_unlinkdata. It is destroyed in
nfs_async_unlink_release() after an explicit d_lookup_done() on the
dentry wq went into.
Remaining exception is d_add_ci(). There wq is what we'd found in
->d_wait of d_add_ci() argument. Callers of d_add_ci() are two
instances of ->d_lookup() and they must have been given an in-lookup
dentry. Which means that they'd been called by __lookup_slow() or
lookup_open(), with wq in the call frame of one of those.
Result of d_alloc_parallel() in d_add_ci() is fed to
d_splice_alias(), which either returns non-NULL (and d_add_ci() does
d_lookup_done()) or feeds dentry to __d_add() that will do
__d_lookup_done() under ->d_lock. That concludes the analysis.
Let __d_lookup_unhash():
1) Lock the lookup hash and clear DCACHE_PAR_LOOKUP
2) Unhash the dentry
3) Retrieve and clear dentry::d_wait
4) Unlock the hash and return the retrieved waitqueue head pointer
5) Let the caller handle the wake up.
6) Rename __d_lookup_done() to __d_lookup_unhash_wake() to enforce
build failures for OOT code that used __d_lookup_done() and is not
aware of the new return value.
This does not yet solve the PREEMPT_RT problem completely because
preemption is still disabled due to i_dir_seq being held for write. This
will be addressed in subsequent steps.
An alternative solution would be to switch the waitqueue to a simple
waitqueue, but aside of Linus not being a fan of them, moving the wake up
closer to the place where dentry::lock is unlocked reduces lock contention
time for the woken up waiter.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Link: https://lkml.kernel.org/r/20220613140712.77932-3-bigeasy@linutronix.de
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2022-07-27 11:49:03 +00:00
|
|
|
wait_queue_head_t *d_wait;
|
parallel lookups machinery, part 2
We'll need to verify that there's neither a hashed nor in-lookup
dentry with desired parent/name before adding to in-lookup set.
One possible solution would be to hold the parent's ->d_lock through
both checks, but while the in-lookup set is relatively small at any
time, dcache is not. And holding the parent's ->d_lock through
something like __d_lookup_rcu() would suck too badly.
So we leave the parent's ->d_lock alone, which means that we watch
out for the following scenario:
* we verify that there's no hashed match
* existing in-lookup match gets hashed by another process
* we verify that there's no in-lookup matches and decide
that everything's fine.
Solution: per-directory kinda-sorta seqlock, bumped around the times
we hash something that used to be in-lookup or move (and hash)
something in place of in-lookup. Then the above would turn into
* read the counter
* do dcache lookup
* if no matches found, check for in-lookup matches
* if there had been none of those either, check if the
counter has changed; repeat if it has.
The "kinda-sorta" part is due to the fact that we don't have much spare
space in inode. There is a spare word (shared with i_bdev/i_cdev/i_pipe),
so the counter part is not a problem, but spinlock is a different story.
We could use the parent's ->d_lock, and it would be less painful in
terms of contention, for __d_add() it would be rather inconvenient to
grab; we could do that (using lock_parent()), but...
Fortunately, we can get serialization on the counter itself, and it
might be a good idea in general; we can use cmpxchg() in a loop to
get from even to odd and smp_store_release() from odd to even.
This commit adds the counter and updating logics; the readers will be
added in the next commit.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2016-04-15 04:58:55 +00:00
|
|
|
struct inode *dir = NULL;
|
|
|
|
unsigned n;
|
2016-04-14 23:40:56 +00:00
|
|
|
spin_lock(&dentry->d_lock);
|
parallel lookups machinery, part 2
We'll need to verify that there's neither a hashed nor in-lookup
dentry with desired parent/name before adding to in-lookup set.
One possible solution would be to hold the parent's ->d_lock through
both checks, but while the in-lookup set is relatively small at any
time, dcache is not. And holding the parent's ->d_lock through
something like __d_lookup_rcu() would suck too badly.
So we leave the parent's ->d_lock alone, which means that we watch
out for the following scenario:
* we verify that there's no hashed match
* existing in-lookup match gets hashed by another process
* we verify that there's no in-lookup matches and decide
that everything's fine.
Solution: per-directory kinda-sorta seqlock, bumped around the times
we hash something that used to be in-lookup or move (and hash)
something in place of in-lookup. Then the above would turn into
* read the counter
* do dcache lookup
* if no matches found, check for in-lookup matches
* if there had been none of those either, check if the
counter has changed; repeat if it has.
The "kinda-sorta" part is due to the fact that we don't have much spare
space in inode. There is a spare word (shared with i_bdev/i_cdev/i_pipe),
so the counter part is not a problem, but spinlock is a different story.
We could use the parent's ->d_lock, and it would be less painful in
terms of contention, for __d_add() it would be rather inconvenient to
grab; we could do that (using lock_parent()), but...
Fortunately, we can get serialization on the counter itself, and it
might be a good idea in general; we can use cmpxchg() in a loop to
get from even to odd and smp_store_release() from odd to even.
This commit adds the counter and updating logics; the readers will be
added in the next commit.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2016-04-15 04:58:55 +00:00
|
|
|
if (unlikely(d_in_lookup(dentry))) {
|
|
|
|
dir = dentry->d_parent->d_inode;
|
|
|
|
n = start_dir_add(dir);
|
fs/dcache: Move the wakeup from __d_lookup_done() to the caller.
__d_lookup_done() wakes waiters on dentry->d_wait. On PREEMPT_RT we are
not allowed to do that with preemption disabled, since the wakeup
acquired wait_queue_head::lock, which is a "sleeping" spinlock on RT.
Calling it under dentry->d_lock is not a problem, since that is also a
"sleeping" spinlock on the same configs. Unfortunately, two of its
callers (__d_add() and __d_move()) are holding more than just ->d_lock
and that needs to be dealt with.
The key observation is that wakeup can be moved to any point before
dropping ->d_lock.
As a first step to solve this, move the wake up outside of the
hlist_bl_lock() held section.
This is safe because:
Waiters get inserted into ->d_wait only after they'd taken ->d_lock
and observed DCACHE_PAR_LOOKUP in flags. As long as they are
woken up (and evicted from the queue) between the moment __d_lookup_done()
has removed DCACHE_PAR_LOOKUP and dropping ->d_lock, we are safe,
since the waitqueue ->d_wait points to won't get destroyed without
having __d_lookup_done(dentry) called (under ->d_lock).
->d_wait is set only by d_alloc_parallel() and only in case when
it returns a freshly allocated in-lookup dentry. Whenever that happens,
we are guaranteed that __d_lookup_done() will be called for resulting
dentry (under ->d_lock) before the wq in question gets destroyed.
With two exceptions wq lives in call frame of the caller of
d_alloc_parallel() and we have an explicit d_lookup_done() on the
resulting in-lookup dentry before we leave that frame.
One of those exceptions is nfs_call_unlink(), where wq is embedded into
(dynamically allocated) struct nfs_unlinkdata. It is destroyed in
nfs_async_unlink_release() after an explicit d_lookup_done() on the
dentry wq went into.
Remaining exception is d_add_ci(). There wq is what we'd found in
->d_wait of d_add_ci() argument. Callers of d_add_ci() are two
instances of ->d_lookup() and they must have been given an in-lookup
dentry. Which means that they'd been called by __lookup_slow() or
lookup_open(), with wq in the call frame of one of those.
Result of d_alloc_parallel() in d_add_ci() is fed to
d_splice_alias(), which either returns non-NULL (and d_add_ci() does
d_lookup_done()) or feeds dentry to __d_add() that will do
__d_lookup_done() under ->d_lock. That concludes the analysis.
Let __d_lookup_unhash():
1) Lock the lookup hash and clear DCACHE_PAR_LOOKUP
2) Unhash the dentry
3) Retrieve and clear dentry::d_wait
4) Unlock the hash and return the retrieved waitqueue head pointer
5) Let the caller handle the wake up.
6) Rename __d_lookup_done() to __d_lookup_unhash_wake() to enforce
build failures for OOT code that used __d_lookup_done() and is not
aware of the new return value.
This does not yet solve the PREEMPT_RT problem completely because
preemption is still disabled due to i_dir_seq being held for write. This
will be addressed in subsequent steps.
An alternative solution would be to switch the waitqueue to a simple
waitqueue, but aside of Linus not being a fan of them, moving the wake up
closer to the place where dentry::lock is unlocked reduces lock contention
time for the woken up waiter.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Link: https://lkml.kernel.org/r/20220613140712.77932-3-bigeasy@linutronix.de
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2022-07-27 11:49:03 +00:00
|
|
|
d_wait = __d_lookup_unhash(dentry);
|
parallel lookups machinery, part 2
We'll need to verify that there's neither a hashed nor in-lookup
dentry with desired parent/name before adding to in-lookup set.
One possible solution would be to hold the parent's ->d_lock through
both checks, but while the in-lookup set is relatively small at any
time, dcache is not. And holding the parent's ->d_lock through
something like __d_lookup_rcu() would suck too badly.
So we leave the parent's ->d_lock alone, which means that we watch
out for the following scenario:
* we verify that there's no hashed match
* existing in-lookup match gets hashed by another process
* we verify that there's no in-lookup matches and decide
that everything's fine.
Solution: per-directory kinda-sorta seqlock, bumped around the times
we hash something that used to be in-lookup or move (and hash)
something in place of in-lookup. Then the above would turn into
* read the counter
* do dcache lookup
* if no matches found, check for in-lookup matches
* if there had been none of those either, check if the
counter has changed; repeat if it has.
The "kinda-sorta" part is due to the fact that we don't have much spare
space in inode. There is a spare word (shared with i_bdev/i_cdev/i_pipe),
so the counter part is not a problem, but spinlock is a different story.
We could use the parent's ->d_lock, and it would be less painful in
terms of contention, for __d_add() it would be rather inconvenient to
grab; we could do that (using lock_parent()), but...
Fortunately, we can get serialization on the counter itself, and it
might be a good idea in general; we can use cmpxchg() in a loop to
get from even to odd and smp_store_release() from odd to even.
This commit adds the counter and updating logics; the readers will be
added in the next commit.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2016-04-15 04:58:55 +00:00
|
|
|
}
|
2016-03-10 00:52:39 +00:00
|
|
|
if (inode) {
|
2016-04-14 23:40:56 +00:00
|
|
|
unsigned add_flags = d_flags_for_inode(inode);
|
|
|
|
hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry);
|
|
|
|
raw_write_seqcount_begin(&dentry->d_seq);
|
|
|
|
__d_set_inode_and_type(dentry, inode, add_flags);
|
|
|
|
raw_write_seqcount_end(&dentry->d_seq);
|
2016-05-29 22:35:12 +00:00
|
|
|
fsnotify_update_flags(dentry);
|
2016-03-10 00:52:39 +00:00
|
|
|
}
|
2016-07-29 21:45:21 +00:00
|
|
|
__d_rehash(dentry);
|
parallel lookups machinery, part 2
We'll need to verify that there's neither a hashed nor in-lookup
dentry with desired parent/name before adding to in-lookup set.
One possible solution would be to hold the parent's ->d_lock through
both checks, but while the in-lookup set is relatively small at any
time, dcache is not. And holding the parent's ->d_lock through
something like __d_lookup_rcu() would suck too badly.
So we leave the parent's ->d_lock alone, which means that we watch
out for the following scenario:
* we verify that there's no hashed match
* existing in-lookup match gets hashed by another process
* we verify that there's no in-lookup matches and decide
that everything's fine.
Solution: per-directory kinda-sorta seqlock, bumped around the times
we hash something that used to be in-lookup or move (and hash)
something in place of in-lookup. Then the above would turn into
* read the counter
* do dcache lookup
* if no matches found, check for in-lookup matches
* if there had been none of those either, check if the
counter has changed; repeat if it has.
The "kinda-sorta" part is due to the fact that we don't have much spare
space in inode. There is a spare word (shared with i_bdev/i_cdev/i_pipe),
so the counter part is not a problem, but spinlock is a different story.
We could use the parent's ->d_lock, and it would be less painful in
terms of contention, for __d_add() it would be rather inconvenient to
grab; we could do that (using lock_parent()), but...
Fortunately, we can get serialization on the counter itself, and it
might be a good idea in general; we can use cmpxchg() in a loop to
get from even to odd and smp_store_release() from odd to even.
This commit adds the counter and updating logics; the readers will be
added in the next commit.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2016-04-15 04:58:55 +00:00
|
|
|
if (dir)
|
2022-07-27 11:49:04 +00:00
|
|
|
end_dir_add(dir, n, d_wait);
|
2016-04-14 23:40:56 +00:00
|
|
|
spin_unlock(&dentry->d_lock);
|
|
|
|
if (inode)
|
|
|
|
spin_unlock(&inode->i_lock);
|
2016-03-10 00:52:39 +00:00
|
|
|
}
|
|
|
|
|
2016-03-09 02:01:03 +00:00
|
|
|
/**
|
|
|
|
* d_add - add dentry to hash queues
|
|
|
|
* @entry: dentry to add
|
|
|
|
* @inode: The inode to attach to this dentry
|
|
|
|
*
|
|
|
|
* This adds the entry to the hash queues and initializes @inode.
|
|
|
|
* The entry was actually filled in earlier during d_alloc().
|
|
|
|
*/
|
|
|
|
|
|
|
|
void d_add(struct dentry *entry, struct inode *inode)
|
|
|
|
{
|
2016-04-11 04:53:26 +00:00
|
|
|
if (inode) {
|
|
|
|
security_d_instantiate(entry, inode);
|
2016-03-10 00:52:39 +00:00
|
|
|
spin_lock(&inode->i_lock);
|
2016-04-11 04:53:26 +00:00
|
|
|
}
|
2016-03-10 00:52:39 +00:00
|
|
|
__d_add(entry, inode);
|
2016-03-09 02:01:03 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(d_add);
|
|
|
|
|
2016-03-08 17:44:17 +00:00
|
|
|
/**
|
|
|
|
* d_exact_alias - find and hash an exact unhashed alias
|
|
|
|
* @entry: dentry to add
|
|
|
|
* @inode: The inode to go with this dentry
|
|
|
|
*
|
|
|
|
* If an unhashed dentry with the same name/parent and desired
|
|
|
|
* inode already exists, hash and return it. Otherwise, return
|
|
|
|
* NULL.
|
|
|
|
*
|
|
|
|
* Parent directory should be locked.
|
|
|
|
*/
|
|
|
|
struct dentry *d_exact_alias(struct dentry *entry, struct inode *inode)
|
|
|
|
{
|
|
|
|
struct dentry *alias;
|
|
|
|
unsigned int hash = entry->d_name.hash;
|
|
|
|
|
|
|
|
spin_lock(&inode->i_lock);
|
|
|
|
hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
|
|
|
|
/*
|
|
|
|
* Don't need alias->d_lock here, because aliases with
|
|
|
|
* d_parent == entry->d_parent are not subject to name or
|
|
|
|
* parent changes, because the parent inode i_mutex is held.
|
|
|
|
*/
|
|
|
|
if (alias->d_name.hash != hash)
|
|
|
|
continue;
|
|
|
|
if (alias->d_parent != entry->d_parent)
|
|
|
|
continue;
|
2016-06-26 03:33:49 +00:00
|
|
|
if (!d_same_name(alias, entry->d_parent, &entry->d_name))
|
2016-03-08 17:44:17 +00:00
|
|
|
continue;
|
|
|
|
spin_lock(&alias->d_lock);
|
|
|
|
if (!d_unhashed(alias)) {
|
|
|
|
spin_unlock(&alias->d_lock);
|
|
|
|
alias = NULL;
|
|
|
|
} else {
|
2023-11-06 13:44:17 +00:00
|
|
|
dget_dlock(alias);
|
2016-07-29 21:45:21 +00:00
|
|
|
__d_rehash(alias);
|
2016-03-08 17:44:17 +00:00
|
|
|
spin_unlock(&alias->d_lock);
|
|
|
|
}
|
|
|
|
spin_unlock(&inode->i_lock);
|
|
|
|
return alias;
|
|
|
|
}
|
|
|
|
spin_unlock(&inode->i_lock);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(d_exact_alias);
|
|
|
|
|
Allow sharing external names after __d_move()
* external dentry names get a small structure prepended to them
(struct external_name).
* it contains an atomic refcount, matching the number of struct dentry
instances that have ->d_name.name pointing to that external name. The
first thing free_dentry() does is decrementing refcount of external name,
so the instances that are between the call of free_dentry() and
RCU-delayed actual freeing do not contribute.
* __d_move(x, y, false) makes the name of x equal to the name of y,
external or not. If y has an external name, extra reference is grabbed
and put into x->d_name.name. If x used to have an external name, the
reference to the old name is dropped and, should it reach zero, freeing
is scheduled via kfree_rcu().
* free_dentry() in dentry with external name decrements the refcount of
that name and, should it reach zero, does RCU-delayed call that will
free both the dentry and external name. Otherwise it does what it
used to do, except that __d_free() doesn't even look at ->d_name.name;
it simply frees the dentry.
All non-RCU accesses to dentry external name are safe wrt freeing since they
all should happen before free_dentry() is called. RCU accesses might run
into a dentry seen by free_dentry() or into an old name that got already
dropped by __d_move(); however, in both cases dentry must have been
alive and refer to that name at some point after we'd done rcu_read_lock(),
which means that any freeing must be still pending.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2014-09-29 18:54:27 +00:00
|
|
|
static void swap_names(struct dentry *dentry, struct dentry *target)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
Allow sharing external names after __d_move()
* external dentry names get a small structure prepended to them
(struct external_name).
* it contains an atomic refcount, matching the number of struct dentry
instances that have ->d_name.name pointing to that external name. The
first thing free_dentry() does is decrementing refcount of external name,
so the instances that are between the call of free_dentry() and
RCU-delayed actual freeing do not contribute.
* __d_move(x, y, false) makes the name of x equal to the name of y,
external or not. If y has an external name, extra reference is grabbed
and put into x->d_name.name. If x used to have an external name, the
reference to the old name is dropped and, should it reach zero, freeing
is scheduled via kfree_rcu().
* free_dentry() in dentry with external name decrements the refcount of
that name and, should it reach zero, does RCU-delayed call that will
free both the dentry and external name. Otherwise it does what it
used to do, except that __d_free() doesn't even look at ->d_name.name;
it simply frees the dentry.
All non-RCU accesses to dentry external name are safe wrt freeing since they
all should happen before free_dentry() is called. RCU accesses might run
into a dentry seen by free_dentry() or into an old name that got already
dropped by __d_move(); however, in both cases dentry must have been
alive and refer to that name at some point after we'd done rcu_read_lock(),
which means that any freeing must be still pending.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2014-09-29 18:54:27 +00:00
|
|
|
if (unlikely(dname_external(target))) {
|
|
|
|
if (unlikely(dname_external(dentry))) {
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* Both external: swap the pointers
|
|
|
|
*/
|
2009-01-08 02:09:14 +00:00
|
|
|
swap(target->d_name.name, dentry->d_name.name);
|
2005-04-16 22:20:36 +00:00
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* dentry:internal, target:external. Steal target's
|
|
|
|
* storage and make target internal.
|
|
|
|
*/
|
2007-10-21 23:41:38 +00:00
|
|
|
memcpy(target->d_iname, dentry->d_name.name,
|
|
|
|
dentry->d_name.len + 1);
|
2005-04-16 22:20:36 +00:00
|
|
|
dentry->d_name.name = target->d_name.name;
|
|
|
|
target->d_name.name = target->d_iname;
|
|
|
|
}
|
|
|
|
} else {
|
Allow sharing external names after __d_move()
* external dentry names get a small structure prepended to them
(struct external_name).
* it contains an atomic refcount, matching the number of struct dentry
instances that have ->d_name.name pointing to that external name. The
first thing free_dentry() does is decrementing refcount of external name,
so the instances that are between the call of free_dentry() and
RCU-delayed actual freeing do not contribute.
* __d_move(x, y, false) makes the name of x equal to the name of y,
external or not. If y has an external name, extra reference is grabbed
and put into x->d_name.name. If x used to have an external name, the
reference to the old name is dropped and, should it reach zero, freeing
is scheduled via kfree_rcu().
* free_dentry() in dentry with external name decrements the refcount of
that name and, should it reach zero, does RCU-delayed call that will
free both the dentry and external name. Otherwise it does what it
used to do, except that __d_free() doesn't even look at ->d_name.name;
it simply frees the dentry.
All non-RCU accesses to dentry external name are safe wrt freeing since they
all should happen before free_dentry() is called. RCU accesses might run
into a dentry seen by free_dentry() or into an old name that got already
dropped by __d_move(); however, in both cases dentry must have been
alive and refer to that name at some point after we'd done rcu_read_lock(),
which means that any freeing must be still pending.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2014-09-29 18:54:27 +00:00
|
|
|
if (unlikely(dname_external(dentry))) {
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* dentry:external, target:internal. Give dentry's
|
|
|
|
* storage to target and make dentry internal
|
|
|
|
*/
|
|
|
|
memcpy(dentry->d_iname, target->d_name.name,
|
|
|
|
target->d_name.len + 1);
|
|
|
|
target->d_name.name = dentry->d_name.name;
|
|
|
|
dentry->d_name.name = dentry->d_iname;
|
|
|
|
} else {
|
|
|
|
/*
|
2014-04-01 15:08:43 +00:00
|
|
|
* Both are internal.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2014-04-01 15:08:43 +00:00
|
|
|
unsigned int i;
|
|
|
|
BUILD_BUG_ON(!IS_ALIGNED(DNAME_INLINE_LEN, sizeof(long)));
|
|
|
|
for (i = 0; i < DNAME_INLINE_LEN / sizeof(long); i++) {
|
|
|
|
swap(((long *) &dentry->d_iname)[i],
|
|
|
|
((long *) &target->d_iname)[i]);
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
}
|
2014-09-24 19:27:39 +00:00
|
|
|
swap(dentry->d_name.hash_len, target->d_name.hash_len);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
Allow sharing external names after __d_move()
* external dentry names get a small structure prepended to them
(struct external_name).
* it contains an atomic refcount, matching the number of struct dentry
instances that have ->d_name.name pointing to that external name. The
first thing free_dentry() does is decrementing refcount of external name,
so the instances that are between the call of free_dentry() and
RCU-delayed actual freeing do not contribute.
* __d_move(x, y, false) makes the name of x equal to the name of y,
external or not. If y has an external name, extra reference is grabbed
and put into x->d_name.name. If x used to have an external name, the
reference to the old name is dropped and, should it reach zero, freeing
is scheduled via kfree_rcu().
* free_dentry() in dentry with external name decrements the refcount of
that name and, should it reach zero, does RCU-delayed call that will
free both the dentry and external name. Otherwise it does what it
used to do, except that __d_free() doesn't even look at ->d_name.name;
it simply frees the dentry.
All non-RCU accesses to dentry external name are safe wrt freeing since they
all should happen before free_dentry() is called. RCU accesses might run
into a dentry seen by free_dentry() or into an old name that got already
dropped by __d_move(); however, in both cases dentry must have been
alive and refer to that name at some point after we'd done rcu_read_lock(),
which means that any freeing must be still pending.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2014-09-29 18:54:27 +00:00
|
|
|
static void copy_name(struct dentry *dentry, struct dentry *target)
|
|
|
|
{
|
|
|
|
struct external_name *old_name = NULL;
|
|
|
|
if (unlikely(dname_external(dentry)))
|
|
|
|
old_name = external_name(dentry);
|
|
|
|
if (unlikely(dname_external(target))) {
|
|
|
|
atomic_inc(&external_name(target)->u.count);
|
|
|
|
dentry->d_name = target->d_name;
|
|
|
|
} else {
|
|
|
|
memcpy(dentry->d_iname, target->d_name.name,
|
|
|
|
target->d_name.len + 1);
|
|
|
|
dentry->d_name.name = dentry->d_iname;
|
|
|
|
dentry->d_name.hash_len = target->d_name.hash_len;
|
|
|
|
}
|
|
|
|
if (old_name && likely(atomic_dec_and_test(&old_name->u.count)))
|
2018-10-26 22:05:41 +00:00
|
|
|
kfree_rcu(old_name, u.head);
|
Allow sharing external names after __d_move()
* external dentry names get a small structure prepended to them
(struct external_name).
* it contains an atomic refcount, matching the number of struct dentry
instances that have ->d_name.name pointing to that external name. The
first thing free_dentry() does is decrementing refcount of external name,
so the instances that are between the call of free_dentry() and
RCU-delayed actual freeing do not contribute.
* __d_move(x, y, false) makes the name of x equal to the name of y,
external or not. If y has an external name, extra reference is grabbed
and put into x->d_name.name. If x used to have an external name, the
reference to the old name is dropped and, should it reach zero, freeing
is scheduled via kfree_rcu().
* free_dentry() in dentry with external name decrements the refcount of
that name and, should it reach zero, does RCU-delayed call that will
free both the dentry and external name. Otherwise it does what it
used to do, except that __d_free() doesn't even look at ->d_name.name;
it simply frees the dentry.
All non-RCU accesses to dentry external name are safe wrt freeing since they
all should happen before free_dentry() is called. RCU accesses might run
into a dentry seen by free_dentry() or into an old name that got already
dropped by __d_move(); however, in both cases dentry must have been
alive and refer to that name at some point after we'd done rcu_read_lock(),
which means that any freeing must be still pending.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2014-09-29 18:54:27 +00:00
|
|
|
}
|
|
|
|
|
2006-10-21 17:24:20 +00:00
|
|
|
/*
|
2011-07-13 01:42:24 +00:00
|
|
|
* __d_move - move a dentry
|
2005-04-16 22:20:36 +00:00
|
|
|
* @dentry: entry to move
|
|
|
|
* @target: new dentry
|
2014-04-01 15:08:43 +00:00
|
|
|
* @exchange: exchange the two dentries
|
2005-04-16 22:20:36 +00:00
|
|
|
*
|
|
|
|
* Update the dcache to reflect the move of a file name. Negative
|
2011-07-26 17:33:16 +00:00
|
|
|
* dcache entries should not be moved in this way. Caller must hold
|
|
|
|
* rename_lock, the i_mutex of the source and target directories,
|
|
|
|
* and the sb->s_vfs_rename_mutex if they differ. See lock_rename().
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2014-04-01 15:08:43 +00:00
|
|
|
static void __d_move(struct dentry *dentry, struct dentry *target,
|
|
|
|
bool exchange)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2018-03-11 19:15:46 +00:00
|
|
|
struct dentry *old_parent, *p;
|
fs/dcache: Move the wakeup from __d_lookup_done() to the caller.
__d_lookup_done() wakes waiters on dentry->d_wait. On PREEMPT_RT we are
not allowed to do that with preemption disabled, since the wakeup
acquired wait_queue_head::lock, which is a "sleeping" spinlock on RT.
Calling it under dentry->d_lock is not a problem, since that is also a
"sleeping" spinlock on the same configs. Unfortunately, two of its
callers (__d_add() and __d_move()) are holding more than just ->d_lock
and that needs to be dealt with.
The key observation is that wakeup can be moved to any point before
dropping ->d_lock.
As a first step to solve this, move the wake up outside of the
hlist_bl_lock() held section.
This is safe because:
Waiters get inserted into ->d_wait only after they'd taken ->d_lock
and observed DCACHE_PAR_LOOKUP in flags. As long as they are
woken up (and evicted from the queue) between the moment __d_lookup_done()
has removed DCACHE_PAR_LOOKUP and dropping ->d_lock, we are safe,
since the waitqueue ->d_wait points to won't get destroyed without
having __d_lookup_done(dentry) called (under ->d_lock).
->d_wait is set only by d_alloc_parallel() and only in case when
it returns a freshly allocated in-lookup dentry. Whenever that happens,
we are guaranteed that __d_lookup_done() will be called for resulting
dentry (under ->d_lock) before the wq in question gets destroyed.
With two exceptions wq lives in call frame of the caller of
d_alloc_parallel() and we have an explicit d_lookup_done() on the
resulting in-lookup dentry before we leave that frame.
One of those exceptions is nfs_call_unlink(), where wq is embedded into
(dynamically allocated) struct nfs_unlinkdata. It is destroyed in
nfs_async_unlink_release() after an explicit d_lookup_done() on the
dentry wq went into.
Remaining exception is d_add_ci(). There wq is what we'd found in
->d_wait of d_add_ci() argument. Callers of d_add_ci() are two
instances of ->d_lookup() and they must have been given an in-lookup
dentry. Which means that they'd been called by __lookup_slow() or
lookup_open(), with wq in the call frame of one of those.
Result of d_alloc_parallel() in d_add_ci() is fed to
d_splice_alias(), which either returns non-NULL (and d_add_ci() does
d_lookup_done()) or feeds dentry to __d_add() that will do
__d_lookup_done() under ->d_lock. That concludes the analysis.
Let __d_lookup_unhash():
1) Lock the lookup hash and clear DCACHE_PAR_LOOKUP
2) Unhash the dentry
3) Retrieve and clear dentry::d_wait
4) Unlock the hash and return the retrieved waitqueue head pointer
5) Let the caller handle the wake up.
6) Rename __d_lookup_done() to __d_lookup_unhash_wake() to enforce
build failures for OOT code that used __d_lookup_done() and is not
aware of the new return value.
This does not yet solve the PREEMPT_RT problem completely because
preemption is still disabled due to i_dir_seq being held for write. This
will be addressed in subsequent steps.
An alternative solution would be to switch the waitqueue to a simple
waitqueue, but aside of Linus not being a fan of them, moving the wake up
closer to the place where dentry::lock is unlocked reduces lock contention
time for the woken up waiter.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Link: https://lkml.kernel.org/r/20220613140712.77932-3-bigeasy@linutronix.de
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2022-07-27 11:49:03 +00:00
|
|
|
wait_queue_head_t *d_wait;
|
parallel lookups machinery, part 2
We'll need to verify that there's neither a hashed nor in-lookup
dentry with desired parent/name before adding to in-lookup set.
One possible solution would be to hold the parent's ->d_lock through
both checks, but while the in-lookup set is relatively small at any
time, dcache is not. And holding the parent's ->d_lock through
something like __d_lookup_rcu() would suck too badly.
So we leave the parent's ->d_lock alone, which means that we watch
out for the following scenario:
* we verify that there's no hashed match
* existing in-lookup match gets hashed by another process
* we verify that there's no in-lookup matches and decide
that everything's fine.
Solution: per-directory kinda-sorta seqlock, bumped around the times
we hash something that used to be in-lookup or move (and hash)
something in place of in-lookup. Then the above would turn into
* read the counter
* do dcache lookup
* if no matches found, check for in-lookup matches
* if there had been none of those either, check if the
counter has changed; repeat if it has.
The "kinda-sorta" part is due to the fact that we don't have much spare
space in inode. There is a spare word (shared with i_bdev/i_cdev/i_pipe),
so the counter part is not a problem, but spinlock is a different story.
We could use the parent's ->d_lock, and it would be less painful in
terms of contention, for __d_add() it would be rather inconvenient to
grab; we could do that (using lock_parent()), but...
Fortunately, we can get serialization on the counter itself, and it
might be a good idea in general; we can use cmpxchg() in a loop to
get from even to odd and smp_store_release() from odd to even.
This commit adds the counter and updating logics; the readers will be
added in the next commit.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2016-04-15 04:58:55 +00:00
|
|
|
struct inode *dir = NULL;
|
|
|
|
unsigned n;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2018-03-11 19:15:46 +00:00
|
|
|
WARN_ON(!dentry->d_inode);
|
|
|
|
if (WARN_ON(dentry == target))
|
|
|
|
return;
|
|
|
|
|
2011-01-07 06:49:34 +00:00
|
|
|
BUG_ON(d_ancestor(target, dentry));
|
2018-03-11 19:15:46 +00:00
|
|
|
old_parent = dentry->d_parent;
|
|
|
|
p = d_ancestor(old_parent, target);
|
|
|
|
if (IS_ROOT(dentry)) {
|
|
|
|
BUG_ON(p);
|
|
|
|
spin_lock(&target->d_parent->d_lock);
|
|
|
|
} else if (!p) {
|
|
|
|
/* target is not a descendent of dentry->d_parent */
|
|
|
|
spin_lock(&target->d_parent->d_lock);
|
|
|
|
spin_lock_nested(&old_parent->d_lock, DENTRY_D_LOCK_NESTED);
|
|
|
|
} else {
|
|
|
|
BUG_ON(p == dentry);
|
|
|
|
spin_lock(&old_parent->d_lock);
|
|
|
|
if (p != target)
|
|
|
|
spin_lock_nested(&target->d_parent->d_lock,
|
|
|
|
DENTRY_D_LOCK_NESTED);
|
|
|
|
}
|
|
|
|
spin_lock_nested(&dentry->d_lock, 2);
|
|
|
|
spin_lock_nested(&target->d_lock, 3);
|
2011-01-07 06:49:34 +00:00
|
|
|
|
parallel lookups machinery, part 2
We'll need to verify that there's neither a hashed nor in-lookup
dentry with desired parent/name before adding to in-lookup set.
One possible solution would be to hold the parent's ->d_lock through
both checks, but while the in-lookup set is relatively small at any
time, dcache is not. And holding the parent's ->d_lock through
something like __d_lookup_rcu() would suck too badly.
So we leave the parent's ->d_lock alone, which means that we watch
out for the following scenario:
* we verify that there's no hashed match
* existing in-lookup match gets hashed by another process
* we verify that there's no in-lookup matches and decide
that everything's fine.
Solution: per-directory kinda-sorta seqlock, bumped around the times
we hash something that used to be in-lookup or move (and hash)
something in place of in-lookup. Then the above would turn into
* read the counter
* do dcache lookup
* if no matches found, check for in-lookup matches
* if there had been none of those either, check if the
counter has changed; repeat if it has.
The "kinda-sorta" part is due to the fact that we don't have much spare
space in inode. There is a spare word (shared with i_bdev/i_cdev/i_pipe),
so the counter part is not a problem, but spinlock is a different story.
We could use the parent's ->d_lock, and it would be less painful in
terms of contention, for __d_add() it would be rather inconvenient to
grab; we could do that (using lock_parent()), but...
Fortunately, we can get serialization on the counter itself, and it
might be a good idea in general; we can use cmpxchg() in a loop to
get from even to odd and smp_store_release() from odd to even.
This commit adds the counter and updating logics; the readers will be
added in the next commit.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2016-04-15 04:58:55 +00:00
|
|
|
if (unlikely(d_in_lookup(target))) {
|
|
|
|
dir = target->d_parent->d_inode;
|
|
|
|
n = start_dir_add(dir);
|
fs/dcache: Move the wakeup from __d_lookup_done() to the caller.
__d_lookup_done() wakes waiters on dentry->d_wait. On PREEMPT_RT we are
not allowed to do that with preemption disabled, since the wakeup
acquired wait_queue_head::lock, which is a "sleeping" spinlock on RT.
Calling it under dentry->d_lock is not a problem, since that is also a
"sleeping" spinlock on the same configs. Unfortunately, two of its
callers (__d_add() and __d_move()) are holding more than just ->d_lock
and that needs to be dealt with.
The key observation is that wakeup can be moved to any point before
dropping ->d_lock.
As a first step to solve this, move the wake up outside of the
hlist_bl_lock() held section.
This is safe because:
Waiters get inserted into ->d_wait only after they'd taken ->d_lock
and observed DCACHE_PAR_LOOKUP in flags. As long as they are
woken up (and evicted from the queue) between the moment __d_lookup_done()
has removed DCACHE_PAR_LOOKUP and dropping ->d_lock, we are safe,
since the waitqueue ->d_wait points to won't get destroyed without
having __d_lookup_done(dentry) called (under ->d_lock).
->d_wait is set only by d_alloc_parallel() and only in case when
it returns a freshly allocated in-lookup dentry. Whenever that happens,
we are guaranteed that __d_lookup_done() will be called for resulting
dentry (under ->d_lock) before the wq in question gets destroyed.
With two exceptions wq lives in call frame of the caller of
d_alloc_parallel() and we have an explicit d_lookup_done() on the
resulting in-lookup dentry before we leave that frame.
One of those exceptions is nfs_call_unlink(), where wq is embedded into
(dynamically allocated) struct nfs_unlinkdata. It is destroyed in
nfs_async_unlink_release() after an explicit d_lookup_done() on the
dentry wq went into.
Remaining exception is d_add_ci(). There wq is what we'd found in
->d_wait of d_add_ci() argument. Callers of d_add_ci() are two
instances of ->d_lookup() and they must have been given an in-lookup
dentry. Which means that they'd been called by __lookup_slow() or
lookup_open(), with wq in the call frame of one of those.
Result of d_alloc_parallel() in d_add_ci() is fed to
d_splice_alias(), which either returns non-NULL (and d_add_ci() does
d_lookup_done()) or feeds dentry to __d_add() that will do
__d_lookup_done() under ->d_lock. That concludes the analysis.
Let __d_lookup_unhash():
1) Lock the lookup hash and clear DCACHE_PAR_LOOKUP
2) Unhash the dentry
3) Retrieve and clear dentry::d_wait
4) Unlock the hash and return the retrieved waitqueue head pointer
5) Let the caller handle the wake up.
6) Rename __d_lookup_done() to __d_lookup_unhash_wake() to enforce
build failures for OOT code that used __d_lookup_done() and is not
aware of the new return value.
This does not yet solve the PREEMPT_RT problem completely because
preemption is still disabled due to i_dir_seq being held for write. This
will be addressed in subsequent steps.
An alternative solution would be to switch the waitqueue to a simple
waitqueue, but aside of Linus not being a fan of them, moving the wake up
closer to the place where dentry::lock is unlocked reduces lock contention
time for the woken up waiter.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Link: https://lkml.kernel.org/r/20220613140712.77932-3-bigeasy@linutronix.de
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2022-07-27 11:49:03 +00:00
|
|
|
d_wait = __d_lookup_unhash(target);
|
parallel lookups machinery, part 2
We'll need to verify that there's neither a hashed nor in-lookup
dentry with desired parent/name before adding to in-lookup set.
One possible solution would be to hold the parent's ->d_lock through
both checks, but while the in-lookup set is relatively small at any
time, dcache is not. And holding the parent's ->d_lock through
something like __d_lookup_rcu() would suck too badly.
So we leave the parent's ->d_lock alone, which means that we watch
out for the following scenario:
* we verify that there's no hashed match
* existing in-lookup match gets hashed by another process
* we verify that there's no in-lookup matches and decide
that everything's fine.
Solution: per-directory kinda-sorta seqlock, bumped around the times
we hash something that used to be in-lookup or move (and hash)
something in place of in-lookup. Then the above would turn into
* read the counter
* do dcache lookup
* if no matches found, check for in-lookup matches
* if there had been none of those either, check if the
counter has changed; repeat if it has.
The "kinda-sorta" part is due to the fact that we don't have much spare
space in inode. There is a spare word (shared with i_bdev/i_cdev/i_pipe),
so the counter part is not a problem, but spinlock is a different story.
We could use the parent's ->d_lock, and it would be less painful in
terms of contention, for __d_add() it would be rather inconvenient to
grab; we could do that (using lock_parent()), but...
Fortunately, we can get serialization on the counter itself, and it
might be a good idea in general; we can use cmpxchg() in a loop to
get from even to odd and smp_store_release() from odd to even.
This commit adds the counter and updating logics; the readers will be
added in the next commit.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2016-04-15 04:58:55 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
fs: rcu-walk for path lookup
Perform common cases of path lookups without any stores or locking in the
ancestor dentry elements. This is called rcu-walk, as opposed to the current
algorithm which is a refcount based walk, or ref-walk.
This results in far fewer atomic operations on every path element,
significantly improving path lookup performance. It also avoids cacheline
bouncing on common dentries, significantly improving scalability.
The overall design is like this:
* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
* Take the RCU lock for the entire path walk, starting with the acquiring
of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
not required for dentry persistence.
* synchronize_rcu is called when unregistering a filesystem, so we can
access d_ops and i_ops during rcu-walk.
* Similarly take the vfsmount lock for the entire path walk. So now mnt
refcounts are not required for persistence. Also we are free to perform mount
lookups, and to assume dentry mount points and mount roots are stable up and
down the path.
* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
so we can load this tuple atomically, and also check whether any of its
members have changed.
* Dentry lookups (based on parent, candidate string tuple) recheck the parent
sequence after the child is found in case anything changed in the parent
during the path walk.
* inode is also RCU protected so we can load d_inode and use the inode for
limited things.
* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
* i_op can be loaded.
When we reach the destination dentry, we lock it, recheck lookup sequence,
and increment its refcount and mountpoint refcount. RCU and vfsmount locks
are dropped. This is termed "dropping rcu-walk". If the dentry refcount does
not match, we can not drop rcu-walk gracefully at the current point in the
lokup, so instead return -ECHILD (for want of a better errno). This signals the
path walking code to re-do the entire lookup with a ref-walk.
Aside from the final dentry, there are other situations that may be encounted
where we cannot continue rcu-walk. In that case, we drop rcu-walk (ie. take
a reference on the last good dentry) and continue with a ref-walk. Again, if
we can drop rcu-walk gracefully, we return -ECHILD and do the whole lookup
using ref-walk. But it is very important that we can continue with ref-walk
for most cases, particularly to avoid the overhead of double lookups, and to
gain the scalability advantages on common path elements (like cwd and root).
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links
In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:52 +00:00
|
|
|
write_seqcount_begin(&dentry->d_seq);
|
2013-10-07 22:51:59 +00:00
|
|
|
write_seqcount_begin_nested(&target->d_seq, DENTRY_D_LOCK_NESTED);
|
fs: rcu-walk for path lookup
Perform common cases of path lookups without any stores or locking in the
ancestor dentry elements. This is called rcu-walk, as opposed to the current
algorithm which is a refcount based walk, or ref-walk.
This results in far fewer atomic operations on every path element,
significantly improving path lookup performance. It also avoids cacheline
bouncing on common dentries, significantly improving scalability.
The overall design is like this:
* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
* Take the RCU lock for the entire path walk, starting with the acquiring
of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
not required for dentry persistence.
* synchronize_rcu is called when unregistering a filesystem, so we can
access d_ops and i_ops during rcu-walk.
* Similarly take the vfsmount lock for the entire path walk. So now mnt
refcounts are not required for persistence. Also we are free to perform mount
lookups, and to assume dentry mount points and mount roots are stable up and
down the path.
* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
so we can load this tuple atomically, and also check whether any of its
members have changed.
* Dentry lookups (based on parent, candidate string tuple) recheck the parent
sequence after the child is found in case anything changed in the parent
during the path walk.
* inode is also RCU protected so we can load d_inode and use the inode for
limited things.
* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
* i_op can be loaded.
When we reach the destination dentry, we lock it, recheck lookup sequence,
and increment its refcount and mountpoint refcount. RCU and vfsmount locks
are dropped. This is termed "dropping rcu-walk". If the dentry refcount does
not match, we can not drop rcu-walk gracefully at the current point in the
lokup, so instead return -ECHILD (for want of a better errno). This signals the
path walking code to re-do the entire lookup with a ref-walk.
Aside from the final dentry, there are other situations that may be encounted
where we cannot continue rcu-walk. In that case, we drop rcu-walk (ie. take
a reference on the last good dentry) and continue with a ref-walk. Again, if
we can drop rcu-walk gracefully, we return -ECHILD and do the whole lookup
using ref-walk. But it is very important that we can continue with ref-walk
for most cases, particularly to avoid the overhead of double lookups, and to
gain the scalability advantages on common path elements (like cwd and root).
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links
In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:52 +00:00
|
|
|
|
2016-07-29 21:45:21 +00:00
|
|
|
/* unhash both */
|
2018-03-07 05:49:10 +00:00
|
|
|
if (!d_unhashed(dentry))
|
|
|
|
___d_drop(dentry);
|
|
|
|
if (!d_unhashed(target))
|
|
|
|
___d_drop(target);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
make non-exchanging __d_move() copy ->d_parent rather than swap them
Currently d_move(from, to) does the following:
* name/parent of from <- old name/parent of to, from hashed there
* to is unhashed
* name of to is preserved
* if from used to be detached, to gets detached
* if from used to be attached, parent of to <- old parent of from.
That's both user-visibly bogus and complicates reasoning a lot.
Much saner semantics would be
* name/parent of from <- name/parent of to, from hashed there.
* to is unhashed
* name/parent of to is unchanged.
The price, of course, is that old parent of from might lose a reference.
However,
* all potentially cross-directory callers of d_move() have both
parents pinned directly; typically, dentries themselves are grabbed
only after we have grabbed and locked both parents. IOW, the decrement
of old parent's refcount in case of d_move() won't reach zero.
* __d_move() from d_splice_alias() is done to detached alias.
No refcount decrements in that case
* __d_move() from __d_unalias() *can* get the refcount to zero.
So let's grab a reference to alias' old parent before calling __d_unalias()
and dput() it after we'd dropped rename_lock.
That does make d_splice_alias() potentially blocking. However, it has
no callers in non-sleepable contexts (and the case where we'd grown
that dget/dput pair is _very_ rare, so performance is not an issue).
Another thing that needs adjustment is unlocking in the end of __d_move();
folded it in. And cleaned the remnants of bogus ordering from the
"lock them in the beginning" counterpart - it's never been right and
now (well, for 7 years now) we have that thing always serialized on
rename_lock anyway.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2018-03-11 04:15:52 +00:00
|
|
|
/* ... and switch them in the tree */
|
|
|
|
dentry->d_parent = target->d_parent;
|
|
|
|
if (!exchange) {
|
Allow sharing external names after __d_move()
* external dentry names get a small structure prepended to them
(struct external_name).
* it contains an atomic refcount, matching the number of struct dentry
instances that have ->d_name.name pointing to that external name. The
first thing free_dentry() does is decrementing refcount of external name,
so the instances that are between the call of free_dentry() and
RCU-delayed actual freeing do not contribute.
* __d_move(x, y, false) makes the name of x equal to the name of y,
external or not. If y has an external name, extra reference is grabbed
and put into x->d_name.name. If x used to have an external name, the
reference to the old name is dropped and, should it reach zero, freeing
is scheduled via kfree_rcu().
* free_dentry() in dentry with external name decrements the refcount of
that name and, should it reach zero, does RCU-delayed call that will
free both the dentry and external name. Otherwise it does what it
used to do, except that __d_free() doesn't even look at ->d_name.name;
it simply frees the dentry.
All non-RCU accesses to dentry external name are safe wrt freeing since they
all should happen before free_dentry() is called. RCU accesses might run
into a dentry seen by free_dentry() or into an old name that got already
dropped by __d_move(); however, in both cases dentry must have been
alive and refer to that name at some point after we'd done rcu_read_lock(),
which means that any freeing must be still pending.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2014-09-29 18:54:27 +00:00
|
|
|
copy_name(dentry, target);
|
2017-11-10 04:45:41 +00:00
|
|
|
target->d_hash.pprev = NULL;
|
make non-exchanging __d_move() copy ->d_parent rather than swap them
Currently d_move(from, to) does the following:
* name/parent of from <- old name/parent of to, from hashed there
* to is unhashed
* name of to is preserved
* if from used to be detached, to gets detached
* if from used to be attached, parent of to <- old parent of from.
That's both user-visibly bogus and complicates reasoning a lot.
Much saner semantics would be
* name/parent of from <- name/parent of to, from hashed there.
* to is unhashed
* name/parent of to is unchanged.
The price, of course, is that old parent of from might lose a reference.
However,
* all potentially cross-directory callers of d_move() have both
parents pinned directly; typically, dentries themselves are grabbed
only after we have grabbed and locked both parents. IOW, the decrement
of old parent's refcount in case of d_move() won't reach zero.
* __d_move() from d_splice_alias() is done to detached alias.
No refcount decrements in that case
* __d_move() from __d_unalias() *can* get the refcount to zero.
So let's grab a reference to alias' old parent before calling __d_unalias()
and dput() it after we'd dropped rename_lock.
That does make d_splice_alias() potentially blocking. However, it has
no callers in non-sleepable contexts (and the case where we'd grown
that dget/dput pair is _very_ rare, so performance is not an issue).
Another thing that needs adjustment is unlocking in the end of __d_move();
folded it in. And cleaned the remnants of bogus ordering from the
"lock them in the beginning" counterpart - it's never been right and
now (well, for 7 years now) we have that thing always serialized on
rename_lock anyway.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2018-03-11 04:15:52 +00:00
|
|
|
dentry->d_parent->d_lockref.count++;
|
dcache: sort the freeing-without-RCU-delay mess for good.
For lockless accesses to dentries we don't have pinned we rely
(among other things) upon having an RCU delay between dropping
the last reference and actually freeing the memory.
On the other hand, for things like pipes and sockets we neither
do that kind of lockless access, nor want to deal with the
overhead of an RCU delay every time a socket gets closed.
So delay was made optional - setting DCACHE_RCUACCESS in ->d_flags
made sure it would happen. We tried to avoid setting it unless
we knew we need it. Unfortunately, that had led to recurring
class of bugs, in which we missed the need to set it.
We only really need it for dentries that are created by
d_alloc_pseudo(), so let's not bother with trying to be smart -
just make having an RCU delay the default. The ones that do
*not* get it set the replacement flag (DCACHE_NORCU) and we'd
better use that sparingly. d_alloc_pseudo() is the only
such user right now.
FWIW, the race that finally prompted that switch had been
between __lock_parent() of immediate subdirectory of what's
currently the root of a disconnected tree (e.g. from
open-by-handle in progress) racing with d_splice_alias()
elsewhere picking another alias for the same inode, either
on outright corrupted fs image, or (in case of open-by-handle
on NFS) that subdirectory having been just moved on server.
It's not easy to hit, so the sky is not falling, but that's
not the first race on similar missed cases and the logics
for settinf DCACHE_RCUACCESS has gotten ridiculously
convoluted.
Cc: stable@vger.kernel.org
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2019-03-16 02:23:19 +00:00
|
|
|
if (dentry != old_parent) /* wasn't IS_ROOT */
|
make non-exchanging __d_move() copy ->d_parent rather than swap them
Currently d_move(from, to) does the following:
* name/parent of from <- old name/parent of to, from hashed there
* to is unhashed
* name of to is preserved
* if from used to be detached, to gets detached
* if from used to be attached, parent of to <- old parent of from.
That's both user-visibly bogus and complicates reasoning a lot.
Much saner semantics would be
* name/parent of from <- name/parent of to, from hashed there.
* to is unhashed
* name/parent of to is unchanged.
The price, of course, is that old parent of from might lose a reference.
However,
* all potentially cross-directory callers of d_move() have both
parents pinned directly; typically, dentries themselves are grabbed
only after we have grabbed and locked both parents. IOW, the decrement
of old parent's refcount in case of d_move() won't reach zero.
* __d_move() from d_splice_alias() is done to detached alias.
No refcount decrements in that case
* __d_move() from __d_unalias() *can* get the refcount to zero.
So let's grab a reference to alias' old parent before calling __d_unalias()
and dput() it after we'd dropped rename_lock.
That does make d_splice_alias() potentially blocking. However, it has
no callers in non-sleepable contexts (and the case where we'd grown
that dget/dput pair is _very_ rare, so performance is not an issue).
Another thing that needs adjustment is unlocking in the end of __d_move();
folded it in. And cleaned the remnants of bogus ordering from the
"lock them in the beginning" counterpart - it's never been right and
now (well, for 7 years now) we have that thing always serialized on
rename_lock anyway.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2018-03-11 04:15:52 +00:00
|
|
|
WARN_ON(!--old_parent->d_lockref.count);
|
2005-04-16 22:20:36 +00:00
|
|
|
} else {
|
make non-exchanging __d_move() copy ->d_parent rather than swap them
Currently d_move(from, to) does the following:
* name/parent of from <- old name/parent of to, from hashed there
* to is unhashed
* name of to is preserved
* if from used to be detached, to gets detached
* if from used to be attached, parent of to <- old parent of from.
That's both user-visibly bogus and complicates reasoning a lot.
Much saner semantics would be
* name/parent of from <- name/parent of to, from hashed there.
* to is unhashed
* name/parent of to is unchanged.
The price, of course, is that old parent of from might lose a reference.
However,
* all potentially cross-directory callers of d_move() have both
parents pinned directly; typically, dentries themselves are grabbed
only after we have grabbed and locked both parents. IOW, the decrement
of old parent's refcount in case of d_move() won't reach zero.
* __d_move() from d_splice_alias() is done to detached alias.
No refcount decrements in that case
* __d_move() from __d_unalias() *can* get the refcount to zero.
So let's grab a reference to alias' old parent before calling __d_unalias()
and dput() it after we'd dropped rename_lock.
That does make d_splice_alias() potentially blocking. However, it has
no callers in non-sleepable contexts (and the case where we'd grown
that dget/dput pair is _very_ rare, so performance is not an issue).
Another thing that needs adjustment is unlocking in the end of __d_move();
folded it in. And cleaned the remnants of bogus ordering from the
"lock them in the beginning" counterpart - it's never been right and
now (well, for 7 years now) we have that thing always serialized on
rename_lock anyway.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2018-03-11 04:15:52 +00:00
|
|
|
target->d_parent = old_parent;
|
|
|
|
swap_names(dentry, target);
|
2023-11-07 07:00:39 +00:00
|
|
|
if (!hlist_unhashed(&target->d_sib))
|
|
|
|
__hlist_del(&target->d_sib);
|
|
|
|
hlist_add_head(&target->d_sib, &target->d_parent->d_children);
|
make non-exchanging __d_move() copy ->d_parent rather than swap them
Currently d_move(from, to) does the following:
* name/parent of from <- old name/parent of to, from hashed there
* to is unhashed
* name of to is preserved
* if from used to be detached, to gets detached
* if from used to be attached, parent of to <- old parent of from.
That's both user-visibly bogus and complicates reasoning a lot.
Much saner semantics would be
* name/parent of from <- name/parent of to, from hashed there.
* to is unhashed
* name/parent of to is unchanged.
The price, of course, is that old parent of from might lose a reference.
However,
* all potentially cross-directory callers of d_move() have both
parents pinned directly; typically, dentries themselves are grabbed
only after we have grabbed and locked both parents. IOW, the decrement
of old parent's refcount in case of d_move() won't reach zero.
* __d_move() from d_splice_alias() is done to detached alias.
No refcount decrements in that case
* __d_move() from __d_unalias() *can* get the refcount to zero.
So let's grab a reference to alias' old parent before calling __d_unalias()
and dput() it after we'd dropped rename_lock.
That does make d_splice_alias() potentially blocking. However, it has
no callers in non-sleepable contexts (and the case where we'd grown
that dget/dput pair is _very_ rare, so performance is not an issue).
Another thing that needs adjustment is unlocking in the end of __d_move();
folded it in. And cleaned the remnants of bogus ordering from the
"lock them in the beginning" counterpart - it's never been right and
now (well, for 7 years now) we have that thing always serialized on
rename_lock anyway.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2018-03-11 04:15:52 +00:00
|
|
|
__d_rehash(target);
|
|
|
|
fsnotify_update_flags(target);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2023-11-07 07:00:39 +00:00
|
|
|
if (!hlist_unhashed(&dentry->d_sib))
|
|
|
|
__hlist_del(&dentry->d_sib);
|
|
|
|
hlist_add_head(&dentry->d_sib, &dentry->d_parent->d_children);
|
make non-exchanging __d_move() copy ->d_parent rather than swap them
Currently d_move(from, to) does the following:
* name/parent of from <- old name/parent of to, from hashed there
* to is unhashed
* name of to is preserved
* if from used to be detached, to gets detached
* if from used to be attached, parent of to <- old parent of from.
That's both user-visibly bogus and complicates reasoning a lot.
Much saner semantics would be
* name/parent of from <- name/parent of to, from hashed there.
* to is unhashed
* name/parent of to is unchanged.
The price, of course, is that old parent of from might lose a reference.
However,
* all potentially cross-directory callers of d_move() have both
parents pinned directly; typically, dentries themselves are grabbed
only after we have grabbed and locked both parents. IOW, the decrement
of old parent's refcount in case of d_move() won't reach zero.
* __d_move() from d_splice_alias() is done to detached alias.
No refcount decrements in that case
* __d_move() from __d_unalias() *can* get the refcount to zero.
So let's grab a reference to alias' old parent before calling __d_unalias()
and dput() it after we'd dropped rename_lock.
That does make d_splice_alias() potentially blocking. However, it has
no callers in non-sleepable contexts (and the case where we'd grown
that dget/dput pair is _very_ rare, so performance is not an issue).
Another thing that needs adjustment is unlocking in the end of __d_move();
folded it in. And cleaned the remnants of bogus ordering from the
"lock them in the beginning" counterpart - it's never been right and
now (well, for 7 years now) we have that thing always serialized on
rename_lock anyway.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2018-03-11 04:15:52 +00:00
|
|
|
__d_rehash(dentry);
|
|
|
|
fsnotify_update_flags(dentry);
|
2019-03-20 18:39:11 +00:00
|
|
|
fscrypt_handle_d_move(dentry);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
fs: rcu-walk for path lookup
Perform common cases of path lookups without any stores or locking in the
ancestor dentry elements. This is called rcu-walk, as opposed to the current
algorithm which is a refcount based walk, or ref-walk.
This results in far fewer atomic operations on every path element,
significantly improving path lookup performance. It also avoids cacheline
bouncing on common dentries, significantly improving scalability.
The overall design is like this:
* LOOKUP_RCU is set in nd->flags, which distinguishes rcu-walk from ref-walk.
* Take the RCU lock for the entire path walk, starting with the acquiring
of the starting path (eg. root/cwd/fd-path). So now dentry refcounts are
not required for dentry persistence.
* synchronize_rcu is called when unregistering a filesystem, so we can
access d_ops and i_ops during rcu-walk.
* Similarly take the vfsmount lock for the entire path walk. So now mnt
refcounts are not required for persistence. Also we are free to perform mount
lookups, and to assume dentry mount points and mount roots are stable up and
down the path.
* Have a per-dentry seqlock to protect the dentry name, parent, and inode,
so we can load this tuple atomically, and also check whether any of its
members have changed.
* Dentry lookups (based on parent, candidate string tuple) recheck the parent
sequence after the child is found in case anything changed in the parent
during the path walk.
* inode is also RCU protected so we can load d_inode and use the inode for
limited things.
* i_mode, i_uid, i_gid can be tested for exec permissions during path walk.
* i_op can be loaded.
When we reach the destination dentry, we lock it, recheck lookup sequence,
and increment its refcount and mountpoint refcount. RCU and vfsmount locks
are dropped. This is termed "dropping rcu-walk". If the dentry refcount does
not match, we can not drop rcu-walk gracefully at the current point in the
lokup, so instead return -ECHILD (for want of a better errno). This signals the
path walking code to re-do the entire lookup with a ref-walk.
Aside from the final dentry, there are other situations that may be encounted
where we cannot continue rcu-walk. In that case, we drop rcu-walk (ie. take
a reference on the last good dentry) and continue with a ref-walk. Again, if
we can drop rcu-walk gracefully, we return -ECHILD and do the whole lookup
using ref-walk. But it is very important that we can continue with ref-walk
for most cases, particularly to avoid the overhead of double lookups, and to
gain the scalability advantages on common path elements (like cwd and root).
The cases where rcu-walk cannot continue are:
* NULL dentry (ie. any uncached path element)
* parent with d_inode->i_op->permission or ACLs
* dentries with d_revalidate
* Following links
In future patches, permission checks and d_revalidate become rcu-walk aware. It
may be possible eventually to make following links rcu-walk aware.
Uncached path elements will always require dropping to ref-walk mode, at the
very least because i_mutex needs to be grabbed, and objects allocated.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
2011-01-07 06:49:52 +00:00
|
|
|
write_seqcount_end(&target->d_seq);
|
|
|
|
write_seqcount_end(&dentry->d_seq);
|
|
|
|
|
parallel lookups machinery, part 2
We'll need to verify that there's neither a hashed nor in-lookup
dentry with desired parent/name before adding to in-lookup set.
One possible solution would be to hold the parent's ->d_lock through
both checks, but while the in-lookup set is relatively small at any
time, dcache is not. And holding the parent's ->d_lock through
something like __d_lookup_rcu() would suck too badly.
So we leave the parent's ->d_lock alone, which means that we watch
out for the following scenario:
* we verify that there's no hashed match
* existing in-lookup match gets hashed by another process
* we verify that there's no in-lookup matches and decide
that everything's fine.
Solution: per-directory kinda-sorta seqlock, bumped around the times
we hash something that used to be in-lookup or move (and hash)
something in place of in-lookup. Then the above would turn into
* read the counter
* do dcache lookup
* if no matches found, check for in-lookup matches
* if there had been none of those either, check if the
counter has changed; repeat if it has.
The "kinda-sorta" part is due to the fact that we don't have much spare
space in inode. There is a spare word (shared with i_bdev/i_cdev/i_pipe),
so the counter part is not a problem, but spinlock is a different story.
We could use the parent's ->d_lock, and it would be less painful in
terms of contention, for __d_add() it would be rather inconvenient to
grab; we could do that (using lock_parent()), but...
Fortunately, we can get serialization on the counter itself, and it
might be a good idea in general; we can use cmpxchg() in a loop to
get from even to odd and smp_store_release() from odd to even.
This commit adds the counter and updating logics; the readers will be
added in the next commit.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2016-04-15 04:58:55 +00:00
|
|
|
if (dir)
|
2022-07-27 11:49:04 +00:00
|
|
|
end_dir_add(dir, n, d_wait);
|
make non-exchanging __d_move() copy ->d_parent rather than swap them
Currently d_move(from, to) does the following:
* name/parent of from <- old name/parent of to, from hashed there
* to is unhashed
* name of to is preserved
* if from used to be detached, to gets detached
* if from used to be attached, parent of to <- old parent of from.
That's both user-visibly bogus and complicates reasoning a lot.
Much saner semantics would be
* name/parent of from <- name/parent of to, from hashed there.
* to is unhashed
* name/parent of to is unchanged.
The price, of course, is that old parent of from might lose a reference.
However,
* all potentially cross-directory callers of d_move() have both
parents pinned directly; typically, dentries themselves are grabbed
only after we have grabbed and locked both parents. IOW, the decrement
of old parent's refcount in case of d_move() won't reach zero.
* __d_move() from d_splice_alias() is done to detached alias.
No refcount decrements in that case
* __d_move() from __d_unalias() *can* get the refcount to zero.
So let's grab a reference to alias' old parent before calling __d_unalias()
and dput() it after we'd dropped rename_lock.
That does make d_splice_alias() potentially blocking. However, it has
no callers in non-sleepable contexts (and the case where we'd grown
that dget/dput pair is _very_ rare, so performance is not an issue).
Another thing that needs adjustment is unlocking in the end of __d_move();
folded it in. And cleaned the remnants of bogus ordering from the
"lock them in the beginning" counterpart - it's never been right and
now (well, for 7 years now) we have that thing always serialized on
rename_lock anyway.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2018-03-11 04:15:52 +00:00
|
|
|
|
|
|
|
if (dentry->d_parent != old_parent)
|
|
|
|
spin_unlock(&dentry->d_parent->d_lock);
|
|
|
|
if (dentry != old_parent)
|
|
|
|
spin_unlock(&old_parent->d_lock);
|
|
|
|
spin_unlock(&target->d_lock);
|
|
|
|
spin_unlock(&dentry->d_lock);
|
2011-07-13 01:42:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* d_move - move a dentry
|
|
|
|
* @dentry: entry to move
|
|
|
|
* @target: new dentry
|
|
|
|
*
|
|
|
|
* Update the dcache to reflect the move of a file name. Negative
|
2011-07-26 17:33:16 +00:00
|
|
|
* dcache entries should not be moved in this way. See the locking
|
|
|
|
* requirements for __d_move.
|
2011-07-13 01:42:24 +00:00
|
|
|
*/
|
|
|
|
void d_move(struct dentry *dentry, struct dentry *target)
|
|
|
|
{
|
|
|
|
write_seqlock(&rename_lock);
|
2014-04-01 15:08:43 +00:00
|
|
|
__d_move(dentry, target, false);
|
2005-04-16 22:20:36 +00:00
|
|
|
write_sequnlock(&rename_lock);
|
2006-10-21 17:24:20 +00:00
|
|
|
}
|
2010-01-05 20:45:18 +00:00
|
|
|
EXPORT_SYMBOL(d_move);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2014-04-01 15:08:43 +00:00
|
|
|
/*
|
|
|
|
* d_exchange - exchange two dentries
|
|
|
|
* @dentry1: first dentry
|
|
|
|
* @dentry2: second dentry
|
|
|
|
*/
|
|
|
|
void d_exchange(struct dentry *dentry1, struct dentry *dentry2)
|
|
|
|
{
|
|
|
|
write_seqlock(&rename_lock);
|
|
|
|
|
|
|
|
WARN_ON(!dentry1->d_inode);
|
|
|
|
WARN_ON(!dentry2->d_inode);
|
|
|
|
WARN_ON(IS_ROOT(dentry1));
|
|
|
|
WARN_ON(IS_ROOT(dentry2));
|
|
|
|
|
|
|
|
__d_move(dentry1, dentry2, true);
|
|
|
|
|
|
|
|
write_sequnlock(&rename_lock);
|
|
|
|
}
|
|
|
|
|
2008-10-15 22:50:28 +00:00
|
|
|
/**
|
|
|
|
* d_ancestor - search for an ancestor
|
|
|
|
* @p1: ancestor dentry
|
|
|
|
* @p2: child dentry
|
|
|
|
*
|
|
|
|
* Returns the ancestor dentry of p2 which is a child of p1, if p1 is
|
|
|
|
* an ancestor of p2, else NULL.
|
2006-10-21 17:24:20 +00:00
|
|
|
*/
|
2008-10-15 22:50:28 +00:00
|
|
|
struct dentry *d_ancestor(struct dentry *p1, struct dentry *p2)
|
2006-10-21 17:24:20 +00:00
|
|
|
{
|
|
|
|
struct dentry *p;
|
|
|
|
|
2008-10-15 22:50:27 +00:00
|
|
|
for (p = p2; !IS_ROOT(p); p = p->d_parent) {
|
2006-10-21 17:24:20 +00:00
|
|
|
if (p->d_parent == p1)
|
2008-10-15 22:50:28 +00:00
|
|
|
return p;
|
2006-10-21 17:24:20 +00:00
|
|
|
}
|
2008-10-15 22:50:28 +00:00
|
|
|
return NULL;
|
2006-10-21 17:24:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This helper attempts to cope with remotely renamed directories
|
|
|
|
*
|
|
|
|
* It assumes that the caller is already holding
|
2015-08-15 18:36:41 +00:00
|
|
|
* dentry->d_parent->d_inode->i_mutex, and rename_lock
|
2006-10-21 17:24:20 +00:00
|
|
|
*
|
|
|
|
* Note: If ever the locking in lock_rename() changes, then please
|
|
|
|
* remember to update this too...
|
|
|
|
*/
|
2023-11-23 23:11:00 +00:00
|
|
|
static int __d_unalias(struct dentry *dentry, struct dentry *alias)
|
2006-10-21 17:24:20 +00:00
|
|
|
{
|
2016-04-15 19:08:36 +00:00
|
|
|
struct mutex *m1 = NULL;
|
|
|
|
struct rw_semaphore *m2 = NULL;
|
2015-02-10 15:55:53 +00:00
|
|
|
int ret = -ESTALE;
|
2006-10-21 17:24:20 +00:00
|
|
|
|
|
|
|
/* If alias and dentry share a parent, then no extra locks required */
|
|
|
|
if (alias->d_parent == dentry->d_parent)
|
|
|
|
goto out_unalias;
|
|
|
|
|
|
|
|
/* See lock_rename() */
|
|
|
|
if (!mutex_trylock(&dentry->d_sb->s_vfs_rename_mutex))
|
|
|
|
goto out_err;
|
|
|
|
m1 = &dentry->d_sb->s_vfs_rename_mutex;
|
2016-04-15 19:08:36 +00:00
|
|
|
if (!inode_trylock_shared(alias->d_parent->d_inode))
|
2006-10-21 17:24:20 +00:00
|
|
|
goto out_err;
|
2016-04-15 19:08:36 +00:00
|
|
|
m2 = &alias->d_parent->d_inode->i_rwsem;
|
2006-10-21 17:24:20 +00:00
|
|
|
out_unalias:
|
vfs: Lazily remove mounts on unlinked files and directories.
With the introduction of mount namespaces and bind mounts it became
possible to access files and directories that on some paths are mount
points but are not mount points on other paths. It is very confusing
when rm -rf somedir returns -EBUSY simply because somedir is mounted
somewhere else. With the addition of user namespaces allowing
unprivileged mounts this condition has gone from annoying to allowing
a DOS attack on other users in the system.
The possibility for mischief is removed by updating the vfs to support
rename, unlink and rmdir on a dentry that is a mountpoint and by
lazily unmounting mountpoints on deleted dentries.
In particular this change allows rename, unlink and rmdir system calls
on a dentry without a mountpoint in the current mount namespace to
succeed, and it allows rename, unlink, and rmdir performed on a
distributed filesystem to update the vfs cache even if when there is a
mount in some namespace on the original dentry.
There are two common patterns of maintaining mounts: Mounts on trusted
paths with the parent directory of the mount point and all ancestory
directories up to / owned by root and modifiable only by root
(i.e. /media/xxx, /dev, /dev/pts, /proc, /sys, /sys/fs/cgroup/{cpu,
cpuacct, ...}, /usr, /usr/local). Mounts on unprivileged directories
maintained by fusermount.
In the case of mounts in trusted directories owned by root and
modifiable only by root the current parent directory permissions are
sufficient to ensure a mount point on a trusted path is not removed
or renamed by anyone other than root, even if there is a context
where the there are no mount points to prevent this.
In the case of mounts in directories owned by less privileged users
races with users modifying the path of a mount point are already a
danger. fusermount already uses a combination of chdir,
/proc/<pid>/fd/NNN, and UMOUNT_NOFOLLOW to prevent these races. The
removable of global rename, unlink, and rmdir protection really adds
nothing new to consider only a widening of the attack window, and
fusermount is already safe against unprivileged users modifying the
directory simultaneously.
In principle for perfect userspace programs returning -EBUSY for
unlink, rmdir, and rename of dentires that have mounts in the local
namespace is actually unnecessary. Unfortunately not all userspace
programs are perfect so retaining -EBUSY for unlink, rmdir and rename
of dentries that have mounts in the current mount namespace plays an
important role of maintaining consistency with historical behavior and
making imperfect userspace applications hard to exploit.
v2: Remove spurious old_dentry.
v3: Optimized shrink_submounts_and_drop
Removed unsued afs label
v4: Simplified the changes to check_submounts_and_drop
Do not rename check_submounts_and_drop shrink_submounts_and_drop
Document what why we need atomicity in check_submounts_and_drop
Rely on the parent inode mutex to make d_revalidate and d_invalidate
an atomic unit.
v5: Refcount the mountpoint to detach in case of simultaneous
renames.
Reviewed-by: Miklos Szeredi <miklos@szeredi.hu>
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2013-10-02 01:33:48 +00:00
|
|
|
__d_move(alias, dentry, false);
|
2014-10-13 02:16:02 +00:00
|
|
|
ret = 0;
|
2006-10-21 17:24:20 +00:00
|
|
|
out_err:
|
|
|
|
if (m2)
|
2016-04-15 19:08:36 +00:00
|
|
|
up_read(m2);
|
2006-10-21 17:24:20 +00:00
|
|
|
if (m1)
|
|
|
|
mutex_unlock(m1);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-02-18 19:11:26 +00:00
|
|
|
/**
|
|
|
|
* d_splice_alias - splice a disconnected dentry into the tree if one exists
|
|
|
|
* @inode: the inode which may have a disconnected dentry
|
|
|
|
* @dentry: a negative dentry which we want to point to the inode.
|
|
|
|
*
|
2014-02-17 23:03:57 +00:00
|
|
|
* If inode is a directory and has an IS_ROOT alias, then d_move that in
|
|
|
|
* place of the given dentry and return it, else simply d_add the inode
|
|
|
|
* to the dentry and return NULL.
|
2014-02-18 19:11:26 +00:00
|
|
|
*
|
2014-02-17 22:58:42 +00:00
|
|
|
* If a non-IS_ROOT directory is found, the filesystem is corrupt, and
|
|
|
|
* we should error out: directories can't have multiple aliases.
|
|
|
|
*
|
2014-02-18 19:11:26 +00:00
|
|
|
* This is needed in the lookup routine of any filesystem that is exportable
|
|
|
|
* (via knfsd) so that we can build dcache paths to directories effectively.
|
|
|
|
*
|
|
|
|
* If a dentry was found and moved, then it is returned. Otherwise NULL
|
|
|
|
* is returned. This matches the expected return value of ->lookup.
|
|
|
|
*
|
|
|
|
* Cluster filesystems may call this function with a negative, hashed dentry.
|
|
|
|
* In that case, we know that the inode will be a regular file, and also this
|
|
|
|
* will only occur during atomic_open. So we need to check for the dentry
|
|
|
|
* being already hashed only in the final case.
|
|
|
|
*/
|
|
|
|
struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
|
|
|
|
{
|
|
|
|
if (IS_ERR(inode))
|
|
|
|
return ERR_CAST(inode);
|
|
|
|
|
2006-08-23 00:06:07 +00:00
|
|
|
BUG_ON(!d_unhashed(dentry));
|
|
|
|
|
2016-03-09 23:05:42 +00:00
|
|
|
if (!inode)
|
2014-10-13 02:16:02 +00:00
|
|
|
goto out;
|
2016-03-09 23:05:42 +00:00
|
|
|
|
2016-04-11 04:53:26 +00:00
|
|
|
security_d_instantiate(dentry, inode);
|
2011-01-07 06:50:06 +00:00
|
|
|
spin_lock(&inode->i_lock);
|
2006-10-21 17:24:20 +00:00
|
|
|
if (S_ISDIR(inode->i_mode)) {
|
2014-10-13 02:16:02 +00:00
|
|
|
struct dentry *new = __d_find_any_alias(inode);
|
|
|
|
if (unlikely(new)) {
|
2015-08-15 18:36:41 +00:00
|
|
|
/* The reference to new ensures it remains an alias */
|
|
|
|
spin_unlock(&inode->i_lock);
|
2011-07-13 01:42:24 +00:00
|
|
|
write_seqlock(&rename_lock);
|
2014-10-13 02:16:02 +00:00
|
|
|
if (unlikely(d_ancestor(new, dentry))) {
|
|
|
|
write_sequnlock(&rename_lock);
|
|
|
|
dput(new);
|
|
|
|
new = ERR_PTR(-ELOOP);
|
|
|
|
pr_warn_ratelimited(
|
|
|
|
"VFS: Lookup of '%s' in %s %s"
|
|
|
|
" would have caused loop\n",
|
|
|
|
dentry->d_name.name,
|
|
|
|
inode->i_sb->s_type->name,
|
|
|
|
inode->i_sb->s_id);
|
|
|
|
} else if (!IS_ROOT(new)) {
|
make non-exchanging __d_move() copy ->d_parent rather than swap them
Currently d_move(from, to) does the following:
* name/parent of from <- old name/parent of to, from hashed there
* to is unhashed
* name of to is preserved
* if from used to be detached, to gets detached
* if from used to be attached, parent of to <- old parent of from.
That's both user-visibly bogus and complicates reasoning a lot.
Much saner semantics would be
* name/parent of from <- name/parent of to, from hashed there.
* to is unhashed
* name/parent of to is unchanged.
The price, of course, is that old parent of from might lose a reference.
However,
* all potentially cross-directory callers of d_move() have both
parents pinned directly; typically, dentries themselves are grabbed
only after we have grabbed and locked both parents. IOW, the decrement
of old parent's refcount in case of d_move() won't reach zero.
* __d_move() from d_splice_alias() is done to detached alias.
No refcount decrements in that case
* __d_move() from __d_unalias() *can* get the refcount to zero.
So let's grab a reference to alias' old parent before calling __d_unalias()
and dput() it after we'd dropped rename_lock.
That does make d_splice_alias() potentially blocking. However, it has
no callers in non-sleepable contexts (and the case where we'd grown
that dget/dput pair is _very_ rare, so performance is not an issue).
Another thing that needs adjustment is unlocking in the end of __d_move();
folded it in. And cleaned the remnants of bogus ordering from the
"lock them in the beginning" counterpart - it's never been right and
now (well, for 7 years now) we have that thing always serialized on
rename_lock anyway.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2018-03-11 04:15:52 +00:00
|
|
|
struct dentry *old_parent = dget(new->d_parent);
|
2023-11-23 23:11:00 +00:00
|
|
|
int err = __d_unalias(dentry, new);
|
2011-07-13 01:42:24 +00:00
|
|
|
write_sequnlock(&rename_lock);
|
2014-10-13 02:16:02 +00:00
|
|
|
if (err) {
|
|
|
|
dput(new);
|
|
|
|
new = ERR_PTR(err);
|
|
|
|
}
|
make non-exchanging __d_move() copy ->d_parent rather than swap them
Currently d_move(from, to) does the following:
* name/parent of from <- old name/parent of to, from hashed there
* to is unhashed
* name of to is preserved
* if from used to be detached, to gets detached
* if from used to be attached, parent of to <- old parent of from.
That's both user-visibly bogus and complicates reasoning a lot.
Much saner semantics would be
* name/parent of from <- name/parent of to, from hashed there.
* to is unhashed
* name/parent of to is unchanged.
The price, of course, is that old parent of from might lose a reference.
However,
* all potentially cross-directory callers of d_move() have both
parents pinned directly; typically, dentries themselves are grabbed
only after we have grabbed and locked both parents. IOW, the decrement
of old parent's refcount in case of d_move() won't reach zero.
* __d_move() from d_splice_alias() is done to detached alias.
No refcount decrements in that case
* __d_move() from __d_unalias() *can* get the refcount to zero.
So let's grab a reference to alias' old parent before calling __d_unalias()
and dput() it after we'd dropped rename_lock.
That does make d_splice_alias() potentially blocking. However, it has
no callers in non-sleepable contexts (and the case where we'd grown
that dget/dput pair is _very_ rare, so performance is not an issue).
Another thing that needs adjustment is unlocking in the end of __d_move();
folded it in. And cleaned the remnants of bogus ordering from the
"lock them in the beginning" counterpart - it's never been right and
now (well, for 7 years now) we have that thing always serialized on
rename_lock anyway.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2018-03-11 04:15:52 +00:00
|
|
|
dput(old_parent);
|
2011-07-13 01:42:24 +00:00
|
|
|
} else {
|
2014-10-13 02:16:02 +00:00
|
|
|
__d_move(new, dentry, false);
|
|
|
|
write_sequnlock(&rename_lock);
|
2011-08-16 14:31:30 +00:00
|
|
|
}
|
2014-10-13 02:16:02 +00:00
|
|
|
iput(inode);
|
|
|
|
return new;
|
2006-10-21 17:24:20 +00:00
|
|
|
}
|
2006-08-23 00:06:07 +00:00
|
|
|
}
|
2014-10-13 02:16:02 +00:00
|
|
|
out:
|
2016-03-10 00:52:39 +00:00
|
|
|
__d_add(dentry, inode);
|
2014-10-13 02:16:02 +00:00
|
|
|
return NULL;
|
2006-08-23 00:06:07 +00:00
|
|
|
}
|
2014-10-13 02:16:02 +00:00
|
|
|
EXPORT_SYMBOL(d_splice_alias);
|
2006-08-23 00:06:07 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* Test whether new_dentry is a subdirectory of old_dentry.
|
|
|
|
*
|
|
|
|
* Trivially implemented using the dcache structure
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* is_subdir - is new dentry a subdirectory of old_dentry
|
|
|
|
* @new_dentry: new dentry
|
|
|
|
* @old_dentry: old dentry
|
|
|
|
*
|
2015-11-17 06:40:11 +00:00
|
|
|
* Returns true if new_dentry is a subdirectory of the parent (at any depth).
|
|
|
|
* Returns false otherwise.
|
2005-04-16 22:20:36 +00:00
|
|
|
* Caller must ensure that "new_dentry" is pinned before calling is_subdir()
|
|
|
|
*/
|
|
|
|
|
2015-11-17 06:40:11 +00:00
|
|
|
bool is_subdir(struct dentry *new_dentry, struct dentry *old_dentry)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2024-07-02 19:03:26 +00:00
|
|
|
bool subdir;
|
2011-01-07 06:49:37 +00:00
|
|
|
unsigned seq;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2008-10-15 22:50:28 +00:00
|
|
|
if (new_dentry == old_dentry)
|
2015-11-17 06:40:11 +00:00
|
|
|
return true;
|
2008-10-15 22:50:28 +00:00
|
|
|
|
2024-07-02 19:03:26 +00:00
|
|
|
/* Access d_parent under rcu as d_move() may change it. */
|
|
|
|
rcu_read_lock();
|
|
|
|
seq = read_seqbegin(&rename_lock);
|
|
|
|
subdir = d_ancestor(old_dentry, new_dentry);
|
|
|
|
/* Try lockless once... */
|
|
|
|
if (read_seqretry(&rename_lock, seq)) {
|
|
|
|
/* ...else acquire lock for progress even on deep chains. */
|
|
|
|
read_seqlock_excl(&rename_lock);
|
|
|
|
subdir = d_ancestor(old_dentry, new_dentry);
|
|
|
|
read_sequnlock_excl(&rename_lock);
|
|
|
|
}
|
|
|
|
rcu_read_unlock();
|
|
|
|
return subdir;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2018-01-11 09:33:24 +00:00
|
|
|
EXPORT_SYMBOL(is_subdir);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2013-09-05 09:44:35 +00:00
|
|
|
static enum d_walk_ret d_genocide_kill(void *data, struct dentry *dentry)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2013-09-05 09:44:35 +00:00
|
|
|
struct dentry *root = data;
|
|
|
|
if (dentry != root) {
|
|
|
|
if (d_unhashed(dentry) || !dentry->d_inode)
|
|
|
|
return D_WALK_SKIP;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2024-02-04 04:53:05 +00:00
|
|
|
if (!(dentry->d_flags & DCACHE_GENOCIDE)) {
|
|
|
|
dentry->d_flags |= DCACHE_GENOCIDE;
|
|
|
|
dentry->d_lockref.count--;
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2013-09-05 09:44:35 +00:00
|
|
|
return D_WALK_CONTINUE;
|
|
|
|
}
|
2011-01-07 06:49:39 +00:00
|
|
|
|
2013-09-05 09:44:35 +00:00
|
|
|
void d_genocide(struct dentry *parent)
|
|
|
|
{
|
2018-04-15 22:27:23 +00:00
|
|
|
d_walk(parent, parent, d_genocide_kill);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2018-07-10 03:27:33 +00:00
|
|
|
void d_mark_tmpfile(struct file *file, struct inode *inode)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2022-09-24 05:00:00 +00:00
|
|
|
struct dentry *dentry = file->f_path.dentry;
|
|
|
|
|
2013-06-07 05:20:27 +00:00
|
|
|
BUG_ON(dentry->d_name.name != dentry->d_iname ||
|
2014-10-26 23:19:16 +00:00
|
|
|
!hlist_unhashed(&dentry->d_u.d_alias) ||
|
2013-06-07 05:20:27 +00:00
|
|
|
!d_unlinked(dentry));
|
|
|
|
spin_lock(&dentry->d_parent->d_lock);
|
|
|
|
spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
|
|
|
|
dentry->d_name.len = sprintf(dentry->d_iname, "#%llu",
|
|
|
|
(unsigned long long)inode->i_ino);
|
|
|
|
spin_unlock(&dentry->d_lock);
|
|
|
|
spin_unlock(&dentry->d_parent->d_lock);
|
2018-07-10 03:27:33 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(d_mark_tmpfile);
|
|
|
|
|
|
|
|
void d_tmpfile(struct file *file, struct inode *inode)
|
|
|
|
{
|
|
|
|
struct dentry *dentry = file->f_path.dentry;
|
|
|
|
|
|
|
|
inode_dec_link_count(inode);
|
|
|
|
d_mark_tmpfile(file, inode);
|
2013-06-07 05:20:27 +00:00
|
|
|
d_instantiate(dentry, inode);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2013-06-07 05:20:27 +00:00
|
|
|
EXPORT_SYMBOL(d_tmpfile);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2024-06-27 16:11:52 +00:00
|
|
|
/*
|
|
|
|
* Obtain inode number of the parent dentry.
|
|
|
|
*/
|
|
|
|
ino_t d_parent_ino(struct dentry *dentry)
|
|
|
|
{
|
|
|
|
struct dentry *parent;
|
|
|
|
struct inode *iparent;
|
|
|
|
unsigned seq;
|
|
|
|
ino_t ret;
|
|
|
|
|
|
|
|
scoped_guard(rcu) {
|
|
|
|
seq = raw_seqcount_begin(&dentry->d_seq);
|
|
|
|
parent = READ_ONCE(dentry->d_parent);
|
|
|
|
iparent = d_inode_rcu(parent);
|
|
|
|
if (likely(iparent)) {
|
|
|
|
ret = iparent->i_ino;
|
|
|
|
if (!read_seqcount_retry(&dentry->d_seq, seq))
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
spin_lock(&dentry->d_lock);
|
|
|
|
ret = dentry->d_parent->d_inode->i_ino;
|
|
|
|
spin_unlock(&dentry->d_lock);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(d_parent_ino);
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
static __initdata unsigned long dhash_entries;
|
|
|
|
static int __init set_dhash_entries(char *str)
|
|
|
|
{
|
|
|
|
if (!str)
|
|
|
|
return 0;
|
|
|
|
dhash_entries = simple_strtoul(str, &str, 0);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
__setup("dhash_entries=", set_dhash_entries);
|
|
|
|
|
|
|
|
static void __init dcache_init_early(void)
|
|
|
|
{
|
|
|
|
/* If hashes are distributed across NUMA nodes, defer
|
|
|
|
* hash allocation until vmalloc space is available.
|
|
|
|
*/
|
|
|
|
if (hashdist)
|
|
|
|
return;
|
|
|
|
|
|
|
|
dentry_hashtable =
|
|
|
|
alloc_large_system_hash("Dentry cache",
|
2011-04-24 05:32:03 +00:00
|
|
|
sizeof(struct hlist_bl_head),
|
2005-04-16 22:20:36 +00:00
|
|
|
dhash_entries,
|
|
|
|
13,
|
2017-07-06 22:39:11 +00:00
|
|
|
HASH_EARLY | HASH_ZERO,
|
2005-04-16 22:20:36 +00:00
|
|
|
&d_hash_shift,
|
2017-11-20 15:05:52 +00:00
|
|
|
NULL,
|
2012-05-23 13:33:35 +00:00
|
|
|
0,
|
2005-04-16 22:20:36 +00:00
|
|
|
0);
|
2017-11-20 15:05:07 +00:00
|
|
|
d_hash_shift = 32 - d_hash_shift;
|
2024-06-04 19:30:02 +00:00
|
|
|
|
|
|
|
runtime_const_init(shift, d_hash_shift);
|
|
|
|
runtime_const_init(ptr, dentry_hashtable);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2007-10-17 06:26:30 +00:00
|
|
|
static void __init dcache_init(void)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2017-07-06 22:39:11 +00:00
|
|
|
/*
|
2005-04-16 22:20:36 +00:00
|
|
|
* A constructor could be added for stable state like the lists,
|
|
|
|
* but it is probably not worth it because of the cache nature
|
2017-07-06 22:39:11 +00:00
|
|
|
* of the dcache.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
dcache: Define usercopy region in dentry_cache slab cache
When a dentry name is short enough, it can be stored directly in the
dentry itself (instead in a separate kmalloc allocation). These dentry
short names, stored in struct dentry.d_iname and therefore contained in
the dentry_cache slab cache, need to be coped to userspace.
cache object allocation:
fs/dcache.c:
__d_alloc(...):
...
dentry = kmem_cache_alloc(dentry_cache, ...);
...
dentry->d_name.name = dentry->d_iname;
example usage trace:
filldir+0xb0/0x140
dcache_readdir+0x82/0x170
iterate_dir+0x142/0x1b0
SyS_getdents+0xb5/0x160
fs/readdir.c:
(called via ctx.actor by dir_emit)
filldir(..., const char *name, ...):
...
copy_to_user(..., name, namlen)
fs/libfs.c:
dcache_readdir(...):
...
next = next_positive(dentry, p, 1)
...
dir_emit(..., next->d_name.name, ...)
In support of usercopy hardening, this patch defines a region in the
dentry_cache slab cache in which userspace copy operations are allowed.
This region is known as the slab cache's usercopy region. Slab caches can
now check that each dynamic copy operation involving cache-managed memory
falls entirely within the slab's usercopy region.
This patch is modified from Brad Spengler/PaX Team's PAX_USERCOPY
whitelisting code in the last public patch of grsecurity/PaX based on my
understanding of the code. Changes or omissions from the original code are
mine and don't reflect the original grsecurity/PaX code.
Signed-off-by: David Windsor <dave@nullcore.net>
[kees: adjust hunks for kmalloc-specific things moved later]
[kees: adjust commit log, provide usage trace]
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: linux-fsdevel@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
2017-06-11 02:50:44 +00:00
|
|
|
dentry_cache = KMEM_CACHE_USERCOPY(dentry,
|
2024-02-24 13:53:15 +00:00
|
|
|
SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|SLAB_ACCOUNT,
|
dcache: Define usercopy region in dentry_cache slab cache
When a dentry name is short enough, it can be stored directly in the
dentry itself (instead in a separate kmalloc allocation). These dentry
short names, stored in struct dentry.d_iname and therefore contained in
the dentry_cache slab cache, need to be coped to userspace.
cache object allocation:
fs/dcache.c:
__d_alloc(...):
...
dentry = kmem_cache_alloc(dentry_cache, ...);
...
dentry->d_name.name = dentry->d_iname;
example usage trace:
filldir+0xb0/0x140
dcache_readdir+0x82/0x170
iterate_dir+0x142/0x1b0
SyS_getdents+0xb5/0x160
fs/readdir.c:
(called via ctx.actor by dir_emit)
filldir(..., const char *name, ...):
...
copy_to_user(..., name, namlen)
fs/libfs.c:
dcache_readdir(...):
...
next = next_positive(dentry, p, 1)
...
dir_emit(..., next->d_name.name, ...)
In support of usercopy hardening, this patch defines a region in the
dentry_cache slab cache in which userspace copy operations are allowed.
This region is known as the slab cache's usercopy region. Slab caches can
now check that each dynamic copy operation involving cache-managed memory
falls entirely within the slab's usercopy region.
This patch is modified from Brad Spengler/PaX Team's PAX_USERCOPY
whitelisting code in the last public patch of grsecurity/PaX based on my
understanding of the code. Changes or omissions from the original code are
mine and don't reflect the original grsecurity/PaX code.
Signed-off-by: David Windsor <dave@nullcore.net>
[kees: adjust hunks for kmalloc-specific things moved later]
[kees: adjust commit log, provide usage trace]
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: linux-fsdevel@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
2017-06-11 02:50:44 +00:00
|
|
|
d_iname);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/* Hash may have been set up in dcache_init_early */
|
|
|
|
if (!hashdist)
|
|
|
|
return;
|
|
|
|
|
|
|
|
dentry_hashtable =
|
|
|
|
alloc_large_system_hash("Dentry cache",
|
2011-04-24 05:32:03 +00:00
|
|
|
sizeof(struct hlist_bl_head),
|
2005-04-16 22:20:36 +00:00
|
|
|
dhash_entries,
|
|
|
|
13,
|
2017-07-06 22:39:11 +00:00
|
|
|
HASH_ZERO,
|
2005-04-16 22:20:36 +00:00
|
|
|
&d_hash_shift,
|
2017-11-20 15:05:52 +00:00
|
|
|
NULL,
|
2012-05-23 13:33:35 +00:00
|
|
|
0,
|
2005-04-16 22:20:36 +00:00
|
|
|
0);
|
2017-11-20 15:05:07 +00:00
|
|
|
d_hash_shift = 32 - d_hash_shift;
|
2024-06-04 19:30:02 +00:00
|
|
|
|
|
|
|
runtime_const_init(shift, d_hash_shift);
|
|
|
|
runtime_const_init(ptr, dentry_hashtable);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* SLAB cache for __getname() consumers */
|
2023-10-11 16:55:00 +00:00
|
|
|
struct kmem_cache *names_cachep __ro_after_init;
|
2010-01-05 20:45:18 +00:00
|
|
|
EXPORT_SYMBOL(names_cachep);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
void __init vfs_caches_init_early(void)
|
|
|
|
{
|
2017-06-27 16:19:11 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(in_lookup_hashtable); i++)
|
|
|
|
INIT_HLIST_BL_HEAD(&in_lookup_hashtable[i]);
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
dcache_init_early();
|
|
|
|
inode_init_early();
|
|
|
|
}
|
|
|
|
|
2015-08-06 22:46:20 +00:00
|
|
|
void __init vfs_caches_init(void)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
vfs: Define usercopy region in names_cache slab caches
VFS pathnames are stored in the names_cache slab cache, either inline
or across an entire allocation entry (when approaching PATH_MAX). These
are copied to/from userspace, so they must be entirely whitelisted.
cache object allocation:
include/linux/fs.h:
#define __getname() kmem_cache_alloc(names_cachep, GFP_KERNEL)
example usage trace:
strncpy_from_user+0x4d/0x170
getname_flags+0x6f/0x1f0
user_path_at_empty+0x23/0x40
do_mount+0x69/0xda0
SyS_mount+0x83/0xd0
fs/namei.c:
getname_flags(...):
...
result = __getname();
...
kname = (char *)result->iname;
result->name = kname;
len = strncpy_from_user(kname, filename, EMBEDDED_NAME_MAX);
...
if (unlikely(len == EMBEDDED_NAME_MAX)) {
const size_t size = offsetof(struct filename, iname[1]);
kname = (char *)result;
result = kzalloc(size, GFP_KERNEL);
...
result->name = kname;
len = strncpy_from_user(kname, filename, PATH_MAX);
In support of usercopy hardening, this patch defines the entire cache
object in the names_cache slab cache as whitelisted, since it may entirely
hold name strings to be copied to/from userspace.
This patch is verbatim from Brad Spengler/PaX Team's PAX_USERCOPY
whitelisting code in the last public patch of grsecurity/PaX based on my
understanding of the code. Changes or omissions from the original code are
mine and don't reflect the original grsecurity/PaX code.
Signed-off-by: David Windsor <dave@nullcore.net>
[kees: adjust commit log, add usage trace]
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: linux-fsdevel@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
2017-06-11 02:50:30 +00:00
|
|
|
names_cachep = kmem_cache_create_usercopy("names_cache", PATH_MAX, 0,
|
|
|
|
SLAB_HWCACHE_ALIGN|SLAB_PANIC, 0, PATH_MAX, NULL);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2007-10-17 06:26:30 +00:00
|
|
|
dcache_init();
|
|
|
|
inode_init();
|
2015-08-06 22:46:20 +00:00
|
|
|
files_init();
|
|
|
|
files_maxfiles_init();
|
2007-10-17 06:26:30 +00:00
|
|
|
mnt_init();
|
2005-04-16 22:20:36 +00:00
|
|
|
bdev_cache_init();
|
|
|
|
chrdev_init();
|
|
|
|
}
|