diff options
author | NeilBrown <neilb@suse.de> | 2014-10-13 15:52:20 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-14 02:18:16 +0200 |
commit | 4d885f90e3784df77945101d8ec32dc798a49862 (patch) | |
tree | a034e761a43d14bb24f27e98a0cd3f568bbf7732 /fs/autofs4/autofs_i.h | |
parent | 6ece08e6187a62dd5bdf7c49539980571922c551 (diff) | |
download | linux-4d885f90e3784df77945101d8ec32dc798a49862.tar.gz linux-4d885f90e3784df77945101d8ec32dc798a49862.tar.bz2 linux-4d885f90e3784df77945101d8ec32dc798a49862.zip |
autofs4: avoid taking fs_lock during rcu-walk
->fs_lock protects AUTOFS_INF_EXPIRING. We need to be sure that once
the flag is set, no new references beneath the dentry are taken. So
rcu-walk currently needs to take fs_lock before checking the flag. This
hurts performance.
Change the expiry to a two-stage process. First set AUTOFS_INF_NO_RCU
which forces any path walk into ref-walk mode, then drop the lock and
call synchronize_rcu(). Once that returns we can be sure no rcu-walk is
active beneath the dentry and we can check reference counts again.
Now during an RCU-walk we can test AUTOFS_INF_EXPIRING without taking
the lock as along as we test AUTOFS_INF_NO_RCU too. If either are set,
we must abort the RCU-walk If neither are set, we know that refcounts
will be tested again after we finish the RCU-walk so we are safe to
continue.
->fs_lock is still taken in d_manage() to check for a non-trap
directory. That will be resolved in the next patch.
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Ian Kent <raven@themaw.net>
Tested-by: Ian Kent <raven@themaw.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/autofs4/autofs_i.h')
-rw-r--r-- | fs/autofs4/autofs_i.h | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index 2f1032f12d91..8e98cf954bab 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h @@ -79,6 +79,10 @@ struct autofs_info { }; #define AUTOFS_INF_EXPIRING (1<<0) /* dentry is in the process of expiring */ +#define AUTOFS_INF_NO_RCU (1<<1) /* the dentry is being considered + * for expiry, so RCU_walk is + * not permitted + */ #define AUTOFS_INF_PENDING (1<<2) /* dentry pending mount */ struct autofs_wait_queue { |