diff options
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r-- | fs/nfs/pnfs.c | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 8e672a2b2d69..17149a490065 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -1166,6 +1166,33 @@ pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, | |||
1166 | } | 1166 | } |
1167 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_test); | 1167 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_test); |
1168 | 1168 | ||
1169 | static int pnfs_write_done_resend_to_mds(struct inode *inode, struct list_head *head) | ||
1170 | { | ||
1171 | struct nfs_pageio_descriptor pgio; | ||
1172 | LIST_HEAD(failed); | ||
1173 | |||
1174 | /* Resend all requests through the MDS */ | ||
1175 | nfs_pageio_init_write_mds(&pgio, inode, FLUSH_STABLE); | ||
1176 | while (!list_empty(head)) { | ||
1177 | struct nfs_page *req = nfs_list_entry(head->next); | ||
1178 | |||
1179 | nfs_list_remove_request(req); | ||
1180 | if (!nfs_pageio_add_request(&pgio, req)) | ||
1181 | nfs_list_add_request(req, &failed); | ||
1182 | } | ||
1183 | nfs_pageio_complete(&pgio); | ||
1184 | |||
1185 | if (!list_empty(&failed)) { | ||
1186 | /* For some reason our attempt to resend pages. Mark the | ||
1187 | * overall send request as having failed, and let | ||
1188 | * nfs_writeback_release_full deal with the error. | ||
1189 | */ | ||
1190 | list_move(&failed, head); | ||
1191 | return -EIO; | ||
1192 | } | ||
1193 | return 0; | ||
1194 | } | ||
1195 | |||
1169 | /* | 1196 | /* |
1170 | * Called by non rpc-based layout drivers | 1197 | * Called by non rpc-based layout drivers |
1171 | */ | 1198 | */ |
@@ -1175,9 +1202,17 @@ void pnfs_ld_write_done(struct nfs_write_data *data) | |||
1175 | pnfs_set_layoutcommit(data); | 1202 | pnfs_set_layoutcommit(data); |
1176 | data->mds_ops->rpc_call_done(&data->task, data); | 1203 | data->mds_ops->rpc_call_done(&data->task, data); |
1177 | } else { | 1204 | } else { |
1178 | put_lseg(data->lseg); | ||
1179 | data->lseg = NULL; | ||
1180 | dprintk("pnfs write error = %d\n", data->pnfs_error); | 1205 | dprintk("pnfs write error = %d\n", data->pnfs_error); |
1206 | if (NFS_SERVER(data->inode)->pnfs_curr_ld->flags & | ||
1207 | PNFS_LAYOUTRET_ON_ERROR) { | ||
1208 | /* Don't lo_commit on error, Server will needs to | ||
1209 | * preform a file recovery. | ||
1210 | */ | ||
1211 | clear_bit(NFS_INO_LAYOUTCOMMIT, | ||
1212 | &NFS_I(data->inode)->flags); | ||
1213 | pnfs_return_layout(data->inode); | ||
1214 | } | ||
1215 | data->task.tk_status = pnfs_write_done_resend_to_mds(data->inode, &data->pages); | ||
1181 | } | 1216 | } |
1182 | data->mds_ops->rpc_release(data); | 1217 | data->mds_ops->rpc_release(data); |
1183 | } | 1218 | } |
@@ -1267,6 +1302,9 @@ static void pnfs_ld_handle_read_error(struct nfs_read_data *data) | |||
1267 | put_lseg(data->lseg); | 1302 | put_lseg(data->lseg); |
1268 | data->lseg = NULL; | 1303 | data->lseg = NULL; |
1269 | dprintk("pnfs write error = %d\n", data->pnfs_error); | 1304 | dprintk("pnfs write error = %d\n", data->pnfs_error); |
1305 | if (NFS_SERVER(data->inode)->pnfs_curr_ld->flags & | ||
1306 | PNFS_LAYOUTRET_ON_ERROR) | ||
1307 | pnfs_return_layout(data->inode); | ||
1270 | 1308 | ||
1271 | nfs_pageio_init_read_mds(&pgio, data->inode); | 1309 | nfs_pageio_init_read_mds(&pgio, data->inode); |
1272 | 1310 | ||