From: NeilBrown <neilb@suse.de>
To: Trond Myklebust <trond.myklebust@primarydata.com>
Cc: linux-nfs@vger.kernel.org
Subject: [PATCH 4/7] NFS: support RCU_WALK in nfs_permission()
Date: Mon, 14 Jul 2014 11:28:20 +1000 [thread overview]
Message-ID: <20140714012820.12562.43671.stgit@notabene.brown> (raw)
In-Reply-To: <20140714011630.12562.1940.stgit@notabene.brown>
nfs_permission makes two calls which are not always safe in RCU_WALK,
rpc_lookup_cred and nfs_do_access.
The second can easily be made rcu-safe by aborting with -ECHILD before
making the RPC call.
The former can be made rcu-safe by calling rpc_lookup_cred_nonblock()
instead.
As this will almost always succeed, we use it even when RCU_WALK
isn't being used as it still saves some spinlocks in a common case.
We only fall back to rpc_lookup_cred() if rpc_lookup_cred_nonblock()
fails and MAY_NOT_BLOCK isn't set.
This optimisation (always trying rpc_lookup_cred_nonblock()) is
particularly important when a security module is active.
In that case inode_permission() may return -ECHILD from
security_inode_permission() even though ->permission() succeeded in
RCU_WALK mode.
This leads to may_lookup() retrying inode_permission after performing
unlazy_walk(). The spinlock that rpc_lookup_cred() takes is often
more expensive than anything security_inode_permission() does, so that
spinlock becomes the main bottleneck.
Signed-off-by: NeilBrown <neilb@suse.de>
---
fs/nfs/dir.c | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 3c2b36acf291..ac958f29e558 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -2288,6 +2288,10 @@ static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
if (status == 0)
goto out_cached;
+ status = -ECHILD;
+ if (mask & MAY_NOT_BLOCK)
+ goto out;
+
/* Be clever: ask server to check for all possible rights */
cache.mask = MAY_EXEC | MAY_WRITE | MAY_READ;
cache.cred = cred;
@@ -2364,15 +2368,23 @@ force_lookup:
if (!NFS_PROTO(inode)->access)
goto out_notsup;
- if (mask & MAY_NOT_BLOCK)
- return -ECHILD;
-
- cred = rpc_lookup_cred();
- if (!IS_ERR(cred)) {
- res = nfs_do_access(inode, cred, mask);
- put_rpccred(cred);
- } else
+ /* Always try fast lookups first */
+ rcu_read_lock();
+ cred = rpc_lookup_cred_nonblock();
+ if (!IS_ERR(cred))
+ res = nfs_do_access(inode, cred, mask|MAY_NOT_BLOCK);
+ else
res = PTR_ERR(cred);
+ rcu_read_unlock();
+ if (res == -ECHILD && !(mask & MAY_NOT_BLOCK)) {
+ /* Fast lookup failed, try the slow way */
+ cred = rpc_lookup_cred();
+ if (!IS_ERR(cred)) {
+ res = nfs_do_access(inode, cred, mask);
+ put_rpccred(cred);
+ } else
+ res = PTR_ERR(cred);
+ }
out:
if (!res && (mask & MAY_EXEC) && !execute_ok(inode))
res = -EACCES;
next prev parent reply other threads:[~2014-07-14 1:31 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-07-14 1:28 [PATCH 0/7] Add RCU-walk support to NFS NeilBrown
2014-07-14 1:28 ` [PATCH 7/7] NFS: allow lockless access to access_cache NeilBrown
2014-07-14 1:28 ` [PATCH 5/7] NFS: teach nfs_neg_need_reval to understand LOOKUP_RCU NeilBrown
2014-07-14 1:28 ` [PATCH 1/7] NFS: nfs4_lookup_revalidate: only evaluate parent if it will be used NeilBrown
2014-07-15 16:56 ` Christoph Hellwig
2014-07-14 1:28 ` NeilBrown [this message]
2014-07-14 1:28 ` [PATCH 6/7] NFS: teach nfs_lookup_verify_inode to handle LOOKUP_RCU NeilBrown
2014-07-14 1:28 ` [PATCH 2/7] NFS: prepare for RCU-walk support but pushing tests later in code NeilBrown
2014-07-14 1:28 ` [PATCH 3/7] sunrpc/auth: allow lockless (rcu) lookup of credential cache NeilBrown
2014-07-14 2:00 ` [PATCH 0/7] Add RCU-walk support to NFS Trond Myklebust
2014-07-14 2:25 ` NeilBrown
2014-07-14 2:39 ` Trond Myklebust
2014-07-23 7:14 ` NeilBrown
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20140714012820.12562.43671.stgit@notabene.brown \
--to=neilb@suse.de \
--cc=linux-nfs@vger.kernel.org \
--cc=trond.myklebust@primarydata.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.