aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/nfs4filelayout.c130
-rw-r--r--fs/nfs/nfs4filelayout.h3
-rw-r--r--fs/nfs/pnfs.c6
-rw-r--r--fs/nfs/pnfs.h4
4 files changed, 108 insertions, 35 deletions
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index 0db8c0783039..f503cbe5a21a 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -82,29 +82,77 @@ filelayout_get_dserver_offset(struct pnfs_layout_segment *lseg, loff_t offset)
82 BUG(); 82 BUG();
83} 83}
84 84
85static void filelayout_reset_write(struct nfs_write_data *data)
86{
87 struct nfs_pgio_header *hdr = data->header;
88 struct inode *inode = hdr->inode;
89 struct rpc_task *task = &data->task;
90
91 if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) {
92 dprintk("%s Reset task %5u for i/o through MDS "
93 "(req %s/%lld, %u bytes @ offset %llu)\n", __func__,
94 data->task.tk_pid,
95 inode->i_sb->s_id,
96 (long long)NFS_FILEID(inode),
97 data->args.count,
98 (unsigned long long)data->args.offset);
99
100 task->tk_status = pnfs_write_done_resend_to_mds(hdr->inode,
101 &hdr->pages,
102 hdr->completion_ops);
103 }
104}
105
106static void filelayout_reset_read(struct nfs_read_data *data)
107{
108 struct nfs_pgio_header *hdr = data->header;
109 struct inode *inode = hdr->inode;
110 struct rpc_task *task = &data->task;
111
112 if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) {
113 dprintk("%s Reset task %5u for i/o through MDS "
114 "(req %s/%lld, %u bytes @ offset %llu)\n", __func__,
115 data->task.tk_pid,
116 inode->i_sb->s_id,
117 (long long)NFS_FILEID(inode),
118 data->args.count,
119 (unsigned long long)data->args.offset);
120
121 task->tk_status = pnfs_read_done_resend_to_mds(hdr->inode,
122 &hdr->pages,
123 hdr->completion_ops);
124 }
125}
126
85static int filelayout_async_handle_error(struct rpc_task *task, 127static int filelayout_async_handle_error(struct rpc_task *task,
86 struct nfs4_state *state, 128 struct nfs4_state *state,
87 struct nfs_client *clp, 129 struct nfs_client *clp,
88 int *reset) 130 struct pnfs_layout_segment *lseg)
89{ 131{
90 struct nfs_server *mds_server = NFS_SERVER(state->inode); 132 struct inode *inode = lseg->pls_layout->plh_inode;
133 struct nfs_server *mds_server = NFS_SERVER(inode);
134 struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg);
91 struct nfs_client *mds_client = mds_server->nfs_client; 135 struct nfs_client *mds_client = mds_server->nfs_client;
92 136
93 if (task->tk_status >= 0) 137 if (task->tk_status >= 0)
94 return 0; 138 return 0;
95 *reset = 0;
96 139
97 switch (task->tk_status) { 140 switch (task->tk_status) {
98 /* MDS state errors */ 141 /* MDS state errors */
99 case -NFS4ERR_DELEG_REVOKED: 142 case -NFS4ERR_DELEG_REVOKED:
100 case -NFS4ERR_ADMIN_REVOKED: 143 case -NFS4ERR_ADMIN_REVOKED:
101 case -NFS4ERR_BAD_STATEID: 144 case -NFS4ERR_BAD_STATEID:
145 if (state == NULL)
146 break;
102 nfs_remove_bad_delegation(state->inode); 147 nfs_remove_bad_delegation(state->inode);
103 case -NFS4ERR_OPENMODE: 148 case -NFS4ERR_OPENMODE:
149 if (state == NULL)
150 break;
104 nfs4_schedule_stateid_recovery(mds_server, state); 151 nfs4_schedule_stateid_recovery(mds_server, state);
105 goto wait_on_recovery; 152 goto wait_on_recovery;
106 case -NFS4ERR_EXPIRED: 153 case -NFS4ERR_EXPIRED:
107 nfs4_schedule_stateid_recovery(mds_server, state); 154 if (state != NULL)
155 nfs4_schedule_stateid_recovery(mds_server, state);
108 nfs4_schedule_lease_recovery(mds_client); 156 nfs4_schedule_lease_recovery(mds_client);
109 goto wait_on_recovery; 157 goto wait_on_recovery;
110 /* DS session errors */ 158 /* DS session errors */
@@ -127,11 +175,22 @@ static int filelayout_async_handle_error(struct rpc_task *task,
127 break; 175 break;
128 case -NFS4ERR_RETRY_UNCACHED_REP: 176 case -NFS4ERR_RETRY_UNCACHED_REP:
129 break; 177 break;
178 /* RPC connection errors */
179 case -ECONNREFUSED:
180 case -EHOSTDOWN:
181 case -EHOSTUNREACH:
182 case -ENETUNREACH:
183 case -EIO:
184 case -ETIMEDOUT:
185 case -EPIPE:
186 dprintk("%s DS connection error %d\n", __func__,
187 task->tk_status);
188 filelayout_mark_devid_invalid(devid);
189 /* fall through */
130 default: 190 default:
131 dprintk("%s DS error. Retry through MDS %d\n", __func__, 191 dprintk("%s Retry through MDS. Error %d\n", __func__,
132 task->tk_status); 192 task->tk_status);
133 *reset = 1; 193 return -NFS4ERR_RESET_TO_MDS;
134 break;
135 } 194 }
136out: 195out:
137 task->tk_status = 0; 196 task->tk_status = 0;
@@ -148,16 +207,17 @@ wait_on_recovery:
148static int filelayout_read_done_cb(struct rpc_task *task, 207static int filelayout_read_done_cb(struct rpc_task *task,
149 struct nfs_read_data *data) 208 struct nfs_read_data *data)
150{ 209{
151 int reset = 0; 210 struct nfs_pgio_header *hdr = data->header;
211 int err;
152 212
153 dprintk("%s DS read\n", __func__); 213 err = filelayout_async_handle_error(task, data->args.context->state,
214 data->ds_clp, hdr->lseg);
154 215
155 if (filelayout_async_handle_error(task, data->args.context->state, 216 switch (err) {
156 data->ds_clp, &reset) == -EAGAIN) { 217 case -NFS4ERR_RESET_TO_MDS:
157 dprintk("%s calling restart ds_clp %p ds_clp->cl_session %p\n", 218 filelayout_reset_read(data);
158 __func__, data->ds_clp, data->ds_clp->cl_session); 219 return task->tk_status;
159 if (reset) 220 case -EAGAIN:
160 nfs4_reset_read(task, data);
161 rpc_restart_call_prepare(task); 221 rpc_restart_call_prepare(task);
162 return -EAGAIN; 222 return -EAGAIN;
163 } 223 }
@@ -230,14 +290,17 @@ static void filelayout_read_release(void *data)
230static int filelayout_write_done_cb(struct rpc_task *task, 290static int filelayout_write_done_cb(struct rpc_task *task,
231 struct nfs_write_data *data) 291 struct nfs_write_data *data)
232{ 292{
233 int reset = 0; 293 struct nfs_pgio_header *hdr = data->header;
234 294 int err;
235 if (filelayout_async_handle_error(task, data->args.context->state, 295
236 data->ds_clp, &reset) == -EAGAIN) { 296 err = filelayout_async_handle_error(task, data->args.context->state,
237 dprintk("%s calling restart ds_clp %p ds_clp->cl_session %p\n", 297 data->ds_clp, hdr->lseg);
238 __func__, data->ds_clp, data->ds_clp->cl_session); 298
239 if (reset) 299 switch (err) {
240 nfs4_reset_write(task, data); 300 case -NFS4ERR_RESET_TO_MDS:
301 filelayout_reset_write(data);
302 return task->tk_status;
303 case -EAGAIN:
241 rpc_restart_call_prepare(task); 304 rpc_restart_call_prepare(task);
242 return -EAGAIN; 305 return -EAGAIN;
243 } 306 }
@@ -260,16 +323,17 @@ static void prepare_to_resend_writes(struct nfs_commit_data *data)
260static int filelayout_commit_done_cb(struct rpc_task *task, 323static int filelayout_commit_done_cb(struct rpc_task *task,
261 struct nfs_commit_data *data) 324 struct nfs_commit_data *data)
262{ 325{
263 int reset = 0; 326 int err;
264 327
265 if (filelayout_async_handle_error(task, data->context->state, 328 err = filelayout_async_handle_error(task, NULL, data->ds_clp,
266 data->ds_clp, &reset) == -EAGAIN) { 329 data->lseg);
267 dprintk("%s calling restart ds_clp %p ds_clp->cl_session %p\n", 330
268 __func__, data->ds_clp, data->ds_clp->cl_session); 331 switch (err) {
269 if (reset) 332 case -NFS4ERR_RESET_TO_MDS:
270 prepare_to_resend_writes(data); 333 prepare_to_resend_writes(data);
271 else 334 return -EAGAIN;
272 rpc_restart_call_prepare(task); 335 case -EAGAIN:
336 rpc_restart_call_prepare(task);
273 return -EAGAIN; 337 return -EAGAIN;
274 } 338 }
275 339
diff --git a/fs/nfs/nfs4filelayout.h b/fs/nfs/nfs4filelayout.h
index 6fb1901ffd6a..3259be60da92 100644
--- a/fs/nfs/nfs4filelayout.h
+++ b/fs/nfs/nfs4filelayout.h
@@ -48,6 +48,9 @@
48#define NFS4_PNFS_MAX_STRIPE_CNT 4096 48#define NFS4_PNFS_MAX_STRIPE_CNT 4096
49#define NFS4_PNFS_MAX_MULTI_CNT 256 /* 256 fit into a u8 stripe_index */ 49#define NFS4_PNFS_MAX_MULTI_CNT 256 /* 256 fit into a u8 stripe_index */
50 50
51/* error codes for internal use */
52#define NFS4ERR_RESET_TO_MDS 12001
53
51enum stripetype4 { 54enum stripetype4 {
52 STRIPE_SPARSE = 1, 55 STRIPE_SPARSE = 1,
53 STRIPE_DENSE = 2 56 STRIPE_DENSE = 2
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 6fdeca2fbc2a..16cc1948cb46 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1175,7 +1175,7 @@ pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
1175} 1175}
1176EXPORT_SYMBOL_GPL(pnfs_generic_pg_test); 1176EXPORT_SYMBOL_GPL(pnfs_generic_pg_test);
1177 1177
1178static int pnfs_write_done_resend_to_mds(struct inode *inode, 1178int pnfs_write_done_resend_to_mds(struct inode *inode,
1179 struct list_head *head, 1179 struct list_head *head,
1180 const struct nfs_pgio_completion_ops *compl_ops) 1180 const struct nfs_pgio_completion_ops *compl_ops)
1181{ 1181{
@@ -1203,6 +1203,7 @@ static int pnfs_write_done_resend_to_mds(struct inode *inode,
1203 } 1203 }
1204 return 0; 1204 return 0;
1205} 1205}
1206EXPORT_SYMBOL_GPL(pnfs_write_done_resend_to_mds);
1206 1207
1207static void pnfs_ld_handle_write_error(struct nfs_write_data *data) 1208static void pnfs_ld_handle_write_error(struct nfs_write_data *data)
1208{ 1209{
@@ -1329,7 +1330,7 @@ pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
1329} 1330}
1330EXPORT_SYMBOL_GPL(pnfs_generic_pg_writepages); 1331EXPORT_SYMBOL_GPL(pnfs_generic_pg_writepages);
1331 1332
1332static int pnfs_read_done_resend_to_mds(struct inode *inode, 1333int pnfs_read_done_resend_to_mds(struct inode *inode,
1333 struct list_head *head, 1334 struct list_head *head,
1334 const struct nfs_pgio_completion_ops *compl_ops) 1335 const struct nfs_pgio_completion_ops *compl_ops)
1335{ 1336{
@@ -1353,6 +1354,7 @@ static int pnfs_read_done_resend_to_mds(struct inode *inode,
1353 } 1354 }
1354 return 0; 1355 return 0;
1355} 1356}
1357EXPORT_SYMBOL_GPL(pnfs_read_done_resend_to_mds);
1356 1358
1357static void pnfs_ld_handle_read_error(struct nfs_read_data *data) 1359static void pnfs_ld_handle_read_error(struct nfs_read_data *data)
1358{ 1360{
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index f20054b592b6..9cf9ede8cc52 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -222,6 +222,10 @@ struct pnfs_layout_segment *pnfs_update_layout(struct inode *ino,
222 gfp_t gfp_flags); 222 gfp_t gfp_flags);
223 223
224void nfs4_deviceid_mark_client_invalid(struct nfs_client *clp); 224void nfs4_deviceid_mark_client_invalid(struct nfs_client *clp);
225int pnfs_read_done_resend_to_mds(struct inode *inode, struct list_head *head,
226 const struct nfs_pgio_completion_ops *compl_ops);
227int pnfs_write_done_resend_to_mds(struct inode *inode, struct list_head *head,
228 const struct nfs_pgio_completion_ops *compl_ops);
225 229
226/* nfs4_deviceid_flags */ 230/* nfs4_deviceid_flags */
227enum { 231enum {