Commit 30005121 authored by Weston Andros Adamson's avatar Weston Andros Adamson Committed by Trond Myklebust

NFSv4.1: LAYOUTGET EDELAY loops timeout to the MDS

The client will currently try LAYOUTGETs forever if a server is returning
NFS4ERR_LAYOUTTRYLATER or NFS4ERR_RECALLCONFLICT - even if the client no
longer needs the layout (ie process killed, unmounted).

This patch uses the DS timeout value (module parameter 'dataserver_timeo'
via rpc layer) to set an upper limit of how long the client tries LATOUTGETs
in this situation.  Once the timeout is reached, IO is redirected to the MDS.

This also changes how the client checks if a layout is on the clp list
to avoid a double list_add.
Signed-off-by: default avatarWeston Andros Adamson <dros@netapp.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent edddbb1e
...@@ -93,6 +93,8 @@ static int nfs4_map_errors(int err) ...@@ -93,6 +93,8 @@ static int nfs4_map_errors(int err)
return err; return err;
switch (err) { switch (err) {
case -NFS4ERR_RESOURCE: case -NFS4ERR_RESOURCE:
case -NFS4ERR_LAYOUTTRYLATER:
case -NFS4ERR_RECALLCONFLICT:
return -EREMOTEIO; return -EREMOTEIO;
case -NFS4ERR_WRONGSEC: case -NFS4ERR_WRONGSEC:
return -EPERM; return -EPERM;
...@@ -6046,6 +6048,7 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) ...@@ -6046,6 +6048,7 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
struct nfs_server *server = NFS_SERVER(inode); struct nfs_server *server = NFS_SERVER(inode);
struct pnfs_layout_hdr *lo; struct pnfs_layout_hdr *lo;
struct nfs4_state *state = NULL; struct nfs4_state *state = NULL;
unsigned long timeo, giveup;
dprintk("--> %s\n", __func__); dprintk("--> %s\n", __func__);
...@@ -6057,7 +6060,10 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) ...@@ -6057,7 +6060,10 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
goto out; goto out;
case -NFS4ERR_LAYOUTTRYLATER: case -NFS4ERR_LAYOUTTRYLATER:
case -NFS4ERR_RECALLCONFLICT: case -NFS4ERR_RECALLCONFLICT:
task->tk_status = -NFS4ERR_DELAY; timeo = rpc_get_timeout(task->tk_client);
giveup = lgp->args.timestamp + timeo;
if (time_after(giveup, jiffies))
task->tk_status = -NFS4ERR_DELAY;
break; break;
case -NFS4ERR_EXPIRED: case -NFS4ERR_EXPIRED:
case -NFS4ERR_BAD_STATEID: case -NFS4ERR_BAD_STATEID:
...@@ -6178,6 +6184,7 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) ...@@ -6178,6 +6184,7 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
lgp->args.layout.pglen = max_pages * PAGE_SIZE; lgp->args.layout.pglen = max_pages * PAGE_SIZE;
lgp->args.timestamp = jiffies;
lgp->res.layoutp = &lgp->args.layout; lgp->res.layoutp = &lgp->args.layout;
lgp->res.seq_res.sr_slot = NULL; lgp->res.seq_res.sr_slot = NULL;
......
...@@ -1181,7 +1181,7 @@ pnfs_update_layout(struct inode *ino, ...@@ -1181,7 +1181,7 @@ pnfs_update_layout(struct inode *ino,
struct nfs_client *clp = server->nfs_client; struct nfs_client *clp = server->nfs_client;
struct pnfs_layout_hdr *lo; struct pnfs_layout_hdr *lo;
struct pnfs_layout_segment *lseg = NULL; struct pnfs_layout_segment *lseg = NULL;
bool first = false; bool first;
if (!pnfs_enabled_sb(NFS_SERVER(ino))) if (!pnfs_enabled_sb(NFS_SERVER(ino)))
goto out; goto out;
...@@ -1215,10 +1215,9 @@ pnfs_update_layout(struct inode *ino, ...@@ -1215,10 +1215,9 @@ pnfs_update_layout(struct inode *ino,
goto out_unlock; goto out_unlock;
atomic_inc(&lo->plh_outstanding); atomic_inc(&lo->plh_outstanding);
if (list_empty(&lo->plh_segs)) first = list_empty(&lo->plh_layouts) ? true : false;
first = true;
spin_unlock(&ino->i_lock); spin_unlock(&ino->i_lock);
if (first) { if (first) {
/* The lo must be on the clp list if there is any /* The lo must be on the clp list if there is any
* chance of a CB_LAYOUTRECALL(FILE) coming in. * chance of a CB_LAYOUTRECALL(FILE) coming in.
......
...@@ -233,6 +233,7 @@ struct nfs4_layoutget_args { ...@@ -233,6 +233,7 @@ struct nfs4_layoutget_args {
struct inode *inode; struct inode *inode;
struct nfs_open_context *ctx; struct nfs_open_context *ctx;
nfs4_stateid stateid; nfs4_stateid stateid;
unsigned long timestamp;
struct nfs4_layoutdriver_data layout; struct nfs4_layoutdriver_data layout;
}; };
......
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