@@ -1006,7 +1006,7 @@ int nfs_initiate_write(struct rpc_clnt *clnt,
.callback_ops = call_ops,
.callback_data = data,
.workqueue = nfsiod_workqueue,
- .flags = RPC_TASK_ASYNC | flags,
+ .flags = RPC_TASK_ASYNC | RPC_TASK_BUF_WRITE | flags,
.priority = priority,
};
int ret = 0;
@@ -123,6 +123,7 @@ struct rpc_task_setup {
#define RPC_TASK_TIMEOUT 0x1000 /* fail with ETIMEDOUT on timeout */
#define RPC_TASK_NOCONNECT 0x2000 /* return ENOTCONN if not connected */
#define RPC_TASK_NO_RETRANS_TIMEOUT 0x4000 /* wait forever for a reply */
+#define RPC_TASK_BUF_WRITE 0x8000 /* allow buffered writes with destroyed credential key */
#define RPC_IS_ASYNC(t) ((t)->tk_flags & RPC_TASK_ASYNC)
#define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER)
@@ -650,6 +650,8 @@ rpcauth_bindcred(struct rpc_task *task, struct rpc_cred *cred, int flags)
struct rpc_cred *new;
int lookupflags = 0;
+ if (flags & RPC_TASK_BUF_WRITE)
+ lookupflags |= RPC_TASK_BUF_WRITE;
if (flags & RPC_TASK_ASYNC)
lookupflags |= RPCAUTH_LOOKUP_NEW;
if (cred != NULL)
@@ -1511,8 +1511,14 @@ check_expire:
if (ret == 0)
return ret;
- if (test_bit(RPCAUTH_CRED_KEY_DESTROYED, &rc->cr_flags))
- return 0;
+ /* Has kdestroy -> gss-ctx key destroy occurred? */
+ if (test_bit(RPCAUTH_CRED_KEY_DESTROYED, &rc->cr_flags)) {
+ /* tell NFS layer no more buffered writes */
+ set_bit(RPC_CRED_KEY_EXPIRE_SOON, &acred->ac_flags);
+ /* if this is not a buffered write, return not found */
+ if (!(flags & RPC_TASK_BUF_WRITE))
+ return 0;
+ }
/* Notify acred users of GSS context expiration timeout */
if (test_bit(RPC_CRED_NOTIFY_TIMEOUT, &acred->ac_flags) &&