diff options
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r-- | fs/nfs/write.c | 41 |
1 files changed, 26 insertions, 15 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index f5f005e9db48..6927a18b6891 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -441,7 +441,7 @@ nfs_mark_request_dirty(struct nfs_page *req) | |||
441 | * Add a request to the inode's commit list. | 441 | * Add a request to the inode's commit list. |
442 | */ | 442 | */ |
443 | static void | 443 | static void |
444 | nfs_mark_request_commit(struct nfs_page *req) | 444 | nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) |
445 | { | 445 | { |
446 | struct inode *inode = req->wb_context->path.dentry->d_inode; | 446 | struct inode *inode = req->wb_context->path.dentry->d_inode; |
447 | struct nfs_inode *nfsi = NFS_I(inode); | 447 | struct nfs_inode *nfsi = NFS_I(inode); |
@@ -453,6 +453,7 @@ nfs_mark_request_commit(struct nfs_page *req) | |||
453 | NFS_PAGE_TAG_COMMIT); | 453 | NFS_PAGE_TAG_COMMIT); |
454 | nfsi->ncommit++; | 454 | nfsi->ncommit++; |
455 | spin_unlock(&inode->i_lock); | 455 | spin_unlock(&inode->i_lock); |
456 | pnfs_mark_request_commit(req, lseg); | ||
456 | inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | 457 | inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); |
457 | inc_bdi_stat(req->wb_page->mapping->backing_dev_info, BDI_RECLAIMABLE); | 458 | inc_bdi_stat(req->wb_page->mapping->backing_dev_info, BDI_RECLAIMABLE); |
458 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); | 459 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); |
@@ -481,10 +482,11 @@ int nfs_write_need_commit(struct nfs_write_data *data) | |||
481 | } | 482 | } |
482 | 483 | ||
483 | static inline | 484 | static inline |
484 | int nfs_reschedule_unstable_write(struct nfs_page *req) | 485 | int nfs_reschedule_unstable_write(struct nfs_page *req, |
486 | struct nfs_write_data *data) | ||
485 | { | 487 | { |
486 | if (test_and_clear_bit(PG_NEED_COMMIT, &req->wb_flags)) { | 488 | if (test_and_clear_bit(PG_NEED_COMMIT, &req->wb_flags)) { |
487 | nfs_mark_request_commit(req); | 489 | nfs_mark_request_commit(req, data->lseg); |
488 | return 1; | 490 | return 1; |
489 | } | 491 | } |
490 | if (test_and_clear_bit(PG_NEED_RESCHED, &req->wb_flags)) { | 492 | if (test_and_clear_bit(PG_NEED_RESCHED, &req->wb_flags)) { |
@@ -495,7 +497,7 @@ int nfs_reschedule_unstable_write(struct nfs_page *req) | |||
495 | } | 497 | } |
496 | #else | 498 | #else |
497 | static inline void | 499 | static inline void |
498 | nfs_mark_request_commit(struct nfs_page *req) | 500 | nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) |
499 | { | 501 | { |
500 | } | 502 | } |
501 | 503 | ||
@@ -512,7 +514,8 @@ int nfs_write_need_commit(struct nfs_write_data *data) | |||
512 | } | 514 | } |
513 | 515 | ||
514 | static inline | 516 | static inline |
515 | int nfs_reschedule_unstable_write(struct nfs_page *req) | 517 | int nfs_reschedule_unstable_write(struct nfs_page *req, |
518 | struct nfs_write_data *data) | ||
516 | { | 519 | { |
517 | return 0; | 520 | return 0; |
518 | } | 521 | } |
@@ -615,9 +618,11 @@ static struct nfs_page *nfs_try_to_update_request(struct inode *inode, | |||
615 | } | 618 | } |
616 | 619 | ||
617 | if (nfs_clear_request_commit(req) && | 620 | if (nfs_clear_request_commit(req) && |
618 | radix_tree_tag_clear(&NFS_I(inode)->nfs_page_tree, | 621 | radix_tree_tag_clear(&NFS_I(inode)->nfs_page_tree, |
619 | req->wb_index, NFS_PAGE_TAG_COMMIT) != NULL) | 622 | req->wb_index, NFS_PAGE_TAG_COMMIT) != NULL) { |
620 | NFS_I(inode)->ncommit--; | 623 | NFS_I(inode)->ncommit--; |
624 | pnfs_clear_request_commit(req); | ||
625 | } | ||
621 | 626 | ||
622 | /* Okay, the request matches. Update the region */ | 627 | /* Okay, the request matches. Update the region */ |
623 | if (offset < req->wb_offset) { | 628 | if (offset < req->wb_offset) { |
@@ -765,11 +770,12 @@ int nfs_updatepage(struct file *file, struct page *page, | |||
765 | return status; | 770 | return status; |
766 | } | 771 | } |
767 | 772 | ||
768 | static void nfs_writepage_release(struct nfs_page *req) | 773 | static void nfs_writepage_release(struct nfs_page *req, |
774 | struct nfs_write_data *data) | ||
769 | { | 775 | { |
770 | struct page *page = req->wb_page; | 776 | struct page *page = req->wb_page; |
771 | 777 | ||
772 | if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req)) | 778 | if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req, data)) |
773 | nfs_inode_remove_request(req); | 779 | nfs_inode_remove_request(req); |
774 | nfs_clear_page_tag_locked(req); | 780 | nfs_clear_page_tag_locked(req); |
775 | nfs_end_page_writeback(page); | 781 | nfs_end_page_writeback(page); |
@@ -1087,7 +1093,7 @@ static void nfs_writeback_release_partial(void *calldata) | |||
1087 | 1093 | ||
1088 | out: | 1094 | out: |
1089 | if (atomic_dec_and_test(&req->wb_complete)) | 1095 | if (atomic_dec_and_test(&req->wb_complete)) |
1090 | nfs_writepage_release(req); | 1096 | nfs_writepage_release(req, data); |
1091 | nfs_writedata_release(calldata); | 1097 | nfs_writedata_release(calldata); |
1092 | } | 1098 | } |
1093 | 1099 | ||
@@ -1154,7 +1160,7 @@ static void nfs_writeback_release_full(void *calldata) | |||
1154 | 1160 | ||
1155 | if (nfs_write_need_commit(data)) { | 1161 | if (nfs_write_need_commit(data)) { |
1156 | memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); | 1162 | memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); |
1157 | nfs_mark_request_commit(req); | 1163 | nfs_mark_request_commit(req, data->lseg); |
1158 | dprintk(" marked for commit\n"); | 1164 | dprintk(" marked for commit\n"); |
1159 | goto next; | 1165 | goto next; |
1160 | } | 1166 | } |
@@ -1357,14 +1363,15 @@ static void nfs_init_commit(struct nfs_write_data *data, | |||
1357 | nfs_fattr_init(&data->fattr); | 1363 | nfs_fattr_init(&data->fattr); |
1358 | } | 1364 | } |
1359 | 1365 | ||
1360 | static void nfs_retry_commit(struct list_head *page_list) | 1366 | static void nfs_retry_commit(struct list_head *page_list, |
1367 | struct pnfs_layout_segment *lseg) | ||
1361 | { | 1368 | { |
1362 | struct nfs_page *req; | 1369 | struct nfs_page *req; |
1363 | 1370 | ||
1364 | while (!list_empty(page_list)) { | 1371 | while (!list_empty(page_list)) { |
1365 | req = nfs_list_entry(page_list->next); | 1372 | req = nfs_list_entry(page_list->next); |
1366 | nfs_list_remove_request(req); | 1373 | nfs_list_remove_request(req); |
1367 | nfs_mark_request_commit(req); | 1374 | nfs_mark_request_commit(req, lseg); |
1368 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | 1375 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); |
1369 | dec_bdi_stat(req->wb_page->mapping->backing_dev_info, | 1376 | dec_bdi_stat(req->wb_page->mapping->backing_dev_info, |
1370 | BDI_RECLAIMABLE); | 1377 | BDI_RECLAIMABLE); |
@@ -1389,7 +1396,7 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how) | |||
1389 | nfs_init_commit(data, head); | 1396 | nfs_init_commit(data, head); |
1390 | return nfs_initiate_commit(data, NFS_CLIENT(inode), data->mds_ops, how); | 1397 | return nfs_initiate_commit(data, NFS_CLIENT(inode), data->mds_ops, how); |
1391 | out_bad: | 1398 | out_bad: |
1392 | nfs_retry_commit(head); | 1399 | nfs_retry_commit(head, NULL); |
1393 | nfs_commit_clear_lock(NFS_I(inode)); | 1400 | nfs_commit_clear_lock(NFS_I(inode)); |
1394 | return -ENOMEM; | 1401 | return -ENOMEM; |
1395 | } | 1402 | } |
@@ -1477,7 +1484,11 @@ int nfs_commit_inode(struct inode *inode, int how) | |||
1477 | res = nfs_scan_commit(inode, &head, 0, 0); | 1484 | res = nfs_scan_commit(inode, &head, 0, 0); |
1478 | spin_unlock(&inode->i_lock); | 1485 | spin_unlock(&inode->i_lock); |
1479 | if (res) { | 1486 | if (res) { |
1480 | int error = nfs_commit_list(inode, &head, how); | 1487 | int error; |
1488 | |||
1489 | error = pnfs_commit_list(inode, &head, how); | ||
1490 | if (error == PNFS_NOT_ATTEMPTED) | ||
1491 | error = nfs_commit_list(inode, &head, how); | ||
1481 | if (error < 0) | 1492 | if (error < 0) |
1482 | return error; | 1493 | return error; |
1483 | if (!may_wait) | 1494 | if (!may_wait) |