projects/linux·commit e8a56d6f

Merge tag 'pull-dcache' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

e8a56d6f · Linus Torvalds <[email protected]> · 2026-06-15 04:15:31 +05:30

Pull dcache updates from Al Viro:

 - d_alloc_parallel() API change (Neil's with my changes)

 - NORCU fixes

 - Reorganization and simplification of dentry eviction logic

 - Simplifying rcu_read_lock() scopes in fs/dcache.c

 - Secondary roots work - getting rid of NFS fake root dentries and
   dealing with remaining shrink_dcache_for_umount() and
   shrink_dentry_list() races

 - making cursors NORCU (surprisingly easy)

* tag 'pull-dcache' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (22 commits)
  make cursors NORCU
  nfs: get rid of fake root dentries
  wind ->s_roots via ->d_sib instead of ->d_hash
  shrink_dentry_tree(): unify the calls of shrink_dentry_list()
  shrinking rcu_read_lock() scope in d_alloc_parallel()
  d_walk(): shrink rcu_read_lock() scope
  document dentry_kill()
  adjust calling conventions of lock_for_kill(), fold __dentry_kill() into dentry_kill()
  Document rcu_read_lock() use in select_collect2()
  Shift rcu_read_{,un}lock() inside fast_dput()
  simplify safety for lock_for_kill() slowpath
  fold lock_for_kill() and __dentry_kill() into common helper
  fold lock_for_kill() into shrink_kill()
  shrink_dentry_list(): start with removing from shrink list
  d_prune_aliases(): make sure to skip NORCU aliases
  kill d_dispose_if_unused()
  make to_shrink_list() return whether it has moved dentry to list
  select_collect(): ignore dentries on shrink lists if they have positive refcounts
  find_acceptable_alias(): skip NORCU aliases with zero refcount
  fix a race between d_find_any_alias() and final dput() of NORCU dentries
  ...
Commit
e8a56d6fc828bb569fa2dd33c3e6eb16a165b097
Parents
79169a16 · 3df5153c

Merge commit. Changes below are compared with the first parent: 79169a16.

Changes

18 files changed · +387 −294

Only the first 600 diff lines are shown. Download the complete patch.

Documentation/filesystems/porting.rst

View file
diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst
index f546b1d..d13f0a2 100644
--- a/Documentation/filesystems/porting.rst
+++ b/Documentation/filesystems/porting.rst
@@ -1384,3 +1384,20 @@ for_each_alias(dentry, inode) instead of hlist_for_each_entry; better
yet, see if any of the exported primitives could be used instead of
the entire loop. You still need to hold ->i_lock of the inode over
either form of manual loop.
+
+---
+
+**mandatory**
+
+d_alloc_parallel() no longer requires a waitqueue_head.
+
+---
+
+**mandatory**
+
+d_dispose_if_unused() is gone; use __move_to_shrink_list() if you really
+need that functionality, but watch out for memory safety issues - just
+as with d_dispose_if_unused() these are not trivial; with this variant
+of API it's more explicit, since grabbing ->d_lock is caller-side, but
+d_dispose_if_unused() had all the same issues. It's a low-level primitive;
+use only if you have no alternative.

fs/afs/dir_silly.c

View file
diff --git a/fs/afs/dir_silly.c b/fs/afs/dir_silly.c
index a748fd1..982bb6e 100644
--- a/fs/afs/dir_silly.c
+++ b/fs/afs/dir_silly.c
@@ -248,13 +248,11 @@ int afs_silly_iput(struct dentry *dentry, struct inode *inode)
struct dentry *alias;
int ret;
- DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
-
_enter("%p{%pd},%llx", dentry, dentry, vnode->fid.vnode);
down_read(&dvnode->rmdir_lock);
- alias = d_alloc_parallel(dentry->d_parent, &dentry->d_name, &wq);
+ alias = d_alloc_parallel(dentry->d_parent, &dentry->d_name);
if (IS_ERR(alias)) {
up_read(&dvnode->rmdir_lock);
return 0;

fs/dcache.c

View file
diff --git a/fs/dcache.c b/fs/dcache.c
index d6f5053..3e9af9d 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -43,8 +43,8 @@
* - i_dentry, d_alias, d_inode of aliases
* dcache_hash_bucket lock protects:
* - the dcache hash table
- * s_roots bl list spinlock protects:
- * - the s_roots list (see __d_drop)
+ * s_roots_lock protects:
+ * - the s_roots list (see __d_move()/dentry_unlist()/d_obtain_root())
* dentry->d_sb->s_dentry_lru_lock protects:
* - the dcache lru lists and counters
* d_lock protects:
@@ -462,14 +462,10 @@ static void dentry_unlink_inode(struct dentry * dentry)
raw_write_seqcount_begin(&dentry->d_seq);
__d_clear_type_and_inode(dentry);
- hlist_del_init(&dentry->d_alias);
+ __hlist_del(&dentry->d_alias);
/*
* dentry becomes negative, so the space occupied by ->d_alias
- * belongs to ->waiters now; we could use __hlist_del() instead
- * of hlist_del_init(), if not for the stunt pulled by nfs
- * dummy root dentries - positive dentry *not* included into
- * the alias list of its inode. Open-coding hlist_del_init()
- * and removing zeroing would be too clumsy...
+ * belongs to ->waiters now.
*/
dentry->waiters = NULL;
raw_write_seqcount_end(&dentry->d_seq);
@@ -568,16 +564,7 @@ static void d_lru_shrink_move(struct list_lru_one *lru, struct dentry *dentry,
static void ___d_drop(struct dentry *dentry)
{
- 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);
+ struct hlist_bl_head *b = d_hash(dentry->d_name.hash);
hlist_bl_lock(b);
__hlist_bl_del(&dentry->d_hash);
@@ -636,12 +623,14 @@ struct completion_list {
* Use ->waiters for a single-linked list of struct completion_list of
* waiters.
*/
-static inline void d_add_waiter(struct dentry *dentry, struct completion_list *p)
+static inline bool d_add_waiter(struct dentry *dentry, struct completion_list *p)
{
- struct completion_list *v = dentry->waiters;
+ if (unlikely(dentry->d_flags & DCACHE_DENTRY_KILLED))
+ return false;
init_completion(&p->completion);
- p->next = v;
+ p->next = dentry->waiters;
dentry->waiters = p;
+ return true;
}
static inline void d_complete_waiters(struct dentry *dentry)
@@ -658,6 +647,13 @@ static inline void d_complete_waiters(struct dentry *dentry)
}
}
+static void unlink_secondary_root(struct dentry *dentry)
+{
+ spin_lock(&dentry->d_sb->s_roots_lock);
+ hlist_del_init(&dentry->d_sib);
+ spin_unlock(&dentry->d_sb->s_roots_lock);
+}
+
static inline void dentry_unlist(struct dentry *dentry)
{
struct dentry *next;
@@ -669,6 +665,10 @@ static inline void dentry_unlist(struct dentry *dentry)
d_complete_waiters(dentry);
if (unlikely(hlist_unhashed(&dentry->d_sib)))
return;
+ if (unlikely(IS_ROOT(dentry))) {
+ unlink_secondary_root(dentry); // secondary root goes away
+ return;
+ }
__hlist_del(&dentry->d_sib);
/*
* Cursors can move around the list of children. While we'd been
@@ -697,11 +697,113 @@ static inline void dentry_unlist(struct dentry *dentry)
}
}
-static struct dentry *__dentry_kill(struct dentry *dentry)
+/*
+ * Prepare locking environment for killing a dentry.
+ * Called under dentry->d_lock. To proceed with eviction of a positive dentry
+ * we need to get ->i_lock of the inode of that dentry as well.
+ * However, ->i_lock nests outside of ->d_lock, so if trylock fails we might
+ * have to drop and regain the latter. Dentry state can change while its
+ * ->d_lock is not held - it might end up getting killed, becoming busy,
+ * negative, etc., so we need to be careful.
+ *
+ * For NORCU dentries memory safety relies upon having only one call of
+ * lock_for_kill() in the entire lifetime of dentry and dentry_free() being
+ * called only by the caller of lock_for_kill(). That this is NORCU-specific;
+ * the crucial part is that refcounts of NORCU dentries never grow once having
+ * dropped to zero.
+ *
+ * For normal dentries we can not assume that there won't be concurrent calls
+ * of dentry_free() - dentry might end up being evicted by another thread
+ * while we are dropping/retaking locks on the slow path. Memory safety is
+ * provided by keeping the RCU read-side critical area contiguous with
+ * an explicit rcu_read_lock() scope bridging over the break in spinlock scopes.
+ *
+ * If dentry is busy (or busy dying, or already dead), unlock dentry
+ * and return false. Otherwise, return true and have that dentry's
+ * inode (if any) locked in addition to dentry itself.
+ */
+static bool lock_for_kill(struct dentry *dentry)
+{
+ struct inode *inode = dentry->d_inode;
+
+ if (unlikely(dentry->d_lockref.count)) {
+ spin_unlock(&dentry->d_lock);
+ return false;
+ }
+
+ if (!inode || likely(spin_trylock(&inode->i_lock)))
+ return true;
+
+ // Too bad - we need to drop ->d_lock and take locks in correct order.
+ // To avoid breaking RCU read-side critical area when we drop ->d_lock,
+ // take an explicit rcu_read_lock() while we are switching locks.
+ rcu_read_lock();
+ do {
+ spin_unlock(&dentry->d_lock);
+ spin_lock(&inode->i_lock);
+ spin_lock(&dentry->d_lock);
+ // make sure we'd locked the right inode - ->d_inode might've
+ // changed while we were not holding ->d_lock
+ if (likely(inode == dentry->d_inode))
+ break;
+ spin_unlock(&inode->i_lock);
+ inode = dentry->d_inode;
+ } while (inode);
+ rcu_read_unlock();
+ if (likely(!dentry->d_lockref.count))
+ return true;
+ if (inode)
+ spin_unlock(&inode->i_lock);
+ spin_unlock(&dentry->d_lock);
+ return false;
+}
+
+/**
+ * dentry_kill - evict a dentry
+ * @dentry: dentry to be evicted
+ *
+ * All dentry evictions are done by this function. The reference we are
+ * passed does not contribute to the refcount; the caller had either
+ * already decremented the refcount or it had never held one in the
+ * first place. @dentry->d_lock is held by the caller and dropped
+ * by dentry_kill(@dentry).
+ *
+ * We are guaranteed that nobody had called dentry_free(@dentry)
+ * prior to the beginning of RCU read-side critical area we are in.
+ *
+ * Caller must not access @dentry after the call.
+ *
+ * If eviction of @dentry drops the last reference to its parent,
+ * the reference to parent is returned to caller. In that case
+ * it is guaranteed to satisfy the requirements for dentry_kill()
+ * argument - its ->d_lock is held and we are guaranteed that nobody
+ * had passed it to dentry_free() prior to acquisition of its ->d_lock.
+ * Otherwise %NULL is returned.
+ *
+ * If @dentry is idle and remains such after we assemble the full
+ * locking environment for eviction (see lock_for_kill() for details)
+ * we mark it doomed (->d_lockref.count < 0) and proceed to detaching
+ * it from any filesystem objects. Otherwise we drop ->d_lock and
+ * return %NULL.
+ *
+ * Once @dentry is detached from the filesystem objects, we complete
+ * detaching it from dentry tree. The parent, if any, gets locked
+ * and its refcount is decremented; dentry is carefully removed from
+ * the tree (see dentry_unlist() for details) and marked killed
+ * (%DCACHE_DENTRY_KILLED set in ->d_flags). At that point it's just
+ * an inert chunk of memory, accessible only via RCU references
+ * and possibly via a shrink list. If it is not on any shrink lists,
+ * we call dentry_free(), which schedules actual freeing of memory.
+ * Othewise freeing is left to the owner of the shrink list in question.
+ */
+static struct dentry *dentry_kill(struct dentry *dentry)
{
struct dentry *parent = NULL;
bool can_free = true;
+ if (unlikely(!lock_for_kill(dentry)))
+ return NULL;
+
/*
* The dentry is now unrecoverably dead to the world.
*/
@@ -749,43 +851,6 @@ static struct dentry *__dentry_kill(struct dentry *dentry)
}
/*
- * 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
- * that dentry's inode locked.
- */
-
-static bool lock_for_kill(struct dentry *dentry)
-{
- struct inode *inode = dentry->d_inode;
-
- if (unlikely(dentry->d_lockref.count))
- return false;
-
- if (!inode || likely(spin_trylock(&inode->i_lock)))
- return true;
-
- do {
- spin_unlock(&dentry->d_lock);
- spin_lock(&inode->i_lock);
- spin_lock(&dentry->d_lock);
- if (likely(inode == dentry->d_inode))
- break;
- spin_unlock(&inode->i_lock);
- inode = dentry->d_inode;
- } while (inode);
- if (likely(!dentry->d_lockref.count))
- return true;
- if (inode)
- spin_unlock(&inode->i_lock);
- return false;
-}
-
-/*
* 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".
@@ -860,17 +925,17 @@ EXPORT_SYMBOL(d_mark_dontcache);
* If unsuccessful, we return false, having already taken the dentry lock.
* In that case refcount is guaranteed to be zero and we have already
* decided that it's not worth keeping around.
- *
- * 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;
/*
- * try to decrement the lockref optimistically.
+ * Try to decrement the lockref optimistically.
+ * RCU read lock held so that dentry is guaranteed to stay around
+ * even if the refcount goes down to zero.
*/
+ rcu_read_lock();
ret = lockref_put_return(&dentry->d_lockref);
/*
@@ -880,6 +945,7 @@ static inline bool fast_dput(struct dentry *dentry)
*/
if (unlikely(ret < 0)) {
spin_lock(&dentry->d_lock);
+ rcu_read_unlock();
if (WARN_ON_ONCE(dentry->d_lockref.count <= 0)) {
spin_unlock(&dentry->d_lock);
return true;
@@ -891,8 +957,10 @@ static inline bool fast_dput(struct dentry *dentry)
/*
* If we weren't the last ref, we're done.
*/
- if (ret)
+ if (ret) {
+ rcu_read_unlock();
return true;
+ }
/*
* Can we decide that decrement of refcount is all we needed without
@@ -900,8 +968,10 @@ static inline bool fast_dput(struct dentry *dentry)
* dentry looks like it ought to be retained and there's nothing else
* to do.
*/
- if (retain_dentry(dentry, false))
+ if (retain_dentry(dentry, false)) {
+ rcu_read_unlock();
return true;
+ }
/*
* Either not worth retaining or we can't tell without the lock.
@@ -909,6 +979,7 @@ static inline bool fast_dput(struct dentry *dentry)
* but we'll need to re-check the situation after getting the lock.
*/
spin_lock(&dentry->d_lock);
+ rcu_read_unlock();
/*
* Did somebody else grab a reference to it in the meantime, and
@@ -926,21 +997,13 @@ locked:
static void finish_dput(struct dentry *dentry)
__releases(dentry->d_lock)
- __releases(RCU)
{
- while (lock_for_kill(dentry)) {
- rcu_read_unlock();
- dentry = __dentry_kill(dentry);
- if (!dentry)
- return;
+ while ((dentry = dentry_kill(dentry)) != NULL) {
if (retain_dentry(dentry, true)) {
spin_unlock(&dentry->d_lock);
return;
}
- rcu_read_lock();
}
- rcu_read_unlock();
- spin_unlock(&dentry->d_lock);
}
/*
@@ -974,11 +1037,8 @@ void dput(struct dentry *dentry)
if (!dentry)
return;
might_sleep();
- rcu_read_lock();
- if (likely(fast_dput(dentry))) {
- rcu_read_unlock();
+ if (likely(fast_dput(dentry)))
return;
- }
finish_dput(dentry);
}
EXPORT_SYMBOL(dput);
@@ -989,30 +1049,46 @@ void d_make_discardable(struct dentry *dentry)
WARN_ON(!(dentry->d_flags & DCACHE_PERSISTENT));
dentry->d_flags &= ~DCACHE_PERSISTENT;
dentry->d_lockref.count--;
- rcu_read_lock();
finish_dput(dentry);
}
EXPORT_SYMBOL(d_make_discardable);
-static void to_shrink_list(struct dentry *dentry, struct list_head *list)
+/**
+ * __move_to_shrink_list - try to place a dentry into a shrink list
+ * @dentry: dentry to try putting into shrink list
+ * @list: the list to put @dentry into.
+ * Returns: true @dentry had been placed into @list, false otherwise
+ *
+ * If @dentry is idle and not already include into a shrink list, move
+ * it into @list and return %true; otherwise do nothing and return %false.
+ *
+ * Caller must be holding @dentry->d_lock. There must have been no calls of
+ * dentry_free(@dentry) prior to the beginning of the RCU read-side critical
+ * area in which __move_to_shrink_list(@dentry, @list) is called.
+ *
+ * @list should be thread-private and eventually emptied by passing it to
+ * shrink_dentry_list().
+ */
+
+bool __move_to_shrink_list(struct dentry *dentry, struct list_head *list)
__must_hold(&dentry->d_lock)
{
- if (!(dentry->d_flags & DCACHE_SHRINK_LIST)) {
+ if (likely(!dentry->d_lockref.count &&
+ !(dentry->d_flags & DCACHE_SHRINK_LIST))) {
if (dentry->d_flags & DCACHE_LRU_LIST)
d_lru_del(dentry);
d_shrink_add(dentry, list);
+ return true;
}
+ return false;
}
+EXPORT_SYMBOL(__move_to_shrink_list);
void dput_to_list(struct dentry *dentry, struct list_head *list)
{
- rcu_read_lock();
- if (likely(fast_dput(dentry))) {
- rcu_read_unlock();
+ if (likely(fast_dput(dentry)))
return;
- }
- rcu_read_unlock();
- to_shrink_list(dentry, list);
+ __move_to_shrink_list(dentry, list);
spin_unlock(&dentry->d_lock);
}
@@ -1058,7 +1134,10 @@ repeat:
}
EXPORT_SYMBOL(dget_parent);
-static struct dentry * __d_find_any_alias(struct inode *inode)
+/*
+ * inode is a directory, inode->i_lock is held by the caller
+ */
+static struct dentry * __d_find_dir_alias(struct inode *inode)
{
struct dentry *alias;
@@ -1069,6 +1148,18 @@ static struct dentry * __d_find_any_alias(struct inode *inode)
return alias;
}
+static struct dentry * __d_find_any_alias(struct inode *inode)
+{
+ struct dentry *alias;
+
+ if (hlist_empty(&inode->i_dentry))
+ return NULL;
+ for_each_alias(alias, inode)
+ if (dget_alias_ilocked(alias))
+ return alias;
+ return NULL;
+}
+
/**
* d_find_any_alias - find any alias for a given inode
* @inode: inode to find an alias for
@@ -1092,7 +1183,7 @@ static struct dentry *__d_find_alias(struct inode *inode)
struct dentry *alias;
if (S_ISDIR(inode->i_mode))
- return __d_find_any_alias(inode);
+ return __d_find_dir_alias(inode);
for_each_alias(alias, inode) {
spin_lock(&alias->d_lock);
@@ -1158,25 +1249,6 @@ struct dentry *d_find_alias_rcu(struct inode *inode)
return de;
}
-/**
- * d_dispose_if_unused - move unreferenced dentries to shrink list
- * @dentry: dentry in question
- * @dispose: head of shrink list
- *
- * If dentry has no external references, move it to shrink list.
- *
- * NOTE!!! The caller is responsible for preventing eviction of the dentry by
- * holding dentry->d_inode->i_lock or equivalent.
- */
-void d_dispose_if_unused(struct dentry *dentry, struct list_head *dispose)
-{
- spin_lock(&dentry->d_lock);
- if (!dentry->d_lockref.count)
- to_shrink_list(dentry, dispose);
- spin_unlock(&dentry->d_lock);
-}
-EXPORT_SYMBOL(d_dispose_if_unused);
-
/*
* Try to kill dentries associated with this inode.
* WARNING: you must own a reference to inode.
@@ -1187,8 +1259,12 @@ void d_prune_aliases(struct inode *inode)
struct dentry *dentry;
spin_lock(&inode->i_lock);
- for_each_alias(dentry, inode)
- d_dispose_if_unused(dentry, &dispose);
+ for_each_alias(dentry, inode) {
+ spin_lock(&dentry->d_lock);
+ if (likely(!(dentry->d_flags & DCACHE_NORCU)))
+ __move_to_shrink_list(dentry, &dispose);
+ spin_unlock(&dentry->d_lock);
+ }
spin_unlock(&inode->i_lock);
shrink_dentry_list(&dispose);
}
@@ -1196,14 +1272,8 @@ EXPORT_SYMBOL(d_prune_aliases);
static inline void shrink_kill(struct dentry *victim)
{
- 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);
+ while ((victim = dentry_kill(victim)) != NULL)
+ ;
}
void shrink_dentry_list(struct list_head *list)
@@ -1213,18 +1283,12 @@ void shrink_dentry_list(struct list_head *list)
dentry = list_entry(list->prev, struct dentry, d_lru);
spin_lock(&dentry->d_lock);
- rcu_read_lock();
- if (!lock_for_kill(dentry)) {
- bool can_free;
- rcu_read_unlock();
- d_shrink_del(dentry);
- can_free = dentry->d_flags & DCACHE_DENTRY_KILLED;
+ d_shrink_del(dentry);
+ if (unlikely(dentry->d_flags & DCACHE_DENTRY_KILLED)) {
spin_unlock(&dentry->d_lock);
- if (can_free)
- dentry_free(dentry);
+ dentry_free(dentry);
continue;
}
- d_shrink_del(dentry);
shrink_kill(dentry);
}
}
@@ -1385,6 +1449,8 @@ again:
read_seqbegin_or_lock(&rename_lock, &seq);
this_parent = parent;
spin_lock(&this_parent->d_lock);
+ if (unlikely(this_parent->d_flags & DCACHE_DENTRY_CURSOR))
+ goto out_unlock;
ret = enter(data, this_parent);
switch (ret) {
@@ -1433,14 +1499,15 @@ resume:
/*
* All done at this level ... ascend and resume the search.
*/
- rcu_read_lock();
ascend:
if (this_parent != parent) {
dentry = this_parent;
this_parent = dentry->d_parent;
+ rcu_read_lock();
spin_unlock(&dentry->d_lock);
spin_lock(&this_parent->d_lock);
+ rcu_read_unlock();
/* might go back up the wrong parent if we have had a rename. */
if (need_seqretry(&rename_lock, seq))
@@ -1448,7 +1515,6 @@ ascend:
/* go into the first sibling still alive */
hlist_for_each_entry_continue(dentry, d_sib) {
if (likely(!(dentry->d_flags & DCACHE_DENTRY_KILLED))) {

This diff is incomplete. Download the complete patch.

fs/exportfs/expfs.c

View file

This diff is incomplete. Download the complete patch.

fs/file_table.c

View file

This diff is incomplete. Download the complete patch.

fs/fuse/dir.c

View file

This diff is incomplete. Download the complete patch.

fs/fuse/readdir.c

View file

This diff is incomplete. Download the complete patch.

fs/namei.c

View file

This diff is incomplete. Download the complete patch.

fs/nfs/dir.c

View file

This diff is incomplete. Download the complete patch.

fs/nfs/getroot.c

View file

This diff is incomplete. Download the complete patch.

fs/nfs/unlink.c

View file

This diff is incomplete. Download the complete patch.

fs/proc/base.c

View file

This diff is incomplete. Download the complete patch.

fs/proc/proc_sysctl.c

View file

This diff is incomplete. Download the complete patch.

fs/smb/client/readdir.c

View file

This diff is incomplete. Download the complete patch.

fs/super.c

View file

This diff is incomplete. Download the complete patch.

include/linux/dcache.h

View file

This diff is incomplete. Download the complete patch.

include/linux/fs/super_types.h

View file

This diff is incomplete. Download the complete patch.

include/linux/nfs_xdr.h

View file

This diff is incomplete. Download the complete patch.