aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4filelayout.c
diff options
context:
space:
mode:
authorAndy Adamson <andros@netapp.com>2011-02-28 20:34:20 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-03-11 15:38:43 -0500
commitcbdabc7f8bf14ca1d40ab1cb86f64b3bc09716e8 (patch)
tree16939b96996e8380d91d7e2743e811cf5c49f629 /fs/nfs/nfs4filelayout.c
parentdc70d7b3189597f313df7bd2da849cfc39063b15 (diff)
NFSv4.1: filelayout async error handler
Use our own async error handler. Mark the layout as failed and retry i/o through the MDS on specified errors. Update the mds_offset in nfs_readpage_retry so that a failed short-read retry to a DS gets correctly resent through the MDS. Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4filelayout.c')
-rw-r--r--fs/nfs/nfs4filelayout.c81
1 files changed, 81 insertions, 0 deletions
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index 3608411653dc..6a424c19abea 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -40,6 +40,8 @@ MODULE_LICENSE("GPL");
40MODULE_AUTHOR("Dean Hildebrand <dhildebz@umich.edu>"); 40MODULE_AUTHOR("Dean Hildebrand <dhildebz@umich.edu>");
41MODULE_DESCRIPTION("The NFSv4 file layout driver"); 41MODULE_DESCRIPTION("The NFSv4 file layout driver");
42 42
43#define FILELAYOUT_POLL_RETRY_MAX (15*HZ)
44
43static int 45static int
44filelayout_set_layoutdriver(struct nfs_server *nfss) 46filelayout_set_layoutdriver(struct nfs_server *nfss)
45{ 47{
@@ -100,6 +102,83 @@ filelayout_get_dserver_offset(struct pnfs_layout_segment *lseg, loff_t offset)
100 BUG(); 102 BUG();
101} 103}
102 104
105/* For data server errors we don't recover from */
106static void
107filelayout_set_lo_fail(struct pnfs_layout_segment *lseg)
108{
109 if (lseg->pls_range.iomode == IOMODE_RW) {
110 dprintk("%s Setting layout IOMODE_RW fail bit\n", __func__);
111 set_bit(lo_fail_bit(IOMODE_RW), &lseg->pls_layout->plh_flags);
112 } else {
113 dprintk("%s Setting layout IOMODE_READ fail bit\n", __func__);
114 set_bit(lo_fail_bit(IOMODE_READ), &lseg->pls_layout->plh_flags);
115 }
116}
117
118static int filelayout_async_handle_error(struct rpc_task *task,
119 struct nfs4_state *state,
120 struct nfs_client *clp,
121 int *reset)
122{
123 if (task->tk_status >= 0)
124 return 0;
125
126 *reset = 0;
127
128 switch (task->tk_status) {
129 case -NFS4ERR_BADSESSION:
130 case -NFS4ERR_BADSLOT:
131 case -NFS4ERR_BAD_HIGH_SLOT:
132 case -NFS4ERR_DEADSESSION:
133 case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
134 case -NFS4ERR_SEQ_FALSE_RETRY:
135 case -NFS4ERR_SEQ_MISORDERED:
136 dprintk("%s ERROR %d, Reset session. Exchangeid "
137 "flags 0x%x\n", __func__, task->tk_status,
138 clp->cl_exchange_flags);
139 nfs4_schedule_session_recovery(clp->cl_session);
140 break;
141 case -NFS4ERR_DELAY:
142 case -NFS4ERR_GRACE:
143 case -EKEYEXPIRED:
144 rpc_delay(task, FILELAYOUT_POLL_RETRY_MAX);
145 break;
146 default:
147 dprintk("%s DS error. Retry through MDS %d\n", __func__,
148 task->tk_status);
149 *reset = 1;
150 break;
151 }
152 task->tk_status = 0;
153 return -EAGAIN;
154}
155
156/* NFS_PROTO call done callback routines */
157
158static int filelayout_read_done_cb(struct rpc_task *task,
159 struct nfs_read_data *data)
160{
161 struct nfs_client *clp = data->ds_clp;
162 int reset = 0;
163
164 dprintk("%s DS read\n", __func__);
165
166 if (filelayout_async_handle_error(task, data->args.context->state,
167 data->ds_clp, &reset) == -EAGAIN) {
168 dprintk("%s calling restart ds_clp %p ds_clp->cl_session %p\n",
169 __func__, data->ds_clp, data->ds_clp->cl_session);
170 if (reset) {
171 filelayout_set_lo_fail(data->lseg);
172 nfs4_reset_read(task, data);
173 clp = NFS_SERVER(data->inode)->nfs_client;
174 }
175 nfs_restart_rpc(task, clp);
176 return -EAGAIN;
177 }
178
179 return 0;
180}
181
103/* 182/*
104 * Call ops for the async read/write cases 183 * Call ops for the async read/write cases
105 * In the case of dense layouts, the offset needs to be reset to its 184 * In the case of dense layouts, the offset needs to be reset to its
@@ -109,6 +188,8 @@ static void filelayout_read_prepare(struct rpc_task *task, void *data)
109{ 188{
110 struct nfs_read_data *rdata = (struct nfs_read_data *)data; 189 struct nfs_read_data *rdata = (struct nfs_read_data *)data;
111 190
191 rdata->read_done_cb = filelayout_read_done_cb;
192
112 if (nfs41_setup_sequence(rdata->ds_clp->cl_session, 193 if (nfs41_setup_sequence(rdata->ds_clp->cl_session,
113 &rdata->args.seq_args, &rdata->res.seq_res, 194 &rdata->args.seq_args, &rdata->res.seq_res,
114 0, task)) 195 0, task))