ctx->cred = get_cred(filp->f_cred);
        else
                ctx->cred = get_current_cred();
-       ctx->ll_cred = NULL;
+       rcu_assign_pointer(ctx->ll_cred, NULL);
        ctx->state = NULL;
        ctx->mode = f_mode;
        ctx->flags = 0;
        put_cred(ctx->cred);
        dput(ctx->dentry);
        nfs_sb_deactive(sb);
-       put_rpccred(ctx->ll_cred);
+       put_rpccred(rcu_dereference_protected(ctx->ll_cred, 1));
        kfree(ctx->mdsthreshold);
        kfree_rcu(ctx, rcu_head);
 }
 
        struct nfs_open_context *ctx = nfs_file_open_context(filp);
 
        if (nfs_ctx_key_to_expire(ctx, inode) &&
-           !ctx->ll_cred)
+           !rcu_access_pointer(ctx->ll_cred))
                /* Already expired! */
                return -EACCES;
        return 0;
 bool nfs_ctx_key_to_expire(struct nfs_open_context *ctx, struct inode *inode)
 {
        struct rpc_auth *auth = NFS_SERVER(inode)->client->cl_auth;
-       struct rpc_cred *cred = ctx->ll_cred;
+       struct rpc_cred *cred, *new, *old = NULL;
        struct auth_cred acred = {
                .cred = ctx->cred,
        };
+       bool ret = false;
 
-       if (cred && !cred->cr_ops->crmatch(&acred, cred, 0)) {
-               put_rpccred(cred);
-               ctx->ll_cred = NULL;
-               cred = NULL;
-       }
-       if (!cred)
-               cred = auth->au_ops->lookup_cred(auth, &acred, 0);
-       if (!cred || IS_ERR(cred))
+       rcu_read_lock();
+       cred = rcu_dereference(ctx->ll_cred);
+       if (cred && !(cred->cr_ops->crkey_timeout &&
+                     cred->cr_ops->crkey_timeout(cred)))
+               goto out;
+       rcu_read_unlock();
+
+       new = auth->au_ops->lookup_cred(auth, &acred, 0);
+       if (new == cred) {
+               put_rpccred(new);
                return true;
-       ctx->ll_cred = cred;
-       return !!(cred->cr_ops->crkey_timeout &&
-                 cred->cr_ops->crkey_timeout(cred));
+       }
+       if (IS_ERR_OR_NULL(new)) {
+               new = NULL;
+               ret = true;
+       } else if (new->cr_ops->crkey_timeout &&
+                  new->cr_ops->crkey_timeout(new))
+               ret = true;
+
+       rcu_read_lock();
+       old = rcu_dereference_protected(xchg(&ctx->ll_cred,
+                                            RCU_INITIALIZER(new)), 1);
+out:
+       rcu_read_unlock();
+       put_rpccred(old);
+       return ret;
 }
 
 /*