diff options
author | Fred Isaman <iisaman@netapp.com> | 2012-04-20 14:47:37 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-04-27 14:10:36 -0400 |
commit | 1acbbb4e16209e85c35ff6cacad61d802c07289b (patch) | |
tree | 37abc770218a11120fe4f10d5842835d270ce209 /fs/nfs/pnfs.c | |
parent | a20c6bec0b8ae775e2e8f350819cef98eea9a832 (diff) |
NFS4.1: make pnfs_ld_[read|write]_done consistent
The two functions had diverged quite a bit, with the write function
being a bit more robust than the read.
However, these still break badly in the desc->pg_bsize < PAGE_CACHE_SIZE case,
as then there is nothing hanging on the data->pages list, and the resend
ends up doing nothing. This will be fixed in a patch later in the series.
Signed-off-by: Fred Isaman <iisaman@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r-- | fs/nfs/pnfs.c | 64 |
1 files changed, 38 insertions, 26 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 38512bcd2e98..9c4d14a17d49 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -1189,6 +1189,17 @@ static int pnfs_write_done_resend_to_mds(struct inode *inode, struct list_head * | |||
1189 | return 0; | 1189 | return 0; |
1190 | } | 1190 | } |
1191 | 1191 | ||
1192 | static void pnfs_ld_handle_write_error(struct nfs_write_data *data) | ||
1193 | { | ||
1194 | dprintk("pnfs write error = %d\n", data->pnfs_error); | ||
1195 | if (NFS_SERVER(data->inode)->pnfs_curr_ld->flags & | ||
1196 | PNFS_LAYOUTRET_ON_ERROR) { | ||
1197 | clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(data->inode)->flags); | ||
1198 | pnfs_return_layout(data->inode); | ||
1199 | } | ||
1200 | data->task.tk_status = pnfs_write_done_resend_to_mds(data->inode, &data->pages); | ||
1201 | } | ||
1202 | |||
1192 | /* | 1203 | /* |
1193 | * Called by non rpc-based layout drivers | 1204 | * Called by non rpc-based layout drivers |
1194 | */ | 1205 | */ |
@@ -1197,19 +1208,8 @@ void pnfs_ld_write_done(struct nfs_write_data *data) | |||
1197 | if (likely(!data->pnfs_error)) { | 1208 | if (likely(!data->pnfs_error)) { |
1198 | pnfs_set_layoutcommit(data); | 1209 | pnfs_set_layoutcommit(data); |
1199 | data->mds_ops->rpc_call_done(&data->task, data); | 1210 | data->mds_ops->rpc_call_done(&data->task, data); |
1200 | } else { | 1211 | } else |
1201 | dprintk("pnfs write error = %d\n", data->pnfs_error); | 1212 | pnfs_ld_handle_write_error(data); |
1202 | if (NFS_SERVER(data->inode)->pnfs_curr_ld->flags & | ||
1203 | PNFS_LAYOUTRET_ON_ERROR) { | ||
1204 | /* Don't lo_commit on error, Server will needs to | ||
1205 | * preform a file recovery. | ||
1206 | */ | ||
1207 | clear_bit(NFS_INO_LAYOUTCOMMIT, | ||
1208 | &NFS_I(data->inode)->flags); | ||
1209 | pnfs_return_layout(data->inode); | ||
1210 | } | ||
1211 | data->task.tk_status = pnfs_write_done_resend_to_mds(data->inode, &data->pages); | ||
1212 | } | ||
1213 | put_lseg(data->lseg); | 1213 | put_lseg(data->lseg); |
1214 | data->mds_ops->rpc_release(data); | 1214 | data->mds_ops->rpc_release(data); |
1215 | } | 1215 | } |
@@ -1293,26 +1293,38 @@ pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) | |||
1293 | } | 1293 | } |
1294 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_writepages); | 1294 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_writepages); |
1295 | 1295 | ||
1296 | static void pnfs_ld_handle_read_error(struct nfs_read_data *data) | 1296 | static int pnfs_read_done_resend_to_mds(struct inode *inode, struct list_head *head) |
1297 | { | 1297 | { |
1298 | struct nfs_pageio_descriptor pgio; | 1298 | struct nfs_pageio_descriptor pgio; |
1299 | LIST_HEAD(failed); | ||
1299 | 1300 | ||
1300 | put_lseg(data->lseg); | 1301 | /* Resend all requests through the MDS */ |
1301 | data->lseg = NULL; | 1302 | nfs_pageio_init_read_mds(&pgio, inode); |
1302 | dprintk("pnfs write error = %d\n", data->pnfs_error); | 1303 | while (!list_empty(head)) { |
1303 | if (NFS_SERVER(data->inode)->pnfs_curr_ld->flags & | 1304 | struct nfs_page *req = nfs_list_entry(head->next); |
1304 | PNFS_LAYOUTRET_ON_ERROR) | ||
1305 | pnfs_return_layout(data->inode); | ||
1306 | |||
1307 | nfs_pageio_init_read_mds(&pgio, data->inode); | ||
1308 | |||
1309 | while (!list_empty(&data->pages)) { | ||
1310 | struct nfs_page *req = nfs_list_entry(data->pages.next); | ||
1311 | 1305 | ||
1312 | nfs_list_remove_request(req); | 1306 | nfs_list_remove_request(req); |
1313 | nfs_pageio_add_request(&pgio, req); | 1307 | if (!nfs_pageio_add_request(&pgio, req)) |
1308 | nfs_list_add_request(req, &failed); | ||
1314 | } | 1309 | } |
1315 | nfs_pageio_complete(&pgio); | 1310 | nfs_pageio_complete(&pgio); |
1311 | |||
1312 | if (!list_empty(&failed)) { | ||
1313 | list_move(&failed, head); | ||
1314 | return -EIO; | ||
1315 | } | ||
1316 | return 0; | ||
1317 | } | ||
1318 | |||
1319 | static void pnfs_ld_handle_read_error(struct nfs_read_data *data) | ||
1320 | { | ||
1321 | dprintk("pnfs read error = %d\n", data->pnfs_error); | ||
1322 | if (NFS_SERVER(data->inode)->pnfs_curr_ld->flags & | ||
1323 | PNFS_LAYOUTRET_ON_ERROR) { | ||
1324 | clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(data->inode)->flags); | ||
1325 | pnfs_return_layout(data->inode); | ||
1326 | } | ||
1327 | data->task.tk_status = pnfs_read_done_resend_to_mds(data->inode, &data->pages); | ||
1316 | } | 1328 | } |
1317 | 1329 | ||
1318 | /* | 1330 | /* |