Commit 6e7434ab authored by Trond Myklebust's avatar Trond Myklebust

NFSv4/pnfs: Allow layoutget to return EAGAIN for softerr mounts

If we're using the 'softerr' mount option, we may want to allow
layoutget to return EAGAIN to allow knfsd server threads to return a
JUKEBOX/DELAY error to the client instead of busy waiting.
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent 5b9d31ae
...@@ -9646,6 +9646,9 @@ nfs4_layoutget_handle_exception(struct rpc_task *task, ...@@ -9646,6 +9646,9 @@ nfs4_layoutget_handle_exception(struct rpc_task *task,
nfs4_sequence_free_slot(&lgp->res.seq_res); nfs4_sequence_free_slot(&lgp->res.seq_res);
exception->state = NULL;
exception->stateid = NULL;
switch (nfs4err) { switch (nfs4err) {
case 0: case 0:
goto out; goto out;
...@@ -9741,7 +9744,8 @@ static const struct rpc_call_ops nfs4_layoutget_call_ops = { ...@@ -9741,7 +9744,8 @@ static const struct rpc_call_ops nfs4_layoutget_call_ops = {
}; };
struct pnfs_layout_segment * struct pnfs_layout_segment *
nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout) nfs4_proc_layoutget(struct nfs4_layoutget *lgp,
struct nfs4_exception *exception)
{ {
struct inode *inode = lgp->args.inode; struct inode *inode = lgp->args.inode;
struct nfs_server *server = NFS_SERVER(inode); struct nfs_server *server = NFS_SERVER(inode);
...@@ -9761,13 +9765,10 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout) ...@@ -9761,13 +9765,10 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout)
RPC_TASK_MOVEABLE, RPC_TASK_MOVEABLE,
}; };
struct pnfs_layout_segment *lseg = NULL; struct pnfs_layout_segment *lseg = NULL;
struct nfs4_exception exception = {
.inode = inode,
.timeout = *timeout,
};
int status = 0; int status = 0;
nfs4_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0, 0); nfs4_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0, 0);
exception->retry = 0;
task = rpc_run_task(&task_setup_data); task = rpc_run_task(&task_setup_data);
if (IS_ERR(task)) if (IS_ERR(task))
...@@ -9778,11 +9779,12 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout) ...@@ -9778,11 +9779,12 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout)
goto out; goto out;
if (task->tk_status < 0) { if (task->tk_status < 0) {
status = nfs4_layoutget_handle_exception(task, lgp, &exception); exception->retry = 1;
*timeout = exception.timeout; status = nfs4_layoutget_handle_exception(task, lgp, exception);
} else if (lgp->res.layoutp->len == 0) { } else if (lgp->res.layoutp->len == 0) {
exception->retry = 1;
status = -EAGAIN; status = -EAGAIN;
*timeout = nfs4_update_delay(&exception.timeout); nfs4_update_delay(&exception->timeout);
} else } else
lseg = pnfs_layout_process(lgp); lseg = pnfs_layout_process(lgp);
out: out:
......
...@@ -1980,7 +1980,9 @@ pnfs_update_layout(struct inode *ino, ...@@ -1980,7 +1980,9 @@ pnfs_update_layout(struct inode *ino,
struct pnfs_layout_segment *lseg = NULL; struct pnfs_layout_segment *lseg = NULL;
struct nfs4_layoutget *lgp; struct nfs4_layoutget *lgp;
nfs4_stateid stateid; nfs4_stateid stateid;
long timeout = 0; struct nfs4_exception exception = {
.inode = ino,
};
unsigned long giveup = jiffies + (clp->cl_lease_time << 1); unsigned long giveup = jiffies + (clp->cl_lease_time << 1);
bool first; bool first;
...@@ -2144,7 +2146,7 @@ pnfs_update_layout(struct inode *ino, ...@@ -2144,7 +2146,7 @@ pnfs_update_layout(struct inode *ino,
lgp->lo = lo; lgp->lo = lo;
pnfs_get_layout_hdr(lo); pnfs_get_layout_hdr(lo);
lseg = nfs4_proc_layoutget(lgp, &timeout); lseg = nfs4_proc_layoutget(lgp, &exception);
trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg, trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
PNFS_UPDATE_LAYOUT_SEND_LAYOUTGET); PNFS_UPDATE_LAYOUT_SEND_LAYOUTGET);
nfs_layoutget_end(lo); nfs_layoutget_end(lo);
...@@ -2171,6 +2173,8 @@ pnfs_update_layout(struct inode *ino, ...@@ -2171,6 +2173,8 @@ pnfs_update_layout(struct inode *ino,
goto out_put_layout_hdr; goto out_put_layout_hdr;
} }
if (lseg) { if (lseg) {
if (!exception.retry)
goto out_put_layout_hdr;
if (first) if (first)
pnfs_clear_first_layoutget(lo); pnfs_clear_first_layoutget(lo);
trace_pnfs_update_layout(ino, pos, count, trace_pnfs_update_layout(ino, pos, count,
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <linux/nfs_page.h> #include <linux/nfs_page.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
struct nfs4_exception;
struct nfs4_opendata; struct nfs4_opendata;
enum { enum {
...@@ -245,7 +246,9 @@ extern size_t max_response_pages(struct nfs_server *server); ...@@ -245,7 +246,9 @@ extern size_t max_response_pages(struct nfs_server *server);
extern int nfs4_proc_getdeviceinfo(struct nfs_server *server, extern int nfs4_proc_getdeviceinfo(struct nfs_server *server,
struct pnfs_device *dev, struct pnfs_device *dev,
const struct cred *cred); const struct cred *cred);
extern struct pnfs_layout_segment* nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout); extern struct pnfs_layout_segment *
nfs4_proc_layoutget(struct nfs4_layoutget *lgp,
struct nfs4_exception *exception);
extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp, bool sync); extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp, bool sync);
/* pnfs.c */ /* pnfs.c */
......
...@@ -739,6 +739,8 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) ...@@ -739,6 +739,8 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
&pgio); &pgio);
pgio.pg_error = 0; pgio.pg_error = 0;
nfs_pageio_complete(&pgio); nfs_pageio_complete(&pgio);
if (err == -EAGAIN && mntflags & NFS_MOUNT_SOFTERR)
break;
} while (err < 0 && !nfs_error_is_fatal(err)); } while (err < 0 && !nfs_error_is_fatal(err));
nfs_io_completion_put(ioc); nfs_io_completion_put(ioc);
......
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