diff options
Diffstat (limited to 'fs/nfs/proc.c')
| -rw-r--r-- | fs/nfs/proc.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index ef583854d8d0..c752d944fe9e 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
| @@ -47,6 +47,39 @@ | |||
| 47 | #define NFSDBG_FACILITY NFSDBG_PROC | 47 | #define NFSDBG_FACILITY NFSDBG_PROC |
| 48 | 48 | ||
| 49 | /* | 49 | /* |
| 50 | * wrapper to handle the -EKEYEXPIRED error message. This should generally | ||
| 51 | * only happen if using krb5 auth and a user's TGT expires. NFSv2 doesn't | ||
| 52 | * support the NFSERR_JUKEBOX error code, but we handle this situation in the | ||
| 53 | * same way that we handle that error with NFSv3. | ||
| 54 | */ | ||
| 55 | static int | ||
| 56 | nfs_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) | ||
| 57 | { | ||
| 58 | int res; | ||
| 59 | do { | ||
| 60 | res = rpc_call_sync(clnt, msg, flags); | ||
| 61 | if (res != -EKEYEXPIRED) | ||
| 62 | break; | ||
| 63 | schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); | ||
| 64 | res = -ERESTARTSYS; | ||
| 65 | } while (!fatal_signal_pending(current)); | ||
| 66 | return res; | ||
| 67 | } | ||
| 68 | |||
| 69 | #define rpc_call_sync(clnt, msg, flags) nfs_rpc_wrapper(clnt, msg, flags) | ||
| 70 | |||
| 71 | static int | ||
| 72 | nfs_async_handle_expired_key(struct rpc_task *task) | ||
| 73 | { | ||
| 74 | if (task->tk_status != -EKEYEXPIRED) | ||
| 75 | return 0; | ||
| 76 | task->tk_status = 0; | ||
| 77 | rpc_restart_call(task); | ||
| 78 | rpc_delay(task, NFS_JUKEBOX_RETRY_TIME); | ||
| 79 | return 1; | ||
| 80 | } | ||
| 81 | |||
| 82 | /* | ||
| 50 | * Bare-bones access to getattr: this is for nfs_read_super. | 83 | * Bare-bones access to getattr: this is for nfs_read_super. |
| 51 | */ | 84 | */ |
| 52 | static int | 85 | static int |
| @@ -307,6 +340,8 @@ nfs_proc_unlink_setup(struct rpc_message *msg, struct inode *dir) | |||
| 307 | 340 | ||
| 308 | static int nfs_proc_unlink_done(struct rpc_task *task, struct inode *dir) | 341 | static int nfs_proc_unlink_done(struct rpc_task *task, struct inode *dir) |
| 309 | { | 342 | { |
| 343 | if (nfs_async_handle_expired_key(task)) | ||
| 344 | return 0; | ||
| 310 | nfs_mark_for_revalidate(dir); | 345 | nfs_mark_for_revalidate(dir); |
| 311 | return 1; | 346 | return 1; |
| 312 | } | 347 | } |
| @@ -560,6 +595,9 @@ nfs_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 560 | 595 | ||
| 561 | static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data) | 596 | static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data) |
| 562 | { | 597 | { |
| 598 | if (nfs_async_handle_expired_key(task)) | ||
| 599 | return -EAGAIN; | ||
| 600 | |||
| 563 | nfs_invalidate_atime(data->inode); | 601 | nfs_invalidate_atime(data->inode); |
| 564 | if (task->tk_status >= 0) { | 602 | if (task->tk_status >= 0) { |
| 565 | nfs_refresh_inode(data->inode, data->res.fattr); | 603 | nfs_refresh_inode(data->inode, data->res.fattr); |
| @@ -579,6 +617,9 @@ static void nfs_proc_read_setup(struct nfs_read_data *data, struct rpc_message * | |||
| 579 | 617 | ||
| 580 | static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data) | 618 | static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data) |
| 581 | { | 619 | { |
| 620 | if (nfs_async_handle_expired_key(task)) | ||
| 621 | return -EAGAIN; | ||
| 622 | |||
| 582 | if (task->tk_status >= 0) | 623 | if (task->tk_status >= 0) |
| 583 | nfs_post_op_update_inode_force_wcc(data->inode, data->res.fattr); | 624 | nfs_post_op_update_inode_force_wcc(data->inode, data->res.fattr); |
| 584 | return 0; | 625 | return 0; |
