Commit dbd6e343 authored by Trond Myklebust's avatar Trond Myklebust Committed by Linus Torvalds

[PATCH] 2.5.6 correct NFS client handling of EJUKEBOX error...

  The following patch resyncs 2.5.6 with the 2.4.x series w.r.t. the
handling of the EJUKEBOX error. The latter is an NFS-specific error
that is returned by servers that support hierarchical storage: it
notifies the client that the request cannot be completed in a timely
fashion (Imagine for instance a situation where you have a cdrom
jukebox system, and the user has just requested a file on another cd).

Under these circumstances, the RFC specifies that the request should
be retried after suitable timeout during which the server will attempt
to perform whatever action is required to make the file available
again.
parent 36b319a6
......@@ -17,6 +17,37 @@
#define NFSDBG_FACILITY NFSDBG_PROC
/* A wrapper to handle the EJUKEBOX error message */
static int
nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
{
sigset_t oldset;
int res;
rpc_clnt_sigmask(clnt, &oldset);
do {
res = rpc_call_sync(clnt, msg, flags);
if (res != -EJUKEBOX)
break;
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(NFS_JUKEBOX_RETRY_TIME);
res = -ERESTARTSYS;
} while (!signalled());
rpc_clnt_sigunmask(clnt, &oldset);
return res;
}
static inline int
nfs3_rpc_call_wrapper(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
{
struct rpc_message msg = { proc, argp, resp, NULL };
return nfs3_rpc_wrapper(clnt, &msg, flags);
}
#define rpc_call(clnt, proc, argp, resp, flags) \
nfs3_rpc_call_wrapper(clnt, proc, argp, resp, flags)
#define rpc_call_sync(clnt, msg, flags) \
nfs3_rpc_wrapper(clnt, msg, flags)
/*
* Bare-bones access to getattr: this is for nfs_read_super.
*/
......
......@@ -408,6 +408,9 @@ nfs_readpage_result(struct rpc_task *task)
dprintk("NFS: %4d nfs_readpage_result, (status %d)\n",
task->tk_pid, task->tk_status);
if (nfs_async_handle_jukebox(task))
return;
nfs_refresh_inode(inode, &data->fattr);
while (!list_empty(&data->pages)) {
struct nfs_page *req = nfs_list_entry(data->pages.next);
......
......@@ -123,6 +123,8 @@ nfs_async_unlink_done(struct rpc_task *task)
struct dentry *dir = data->dir;
struct inode *dir_i;
if (nfs_async_handle_jukebox(task))
return;
if (!dir)
return;
dir_i = dir->d_inode;
......
......@@ -1012,6 +1012,9 @@ nfs_writeback_done(struct rpc_task *task)
dprintk("NFS: %4d nfs_writeback_done (status %d)\n",
task->tk_pid, task->tk_status);
if (nfs_async_handle_jukebox(task))
return;
/* We can't handle that yet but we check for it nevertheless */
if (resp->count < argp->count && task->tk_status >= 0) {
static unsigned long complain;
......@@ -1205,6 +1208,9 @@ nfs_commit_done(struct rpc_task *task)
dprintk("NFS: %4d nfs_commit_done (status %d)\n",
task->tk_pid, task->tk_status);
if (nfs_async_handle_jukebox(task))
return;
nfs_write_attributes(inode, resp->fattr);
while (!list_empty(&data->pages)) {
req = nfs_list_entry(data->pages.next);
......
......@@ -16,6 +16,7 @@
#include <linux/sunrpc/debug.h>
#include <linux/sunrpc/auth.h>
#include <linux/sunrpc/clnt.h>
#include <linux/nfs.h>
#include <linux/nfs2.h>
......@@ -419,6 +420,29 @@ extern void * nfs_root_data(void);
__retval; \
})
#ifdef CONFIG_NFS_V3
#define NFS_JUKEBOX_RETRY_TIME (5 * HZ)
static inline int
nfs_async_handle_jukebox(struct rpc_task *task)
{
if (task->tk_status != -EJUKEBOX)
return 0;
task->tk_status = 0;
rpc_restart_call(task);
rpc_delay(task, NFS_JUKEBOX_RETRY_TIME);
return 1;
}
#else
static inline int
nfs_async_handle_jukebox(struct rpc_task *task)
{
return 0;
}
#endif /* CONFIG_NFS_V3 */
#endif /* __KERNEL__ */
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment