sunrpc/auth: allow lockless (rcu) lookup of credential cache.
[deliverable/linux.git] / net / sunrpc / auth.c
index 360decdddc783405b9527f32dcf240f9878809fe..24fcbd23ae6c7e96af1f393f7e1c9a4650dabe1c 100644 (file)
@@ -557,6 +557,12 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
        hlist_for_each_entry_rcu(entry, &cache->hashtable[nr], cr_hash) {
                if (!entry->cr_ops->crmatch(acred, entry, flags))
                        continue;
+               if (flags & RPCAUTH_LOOKUP_RCU) {
+                       if (test_bit(RPCAUTH_CRED_HASHED, &entry->cr_flags) &&
+                           !test_bit(RPCAUTH_CRED_NEW, &entry->cr_flags))
+                               cred = entry;
+                       break;
+               }
                spin_lock(&cache->lock);
                if (test_bit(RPCAUTH_CRED_HASHED, &entry->cr_flags) == 0) {
                        spin_unlock(&cache->lock);
@@ -571,6 +577,9 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
        if (cred != NULL)
                goto found;
 
+       if (flags & RPCAUTH_LOOKUP_RCU)
+               return ERR_PTR(-ECHILD);
+
        new = auth->au_ops->crcreate(auth, acred, flags);
        if (IS_ERR(new)) {
                cred = new;
@@ -621,10 +630,14 @@ rpcauth_lookupcred(struct rpc_auth *auth, int flags)
        memset(&acred, 0, sizeof(acred));
        acred.uid = cred->fsuid;
        acred.gid = cred->fsgid;
-       acred.group_info = get_group_info(((struct cred *)cred)->group_info);
+       if (flags & RPCAUTH_LOOKUP_RCU)
+               acred.group_info = rcu_dereference(cred->group_info);
+       else
+               acred.group_info = get_group_info(((struct cred *)cred)->group_info);
 
        ret = auth->au_ops->lookup_cred(auth, &acred, flags);
-       put_group_info(acred.group_info);
+       if (!(flags & RPCAUTH_LOOKUP_RCU))
+               put_group_info(acred.group_info);
        return ret;
 }
 EXPORT_SYMBOL_GPL(rpcauth_lookupcred);
This page took 0.027135 seconds and 5 git commands to generate.