aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c64
1 files changed, 61 insertions, 3 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 26176ce3d96a..6ad06121d88c 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3454,7 +3454,7 @@ static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
3454 return err; 3454 return err;
3455} 3455}
3456 3456
3457void nfs4_set_rw_stateid(nfs4_stateid *stateid, 3457int nfs4_set_rw_stateid(nfs4_stateid *stateid,
3458 const struct nfs_open_context *ctx, 3458 const struct nfs_open_context *ctx,
3459 const struct nfs_lock_context *l_ctx, 3459 const struct nfs_lock_context *l_ctx,
3460 fmode_t fmode) 3460 fmode_t fmode)
@@ -3463,10 +3463,37 @@ void nfs4_set_rw_stateid(nfs4_stateid *stateid,
3463 3463
3464 if (l_ctx != NULL) 3464 if (l_ctx != NULL)
3465 lockowner = &l_ctx->lockowner; 3465 lockowner = &l_ctx->lockowner;
3466 nfs4_select_rw_stateid(stateid, ctx->state, fmode, lockowner); 3466 return nfs4_select_rw_stateid(stateid, ctx->state, fmode, lockowner);
3467} 3467}
3468EXPORT_SYMBOL_GPL(nfs4_set_rw_stateid); 3468EXPORT_SYMBOL_GPL(nfs4_set_rw_stateid);
3469 3469
3470static bool nfs4_stateid_is_current(nfs4_stateid *stateid,
3471 const struct nfs_open_context *ctx,
3472 const struct nfs_lock_context *l_ctx,
3473 fmode_t fmode)
3474{
3475 nfs4_stateid current_stateid;
3476
3477 if (nfs4_set_rw_stateid(&current_stateid, ctx, l_ctx, fmode))
3478 return false;
3479 return nfs4_stateid_match(stateid, &current_stateid);
3480}
3481
3482static bool nfs4_error_stateid_expired(int err)
3483{
3484 switch (err) {
3485 case -NFS4ERR_DELEG_REVOKED:
3486 case -NFS4ERR_ADMIN_REVOKED:
3487 case -NFS4ERR_BAD_STATEID:
3488 case -NFS4ERR_STALE_STATEID:
3489 case -NFS4ERR_OLD_STATEID:
3490 case -NFS4ERR_OPENMODE:
3491 case -NFS4ERR_EXPIRED:
3492 return true;
3493 }
3494 return false;
3495}
3496
3470void __nfs4_read_done_cb(struct nfs_read_data *data) 3497void __nfs4_read_done_cb(struct nfs_read_data *data)
3471{ 3498{
3472 nfs_invalidate_atime(data->header->inode); 3499 nfs_invalidate_atime(data->header->inode);
@@ -3487,6 +3514,20 @@ static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_read_data *data)
3487 return 0; 3514 return 0;
3488} 3515}
3489 3516
3517static bool nfs4_read_stateid_changed(struct rpc_task *task,
3518 struct nfs_readargs *args)
3519{
3520
3521 if (!nfs4_error_stateid_expired(task->tk_status) ||
3522 nfs4_stateid_is_current(&args->stateid,
3523 args->context,
3524 args->lock_context,
3525 FMODE_READ))
3526 return false;
3527 rpc_restart_call_prepare(task);
3528 return true;
3529}
3530
3490static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data) 3531static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
3491{ 3532{
3492 3533
@@ -3494,7 +3535,8 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
3494 3535
3495 if (!nfs4_sequence_done(task, &data->res.seq_res)) 3536 if (!nfs4_sequence_done(task, &data->res.seq_res))
3496 return -EAGAIN; 3537 return -EAGAIN;
3497 3538 if (nfs4_read_stateid_changed(task, &data->args))
3539 return -EAGAIN;
3498 return data->read_done_cb ? data->read_done_cb(task, data) : 3540 return data->read_done_cb ? data->read_done_cb(task, data) :
3499 nfs4_read_done_cb(task, data); 3541 nfs4_read_done_cb(task, data);
3500} 3542}
@@ -3533,10 +3575,26 @@ static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data
3533 return 0; 3575 return 0;
3534} 3576}
3535 3577
3578static bool nfs4_write_stateid_changed(struct rpc_task *task,
3579 struct nfs_writeargs *args)
3580{
3581
3582 if (!nfs4_error_stateid_expired(task->tk_status) ||
3583 nfs4_stateid_is_current(&args->stateid,
3584 args->context,
3585 args->lock_context,
3586 FMODE_WRITE))
3587 return false;
3588 rpc_restart_call_prepare(task);
3589 return true;
3590}
3591
3536static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) 3592static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
3537{ 3593{
3538 if (!nfs4_sequence_done(task, &data->res.seq_res)) 3594 if (!nfs4_sequence_done(task, &data->res.seq_res))
3539 return -EAGAIN; 3595 return -EAGAIN;
3596 if (nfs4_write_stateid_changed(task, &data->args))
3597 return -EAGAIN;
3540 return data->write_done_cb ? data->write_done_cb(task, data) : 3598 return data->write_done_cb ? data->write_done_cb(task, data) :
3541 nfs4_write_done_cb(task, data); 3599 nfs4_write_done_cb(task, data);
3542} 3600}