2013-03-01 01:30:12

by Weston Andros Adamson

[permalink] [raw]
Subject: [PATCH 1/3] PNFS: set the default DS timeout to 60 seconds

The client should have 60 second default timeouts for DS operations, not 6
seconds.

NFS4_DEF_DS_TIMEO is used as "timeout in tenths of a second" in
nfs_init_timeout_values (and is not used anywhere else).
This matches up with the description of the module param dataserver_timeo.

Signed-off-by: Weston Andros Adamson <[email protected]>
---
fs/nfs/nfs4filelayout.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/nfs/nfs4filelayout.h b/fs/nfs/nfs4filelayout.h
index 8c07241..b8da955 100644
--- a/fs/nfs/nfs4filelayout.h
+++ b/fs/nfs/nfs4filelayout.h
@@ -36,7 +36,7 @@
* Default data server connection timeout and retrans vaules.
* Set by module paramters dataserver_timeo and dataserver_retrans.
*/
-#define NFS4_DEF_DS_TIMEO 60
+#define NFS4_DEF_DS_TIMEO 600 /* in tenths of a second */
#define NFS4_DEF_DS_RETRANS 5

/*
--
1.7.12.4 (Apple Git-37)



2013-03-01 01:30:13

by Weston Andros Adamson

[permalink] [raw]
Subject: [PATCH 2/3] SUNRPC: add call to get configured timeout

Returns the configured timeout for the xprt of the rpc client.

Signed-off-by: Weston Andros Adamson <[email protected]>
---
include/linux/sunrpc/clnt.h | 1 +
net/sunrpc/clnt.c | 15 +++++++++++++++
2 files changed, 16 insertions(+)

diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 34206b8..21d52d0 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -160,6 +160,7 @@ void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
int rpc_protocol(struct rpc_clnt *);
struct net * rpc_net_ns(struct rpc_clnt *);
size_t rpc_max_payload(struct rpc_clnt *);
+unsigned long rpc_get_timeout(struct rpc_clnt *clnt);
void rpc_force_rebind(struct rpc_clnt *);
size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t);
const char *rpc_peeraddr2str(struct rpc_clnt *, enum rpc_display_format_t);
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index a9f7906..09dc0c2 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -1196,6 +1196,21 @@ size_t rpc_max_payload(struct rpc_clnt *clnt)
EXPORT_SYMBOL_GPL(rpc_max_payload);

/**
+ * rpc_get_timeout - Get timeout for transport in tenths of seconds
+ * @clnt: RPC client to query
+ */
+unsigned long rpc_get_timeout(struct rpc_clnt *clnt)
+{
+ unsigned long ret;
+
+ rcu_read_lock();
+ ret = rcu_dereference(clnt->cl_xprt)->timeout->to_initval;
+ rcu_read_unlock();
+ return ret;
+}
+EXPORT_SYMBOL_GPL(rpc_get_timeout);
+
+/**
* rpc_force_rebind - force transport to check that remote port is unchanged
* @clnt: client to rebind
*
--
1.7.12.4 (Apple Git-37)


2013-03-01 01:30:15

by Weston Andros Adamson

[permalink] [raw]
Subject: [PATCH 3/3] 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: Weston Andros Adamson <[email protected]>
---
fs/nfs/nfs4proc.c | 9 ++++++++-
fs/nfs/pnfs.c | 7 +++----
include/linux/nfs_xdr.h | 1 +
3 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 37eb385..b2671cb 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -93,6 +93,8 @@ static int nfs4_map_errors(int err)
return err;
switch (err) {
case -NFS4ERR_RESOURCE:
+ case -NFS4ERR_LAYOUTTRYLATER:
+ case -NFS4ERR_RECALLCONFLICT:
return -EREMOTEIO;
case -NFS4ERR_WRONGSEC:
return -EPERM;
@@ -6046,6 +6048,7 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
struct nfs_server *server = NFS_SERVER(inode);
struct pnfs_layout_hdr *lo;
struct nfs4_state *state = NULL;
+ unsigned long timeo, giveup;

dprintk("--> %s\n", __func__);

@@ -6057,7 +6060,10 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
goto out;
case -NFS4ERR_LAYOUTTRYLATER:
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;
case -NFS4ERR_EXPIRED:
case -NFS4ERR_BAD_STATEID:
@@ -6178,6 +6184,7 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags)
return ERR_PTR(-ENOMEM);
}
lgp->args.layout.pglen = max_pages * PAGE_SIZE;
+ lgp->args.timestamp = jiffies;

lgp->res.layoutp = &lgp->args.layout;
lgp->res.seq_res.sr_slot = NULL;
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 97767c8..7e9e897 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1181,7 +1181,7 @@ pnfs_update_layout(struct inode *ino,
struct nfs_client *clp = server->nfs_client;
struct pnfs_layout_hdr *lo;
struct pnfs_layout_segment *lseg = NULL;
- bool first = false;
+ bool first;

if (!pnfs_enabled_sb(NFS_SERVER(ino)))
goto out;
@@ -1215,10 +1215,9 @@ pnfs_update_layout(struct inode *ino,
goto out_unlock;
atomic_inc(&lo->plh_outstanding);

- if (list_empty(&lo->plh_segs))
- first = true;
-
+ first = list_empty(&lo->plh_layouts);
spin_unlock(&ino->i_lock);
+
if (first) {
/* The lo must be on the clp list if there is any
* chance of a CB_LAYOUTRECALL(FILE) coming in.
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 29adb12..2250cab 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -233,6 +233,7 @@ struct nfs4_layoutget_args {
struct inode *inode;
struct nfs_open_context *ctx;
nfs4_stateid stateid;
+ unsigned long timestamp;
struct nfs4_layoutdriver_data layout;
};

--
1.7.12.4 (Apple Git-37)


2013-03-01 21:07:35

by Adamson, Dros

[permalink] [raw]
Subject: Re: [PATCH 2/3] SUNRPC: add call to get configured timeout

Hey Trond,

One minor fixup here: the comment is wrong. rpc_get_timeout returns the timeout in HZ.

Thanks!

-dros

On Feb 28, 2013, at 8:30 PM, Weston Andros Adamson <[email protected]> wrote:

> Returns the configured timeout for the xprt of the rpc client.
>
> Signed-off-by: Weston Andros Adamson <[email protected]>
> ---
> include/linux/sunrpc/clnt.h | 1 +
> net/sunrpc/clnt.c | 15 +++++++++++++++
> 2 files changed, 16 insertions(+)
>
> diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
> index 34206b8..21d52d0 100644
> --- a/include/linux/sunrpc/clnt.h
> +++ b/include/linux/sunrpc/clnt.h
> @@ -160,6 +160,7 @@ void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
> int rpc_protocol(struct rpc_clnt *);
> struct net * rpc_net_ns(struct rpc_clnt *);
> size_t rpc_max_payload(struct rpc_clnt *);
> +unsigned long rpc_get_timeout(struct rpc_clnt *clnt);
> void rpc_force_rebind(struct rpc_clnt *);
> size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t);
> const char *rpc_peeraddr2str(struct rpc_clnt *, enum rpc_display_format_t);
> diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
> index a9f7906..09dc0c2 100644
> --- a/net/sunrpc/clnt.c
> +++ b/net/sunrpc/clnt.c
> @@ -1196,6 +1196,21 @@ size_t rpc_max_payload(struct rpc_clnt *clnt)
> EXPORT_SYMBOL_GPL(rpc_max_payload);
>
> /**
> + * rpc_get_timeout - Get timeout for transport in tenths of seconds
> + * @clnt: RPC client to query
> + */
> +unsigned long rpc_get_timeout(struct rpc_clnt *clnt)
> +{
> + unsigned long ret;
> +
> + rcu_read_lock();
> + ret = rcu_dereference(clnt->cl_xprt)->timeout->to_initval;
> + rcu_read_unlock();
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(rpc_get_timeout);
> +
> +/**
> * rpc_force_rebind - force transport to check that remote port is unchanged
> * @clnt: client to rebind
> *
> --
> 1.7.12.4 (Apple Git-37)
>