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