]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] 2.5.6 correct NFS client handling of EJUKEBOX error...
authorTrond Myklebust <trond.myklebust@fys.uio.no>
Tue, 12 Mar 2002 06:04:53 +0000 (22:04 -0800)
committerLinus Torvalds <torvalds@penguin.transmeta.com>
Tue, 12 Mar 2002 06:04:53 +0000 (22:04 -0800)
  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.

fs/nfs/nfs3proc.c
fs/nfs/read.c
fs/nfs/unlink.c
fs/nfs/write.c
include/linux/nfs_fs.h

index d8e9b491cc9e672357b2c887519315788887bd65..179712b8b95cf4af7af3e4051ceef7ecde8da37e 100644 (file)
 
 #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.
  */
index 87fe7389ffec3a5fd18aa4b1e68350b72aa50af0..f85bec8c32b52d35af38d9d599b095a03bea7916 100644 (file)
@@ -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);
index 5c4489a3a2796289aaeda61875097c95cad886b4..9697bedad53c1b308c4f36b7393ef8ba9827f6ae 100644 (file)
@@ -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;
index c9ef1441c8465515c3c16fc3a69aef43a01ae080..8a61ceaaf3f115cafff6b810c6cbfdfde3adcb07 100644 (file)
@@ -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);
index e95a085a2fddecc0612e4d24085ed0b2f332e8ba..ef81457b484bba4290407029b1b04fde7e9f83f7 100644 (file)
@@ -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__ */
 
 /*