Skip to content

Commit 6e7434a

Browse files
author
Trond Myklebust
committed
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: Trond Myklebust <[email protected]>
1 parent 5b9d31a commit 6e7434a

File tree

4 files changed

+22
-11
lines changed

4 files changed

+22
-11
lines changed

fs/nfs/nfs4proc.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9646,6 +9646,9 @@ nfs4_layoutget_handle_exception(struct rpc_task *task,
96469646

96479647
nfs4_sequence_free_slot(&lgp->res.seq_res);
96489648

9649+
exception->state = NULL;
9650+
exception->stateid = NULL;
9651+
96499652
switch (nfs4err) {
96509653
case 0:
96519654
goto out;
@@ -9741,7 +9744,8 @@ static const struct rpc_call_ops nfs4_layoutget_call_ops = {
97419744
};
97429745

97439746
struct pnfs_layout_segment *
9744-
nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout)
9747+
nfs4_proc_layoutget(struct nfs4_layoutget *lgp,
9748+
struct nfs4_exception *exception)
97459749
{
97469750
struct inode *inode = lgp->args.inode;
97479751
struct nfs_server *server = NFS_SERVER(inode);
@@ -9761,13 +9765,10 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout)
97619765
RPC_TASK_MOVEABLE,
97629766
};
97639767
struct pnfs_layout_segment *lseg = NULL;
9764-
struct nfs4_exception exception = {
9765-
.inode = inode,
9766-
.timeout = *timeout,
9767-
};
97689768
int status = 0;
97699769

97709770
nfs4_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0, 0);
9771+
exception->retry = 0;
97719772

97729773
task = rpc_run_task(&task_setup_data);
97739774
if (IS_ERR(task))
@@ -9778,11 +9779,12 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout)
97789779
goto out;
97799780

97809781
if (task->tk_status < 0) {
9781-
status = nfs4_layoutget_handle_exception(task, lgp, &exception);
9782-
*timeout = exception.timeout;
9782+
exception->retry = 1;
9783+
status = nfs4_layoutget_handle_exception(task, lgp, exception);
97839784
} else if (lgp->res.layoutp->len == 0) {
9785+
exception->retry = 1;
97849786
status = -EAGAIN;
9785-
*timeout = nfs4_update_delay(&exception.timeout);
9787+
nfs4_update_delay(&exception->timeout);
97869788
} else
97879789
lseg = pnfs_layout_process(lgp);
97889790
out:

fs/nfs/pnfs.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1980,7 +1980,9 @@ pnfs_update_layout(struct inode *ino,
19801980
struct pnfs_layout_segment *lseg = NULL;
19811981
struct nfs4_layoutget *lgp;
19821982
nfs4_stateid stateid;
1983-
long timeout = 0;
1983+
struct nfs4_exception exception = {
1984+
.inode = ino,
1985+
};
19841986
unsigned long giveup = jiffies + (clp->cl_lease_time << 1);
19851987
bool first;
19861988

@@ -2144,7 +2146,7 @@ pnfs_update_layout(struct inode *ino,
21442146
lgp->lo = lo;
21452147
pnfs_get_layout_hdr(lo);
21462148

2147-
lseg = nfs4_proc_layoutget(lgp, &timeout);
2149+
lseg = nfs4_proc_layoutget(lgp, &exception);
21482150
trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
21492151
PNFS_UPDATE_LAYOUT_SEND_LAYOUTGET);
21502152
nfs_layoutget_end(lo);
@@ -2171,6 +2173,8 @@ pnfs_update_layout(struct inode *ino,
21712173
goto out_put_layout_hdr;
21722174
}
21732175
if (lseg) {
2176+
if (!exception.retry)
2177+
goto out_put_layout_hdr;
21742178
if (first)
21752179
pnfs_clear_first_layoutget(lo);
21762180
trace_pnfs_update_layout(ino, pos, count,

fs/nfs/pnfs.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include <linux/nfs_page.h>
3636
#include <linux/workqueue.h>
3737

38+
struct nfs4_exception;
3839
struct nfs4_opendata;
3940

4041
enum {
@@ -245,7 +246,9 @@ extern size_t max_response_pages(struct nfs_server *server);
245246
extern int nfs4_proc_getdeviceinfo(struct nfs_server *server,
246247
struct pnfs_device *dev,
247248
const struct cred *cred);
248-
extern struct pnfs_layout_segment* nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout);
249+
extern struct pnfs_layout_segment *
250+
nfs4_proc_layoutget(struct nfs4_layoutget *lgp,
251+
struct nfs4_exception *exception);
249252
extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp, bool sync);
250253

251254
/* pnfs.c */

fs/nfs/write.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,8 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
739739
&pgio);
740740
pgio.pg_error = 0;
741741
nfs_pageio_complete(&pgio);
742+
if (err == -EAGAIN && mntflags & NFS_MOUNT_SOFTERR)
743+
break;
742744
} while (err < 0 && !nfs_error_is_fatal(err));
743745
nfs_io_completion_put(ioc);
744746

0 commit comments

Comments
 (0)