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; |