]> rtime.felk.cvut.cz Git - linux-imx.git/commitdiff
NFSv4.1: LAYOUTGET EDELAY loops timeout to the MDS
authorWeston Andros Adamson <dros@netapp.com>
Fri, 1 Mar 2013 01:30:10 +0000 (20:30 -0500)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Fri, 1 Mar 2013 01:41:35 +0000 (17:41 -0800)
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 <dros@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/nfs4proc.c
fs/nfs/pnfs.c
include/linux/nfs_xdr.h

index 37eb38566fbcb823168758c8cb250b0db2320e26..b2671cb0f901b8e904ee4b91961d2029e12fb2dc 100644 (file)
@@ -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;
index 97767c8683f9ce5ef0f7548f9583b63a6d3dc7bb..48ac5aad62589cd7140f55a52d5ee63f31e743b5 100644 (file)
@@ -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) ? true : false;
        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.
index 29adb12c7ecffad9b58d6144d742489cb974de80..2250cab6fc4bacb586a56e4c7d91f601948a1220 100644 (file)
@@ -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;
 };