diff options
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r-- | fs/nfs/write.c | 419 |
1 files changed, 264 insertions, 155 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 874972d9427c..727168059684 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "iostat.h" | 28 | #include "iostat.h" |
29 | #include "nfs4_fs.h" | 29 | #include "nfs4_fs.h" |
30 | #include "fscache.h" | 30 | #include "fscache.h" |
31 | #include "pnfs.h" | ||
31 | 32 | ||
32 | #define NFSDBG_FACILITY NFSDBG_PAGECACHE | 33 | #define NFSDBG_FACILITY NFSDBG_PAGECACHE |
33 | 34 | ||
@@ -55,10 +56,10 @@ struct nfs_write_data *nfs_commitdata_alloc(void) | |||
55 | if (p) { | 56 | if (p) { |
56 | memset(p, 0, sizeof(*p)); | 57 | memset(p, 0, sizeof(*p)); |
57 | INIT_LIST_HEAD(&p->pages); | 58 | INIT_LIST_HEAD(&p->pages); |
58 | p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE; | ||
59 | } | 59 | } |
60 | return p; | 60 | return p; |
61 | } | 61 | } |
62 | EXPORT_SYMBOL_GPL(nfs_commitdata_alloc); | ||
62 | 63 | ||
63 | void nfs_commit_free(struct nfs_write_data *p) | 64 | void nfs_commit_free(struct nfs_write_data *p) |
64 | { | 65 | { |
@@ -66,6 +67,7 @@ void nfs_commit_free(struct nfs_write_data *p) | |||
66 | kfree(p->pagevec); | 67 | kfree(p->pagevec); |
67 | mempool_free(p, nfs_commit_mempool); | 68 | mempool_free(p, nfs_commit_mempool); |
68 | } | 69 | } |
70 | EXPORT_SYMBOL_GPL(nfs_commit_free); | ||
69 | 71 | ||
70 | struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount) | 72 | struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount) |
71 | { | 73 | { |
@@ -75,7 +77,6 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount) | |||
75 | memset(p, 0, sizeof(*p)); | 77 | memset(p, 0, sizeof(*p)); |
76 | INIT_LIST_HEAD(&p->pages); | 78 | INIT_LIST_HEAD(&p->pages); |
77 | p->npages = pagecount; | 79 | p->npages = pagecount; |
78 | p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE; | ||
79 | if (pagecount <= ARRAY_SIZE(p->page_array)) | 80 | if (pagecount <= ARRAY_SIZE(p->page_array)) |
80 | p->pagevec = p->page_array; | 81 | p->pagevec = p->page_array; |
81 | else { | 82 | else { |
@@ -98,6 +99,7 @@ void nfs_writedata_free(struct nfs_write_data *p) | |||
98 | 99 | ||
99 | static void nfs_writedata_release(struct nfs_write_data *wdata) | 100 | static void nfs_writedata_release(struct nfs_write_data *wdata) |
100 | { | 101 | { |
102 | put_lseg(wdata->lseg); | ||
101 | put_nfs_open_context(wdata->args.context); | 103 | put_nfs_open_context(wdata->args.context); |
102 | nfs_writedata_free(wdata); | 104 | nfs_writedata_free(wdata); |
103 | } | 105 | } |
@@ -179,8 +181,8 @@ static int wb_priority(struct writeback_control *wbc) | |||
179 | if (wbc->for_reclaim) | 181 | if (wbc->for_reclaim) |
180 | return FLUSH_HIGHPRI | FLUSH_STABLE; | 182 | return FLUSH_HIGHPRI | FLUSH_STABLE; |
181 | if (wbc->for_kupdate || wbc->for_background) | 183 | if (wbc->for_kupdate || wbc->for_background) |
182 | return FLUSH_LOWPRI; | 184 | return FLUSH_LOWPRI | FLUSH_COND_STABLE; |
183 | return 0; | 185 | return FLUSH_COND_STABLE; |
184 | } | 186 | } |
185 | 187 | ||
186 | /* | 188 | /* |
@@ -292,9 +294,7 @@ static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, st | |||
292 | nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1); | 294 | nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1); |
293 | 295 | ||
294 | nfs_pageio_cond_complete(pgio, page->index); | 296 | nfs_pageio_cond_complete(pgio, page->index); |
295 | ret = nfs_page_async_flush(pgio, page, | 297 | ret = nfs_page_async_flush(pgio, page, wbc->sync_mode == WB_SYNC_NONE); |
296 | wbc->sync_mode == WB_SYNC_NONE || | ||
297 | wbc->nonblocking != 0); | ||
298 | if (ret == -EAGAIN) { | 298 | if (ret == -EAGAIN) { |
299 | redirty_page_for_writepage(wbc, page); | 299 | redirty_page_for_writepage(wbc, page); |
300 | ret = 0; | 300 | ret = 0; |
@@ -389,11 +389,9 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req) | |||
389 | spin_lock(&inode->i_lock); | 389 | spin_lock(&inode->i_lock); |
390 | error = radix_tree_insert(&nfsi->nfs_page_tree, req->wb_index, req); | 390 | error = radix_tree_insert(&nfsi->nfs_page_tree, req->wb_index, req); |
391 | BUG_ON(error); | 391 | BUG_ON(error); |
392 | if (!nfsi->npages) { | 392 | if (!nfsi->npages && nfs_have_delegation(inode, FMODE_WRITE)) |
393 | igrab(inode); | 393 | nfsi->change_attr++; |
394 | if (nfs_have_delegation(inode, FMODE_WRITE)) | 394 | set_bit(PG_MAPPED, &req->wb_flags); |
395 | nfsi->change_attr++; | ||
396 | } | ||
397 | SetPagePrivate(req->wb_page); | 395 | SetPagePrivate(req->wb_page); |
398 | set_page_private(req->wb_page, (unsigned long)req); | 396 | set_page_private(req->wb_page, (unsigned long)req); |
399 | nfsi->npages++; | 397 | nfsi->npages++; |
@@ -419,14 +417,10 @@ static void nfs_inode_remove_request(struct nfs_page *req) | |||
419 | spin_lock(&inode->i_lock); | 417 | spin_lock(&inode->i_lock); |
420 | set_page_private(req->wb_page, 0); | 418 | set_page_private(req->wb_page, 0); |
421 | ClearPagePrivate(req->wb_page); | 419 | ClearPagePrivate(req->wb_page); |
420 | clear_bit(PG_MAPPED, &req->wb_flags); | ||
422 | radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index); | 421 | radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index); |
423 | nfsi->npages--; | 422 | nfsi->npages--; |
424 | if (!nfsi->npages) { | 423 | spin_unlock(&inode->i_lock); |
425 | spin_unlock(&inode->i_lock); | ||
426 | iput(inode); | ||
427 | } else | ||
428 | spin_unlock(&inode->i_lock); | ||
429 | nfs_clear_request(req); | ||
430 | nfs_release_request(req); | 424 | nfs_release_request(req); |
431 | } | 425 | } |
432 | 426 | ||
@@ -442,7 +436,7 @@ nfs_mark_request_dirty(struct nfs_page *req) | |||
442 | * Add a request to the inode's commit list. | 436 | * Add a request to the inode's commit list. |
443 | */ | 437 | */ |
444 | static void | 438 | static void |
445 | nfs_mark_request_commit(struct nfs_page *req) | 439 | nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) |
446 | { | 440 | { |
447 | struct inode *inode = req->wb_context->path.dentry->d_inode; | 441 | struct inode *inode = req->wb_context->path.dentry->d_inode; |
448 | struct nfs_inode *nfsi = NFS_I(inode); | 442 | struct nfs_inode *nfsi = NFS_I(inode); |
@@ -454,6 +448,7 @@ nfs_mark_request_commit(struct nfs_page *req) | |||
454 | NFS_PAGE_TAG_COMMIT); | 448 | NFS_PAGE_TAG_COMMIT); |
455 | nfsi->ncommit++; | 449 | nfsi->ncommit++; |
456 | spin_unlock(&inode->i_lock); | 450 | spin_unlock(&inode->i_lock); |
451 | pnfs_mark_request_commit(req, lseg); | ||
457 | inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | 452 | inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); |
458 | inc_bdi_stat(req->wb_page->mapping->backing_dev_info, BDI_RECLAIMABLE); | 453 | inc_bdi_stat(req->wb_page->mapping->backing_dev_info, BDI_RECLAIMABLE); |
459 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); | 454 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); |
@@ -475,14 +470,18 @@ nfs_clear_request_commit(struct nfs_page *req) | |||
475 | static inline | 470 | static inline |
476 | int nfs_write_need_commit(struct nfs_write_data *data) | 471 | int nfs_write_need_commit(struct nfs_write_data *data) |
477 | { | 472 | { |
478 | return data->verf.committed != NFS_FILE_SYNC; | 473 | if (data->verf.committed == NFS_DATA_SYNC) |
474 | return data->lseg == NULL; | ||
475 | else | ||
476 | return data->verf.committed != NFS_FILE_SYNC; | ||
479 | } | 477 | } |
480 | 478 | ||
481 | static inline | 479 | static inline |
482 | int nfs_reschedule_unstable_write(struct nfs_page *req) | 480 | int nfs_reschedule_unstable_write(struct nfs_page *req, |
481 | struct nfs_write_data *data) | ||
483 | { | 482 | { |
484 | if (test_and_clear_bit(PG_NEED_COMMIT, &req->wb_flags)) { | 483 | if (test_and_clear_bit(PG_NEED_COMMIT, &req->wb_flags)) { |
485 | nfs_mark_request_commit(req); | 484 | nfs_mark_request_commit(req, data->lseg); |
486 | return 1; | 485 | return 1; |
487 | } | 486 | } |
488 | if (test_and_clear_bit(PG_NEED_RESCHED, &req->wb_flags)) { | 487 | if (test_and_clear_bit(PG_NEED_RESCHED, &req->wb_flags)) { |
@@ -493,7 +492,7 @@ int nfs_reschedule_unstable_write(struct nfs_page *req) | |||
493 | } | 492 | } |
494 | #else | 493 | #else |
495 | static inline void | 494 | static inline void |
496 | nfs_mark_request_commit(struct nfs_page *req) | 495 | nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) |
497 | { | 496 | { |
498 | } | 497 | } |
499 | 498 | ||
@@ -510,7 +509,8 @@ int nfs_write_need_commit(struct nfs_write_data *data) | |||
510 | } | 509 | } |
511 | 510 | ||
512 | static inline | 511 | static inline |
513 | int nfs_reschedule_unstable_write(struct nfs_page *req) | 512 | int nfs_reschedule_unstable_write(struct nfs_page *req, |
513 | struct nfs_write_data *data) | ||
514 | { | 514 | { |
515 | return 0; | 515 | return 0; |
516 | } | 516 | } |
@@ -542,11 +542,15 @@ nfs_scan_commit(struct inode *inode, struct list_head *dst, pgoff_t idx_start, u | |||
542 | if (!nfs_need_commit(nfsi)) | 542 | if (!nfs_need_commit(nfsi)) |
543 | return 0; | 543 | return 0; |
544 | 544 | ||
545 | spin_lock(&inode->i_lock); | ||
545 | ret = nfs_scan_list(nfsi, dst, idx_start, npages, NFS_PAGE_TAG_COMMIT); | 546 | ret = nfs_scan_list(nfsi, dst, idx_start, npages, NFS_PAGE_TAG_COMMIT); |
546 | if (ret > 0) | 547 | if (ret > 0) |
547 | nfsi->ncommit -= ret; | 548 | nfsi->ncommit -= ret; |
549 | spin_unlock(&inode->i_lock); | ||
550 | |||
548 | if (nfs_need_commit(NFS_I(inode))) | 551 | if (nfs_need_commit(NFS_I(inode))) |
549 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); | 552 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); |
553 | |||
550 | return ret; | 554 | return ret; |
551 | } | 555 | } |
552 | #else | 556 | #else |
@@ -613,9 +617,11 @@ static struct nfs_page *nfs_try_to_update_request(struct inode *inode, | |||
613 | } | 617 | } |
614 | 618 | ||
615 | if (nfs_clear_request_commit(req) && | 619 | if (nfs_clear_request_commit(req) && |
616 | radix_tree_tag_clear(&NFS_I(inode)->nfs_page_tree, | 620 | radix_tree_tag_clear(&NFS_I(inode)->nfs_page_tree, |
617 | req->wb_index, NFS_PAGE_TAG_COMMIT) != NULL) | 621 | req->wb_index, NFS_PAGE_TAG_COMMIT) != NULL) { |
618 | NFS_I(inode)->ncommit--; | 622 | NFS_I(inode)->ncommit--; |
623 | pnfs_clear_request_commit(req); | ||
624 | } | ||
619 | 625 | ||
620 | /* Okay, the request matches. Update the region */ | 626 | /* Okay, the request matches. Update the region */ |
621 | if (offset < req->wb_offset) { | 627 | if (offset < req->wb_offset) { |
@@ -674,7 +680,6 @@ static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page, | |||
674 | req = nfs_setup_write_request(ctx, page, offset, count); | 680 | req = nfs_setup_write_request(ctx, page, offset, count); |
675 | if (IS_ERR(req)) | 681 | if (IS_ERR(req)) |
676 | return PTR_ERR(req); | 682 | return PTR_ERR(req); |
677 | nfs_mark_request_dirty(req); | ||
678 | /* Update file length */ | 683 | /* Update file length */ |
679 | nfs_grow_file(page, offset, count); | 684 | nfs_grow_file(page, offset, count); |
680 | nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes); | 685 | nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes); |
@@ -763,11 +768,12 @@ int nfs_updatepage(struct file *file, struct page *page, | |||
763 | return status; | 768 | return status; |
764 | } | 769 | } |
765 | 770 | ||
766 | static void nfs_writepage_release(struct nfs_page *req) | 771 | static void nfs_writepage_release(struct nfs_page *req, |
772 | struct nfs_write_data *data) | ||
767 | { | 773 | { |
768 | struct page *page = req->wb_page; | 774 | struct page *page = req->wb_page; |
769 | 775 | ||
770 | if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req)) | 776 | if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req, data)) |
771 | nfs_inode_remove_request(req); | 777 | nfs_inode_remove_request(req); |
772 | nfs_clear_page_tag_locked(req); | 778 | nfs_clear_page_tag_locked(req); |
773 | nfs_end_page_writeback(page); | 779 | nfs_end_page_writeback(page); |
@@ -784,25 +790,21 @@ static int flush_task_priority(int how) | |||
784 | return RPC_PRIORITY_NORMAL; | 790 | return RPC_PRIORITY_NORMAL; |
785 | } | 791 | } |
786 | 792 | ||
787 | /* | 793 | int nfs_initiate_write(struct nfs_write_data *data, |
788 | * Set up the argument/result storage required for the RPC call. | 794 | struct rpc_clnt *clnt, |
789 | */ | 795 | const struct rpc_call_ops *call_ops, |
790 | static int nfs_write_rpcsetup(struct nfs_page *req, | 796 | int how) |
791 | struct nfs_write_data *data, | ||
792 | const struct rpc_call_ops *call_ops, | ||
793 | unsigned int count, unsigned int offset, | ||
794 | int how) | ||
795 | { | 797 | { |
796 | struct inode *inode = req->wb_context->path.dentry->d_inode; | 798 | struct inode *inode = data->inode; |
797 | int priority = flush_task_priority(how); | 799 | int priority = flush_task_priority(how); |
798 | struct rpc_task *task; | 800 | struct rpc_task *task; |
799 | struct rpc_message msg = { | 801 | struct rpc_message msg = { |
800 | .rpc_argp = &data->args, | 802 | .rpc_argp = &data->args, |
801 | .rpc_resp = &data->res, | 803 | .rpc_resp = &data->res, |
802 | .rpc_cred = req->wb_context->cred, | 804 | .rpc_cred = data->cred, |
803 | }; | 805 | }; |
804 | struct rpc_task_setup task_setup_data = { | 806 | struct rpc_task_setup task_setup_data = { |
805 | .rpc_client = NFS_CLIENT(inode), | 807 | .rpc_client = clnt, |
806 | .task = &data->task, | 808 | .task = &data->task, |
807 | .rpc_message = &msg, | 809 | .rpc_message = &msg, |
808 | .callback_ops = call_ops, | 810 | .callback_ops = call_ops, |
@@ -813,22 +815,64 @@ static int nfs_write_rpcsetup(struct nfs_page *req, | |||
813 | }; | 815 | }; |
814 | int ret = 0; | 816 | int ret = 0; |
815 | 817 | ||
818 | /* Set up the initial task struct. */ | ||
819 | NFS_PROTO(inode)->write_setup(data, &msg); | ||
820 | |||
821 | dprintk("NFS: %5u initiated write call " | ||
822 | "(req %s/%lld, %u bytes @ offset %llu)\n", | ||
823 | data->task.tk_pid, | ||
824 | inode->i_sb->s_id, | ||
825 | (long long)NFS_FILEID(inode), | ||
826 | data->args.count, | ||
827 | (unsigned long long)data->args.offset); | ||
828 | |||
829 | task = rpc_run_task(&task_setup_data); | ||
830 | if (IS_ERR(task)) { | ||
831 | ret = PTR_ERR(task); | ||
832 | goto out; | ||
833 | } | ||
834 | if (how & FLUSH_SYNC) { | ||
835 | ret = rpc_wait_for_completion_task(task); | ||
836 | if (ret == 0) | ||
837 | ret = task->tk_status; | ||
838 | } | ||
839 | rpc_put_task(task); | ||
840 | out: | ||
841 | return ret; | ||
842 | } | ||
843 | EXPORT_SYMBOL_GPL(nfs_initiate_write); | ||
844 | |||
845 | /* | ||
846 | * Set up the argument/result storage required for the RPC call. | ||
847 | */ | ||
848 | static int nfs_write_rpcsetup(struct nfs_page *req, | ||
849 | struct nfs_write_data *data, | ||
850 | const struct rpc_call_ops *call_ops, | ||
851 | unsigned int count, unsigned int offset, | ||
852 | struct pnfs_layout_segment *lseg, | ||
853 | int how) | ||
854 | { | ||
855 | struct inode *inode = req->wb_context->path.dentry->d_inode; | ||
856 | |||
816 | /* Set up the RPC argument and reply structs | 857 | /* Set up the RPC argument and reply structs |
817 | * NB: take care not to mess about with data->commit et al. */ | 858 | * NB: take care not to mess about with data->commit et al. */ |
818 | 859 | ||
819 | data->req = req; | 860 | data->req = req; |
820 | data->inode = inode = req->wb_context->path.dentry->d_inode; | 861 | data->inode = inode = req->wb_context->path.dentry->d_inode; |
821 | data->cred = msg.rpc_cred; | 862 | data->cred = req->wb_context->cred; |
863 | data->lseg = get_lseg(lseg); | ||
822 | 864 | ||
823 | data->args.fh = NFS_FH(inode); | 865 | data->args.fh = NFS_FH(inode); |
824 | data->args.offset = req_offset(req) + offset; | 866 | data->args.offset = req_offset(req) + offset; |
867 | /* pnfs_set_layoutcommit needs this */ | ||
868 | data->mds_offset = data->args.offset; | ||
825 | data->args.pgbase = req->wb_pgbase + offset; | 869 | data->args.pgbase = req->wb_pgbase + offset; |
826 | data->args.pages = data->pagevec; | 870 | data->args.pages = data->pagevec; |
827 | data->args.count = count; | 871 | data->args.count = count; |
828 | data->args.context = get_nfs_open_context(req->wb_context); | 872 | data->args.context = get_nfs_open_context(req->wb_context); |
829 | data->args.lock_context = req->wb_lock_context; | 873 | data->args.lock_context = req->wb_lock_context; |
830 | data->args.stable = NFS_UNSTABLE; | 874 | data->args.stable = NFS_UNSTABLE; |
831 | if (how & FLUSH_STABLE) { | 875 | if (how & (FLUSH_STABLE | FLUSH_COND_STABLE)) { |
832 | data->args.stable = NFS_DATA_SYNC; | 876 | data->args.stable = NFS_DATA_SYNC; |
833 | if (!nfs_need_commit(NFS_I(inode))) | 877 | if (!nfs_need_commit(NFS_I(inode))) |
834 | data->args.stable = NFS_FILE_SYNC; | 878 | data->args.stable = NFS_FILE_SYNC; |
@@ -839,30 +883,11 @@ static int nfs_write_rpcsetup(struct nfs_page *req, | |||
839 | data->res.verf = &data->verf; | 883 | data->res.verf = &data->verf; |
840 | nfs_fattr_init(&data->fattr); | 884 | nfs_fattr_init(&data->fattr); |
841 | 885 | ||
842 | /* Set up the initial task struct. */ | 886 | if (data->lseg && |
843 | NFS_PROTO(inode)->write_setup(data, &msg); | 887 | (pnfs_try_to_write_data(data, call_ops, how) == PNFS_ATTEMPTED)) |
844 | 888 | return 0; | |
845 | dprintk("NFS: %5u initiated write call " | ||
846 | "(req %s/%lld, %u bytes @ offset %llu)\n", | ||
847 | data->task.tk_pid, | ||
848 | inode->i_sb->s_id, | ||
849 | (long long)NFS_FILEID(inode), | ||
850 | count, | ||
851 | (unsigned long long)data->args.offset); | ||
852 | 889 | ||
853 | task = rpc_run_task(&task_setup_data); | 890 | return nfs_initiate_write(data, NFS_CLIENT(inode), call_ops, how); |
854 | if (IS_ERR(task)) { | ||
855 | ret = PTR_ERR(task); | ||
856 | goto out; | ||
857 | } | ||
858 | if (how & FLUSH_SYNC) { | ||
859 | ret = rpc_wait_for_completion_task(task); | ||
860 | if (ret == 0) | ||
861 | ret = task->tk_status; | ||
862 | } | ||
863 | rpc_put_task(task); | ||
864 | out: | ||
865 | return ret; | ||
866 | } | 891 | } |
867 | 892 | ||
868 | /* If a nfs_flush_* function fails, it should remove reqs from @head and | 893 | /* If a nfs_flush_* function fails, it should remove reqs from @head and |
@@ -882,20 +907,27 @@ static void nfs_redirty_request(struct nfs_page *req) | |||
882 | * Generate multiple small requests to write out a single | 907 | * Generate multiple small requests to write out a single |
883 | * contiguous dirty area on one page. | 908 | * contiguous dirty area on one page. |
884 | */ | 909 | */ |
885 | static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int how) | 910 | static int nfs_flush_multi(struct nfs_pageio_descriptor *desc) |
886 | { | 911 | { |
887 | struct nfs_page *req = nfs_list_entry(head->next); | 912 | struct nfs_page *req = nfs_list_entry(desc->pg_list.next); |
888 | struct page *page = req->wb_page; | 913 | struct page *page = req->wb_page; |
889 | struct nfs_write_data *data; | 914 | struct nfs_write_data *data; |
890 | size_t wsize = NFS_SERVER(inode)->wsize, nbytes; | 915 | size_t wsize = NFS_SERVER(desc->pg_inode)->wsize, nbytes; |
891 | unsigned int offset; | 916 | unsigned int offset; |
892 | int requests = 0; | 917 | int requests = 0; |
893 | int ret = 0; | 918 | int ret = 0; |
919 | struct pnfs_layout_segment *lseg; | ||
894 | LIST_HEAD(list); | 920 | LIST_HEAD(list); |
895 | 921 | ||
896 | nfs_list_remove_request(req); | 922 | nfs_list_remove_request(req); |
897 | 923 | ||
898 | nbytes = count; | 924 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && |
925 | (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit || | ||
926 | desc->pg_count > wsize)) | ||
927 | desc->pg_ioflags &= ~FLUSH_COND_STABLE; | ||
928 | |||
929 | |||
930 | nbytes = desc->pg_count; | ||
899 | do { | 931 | do { |
900 | size_t len = min(nbytes, wsize); | 932 | size_t len = min(nbytes, wsize); |
901 | 933 | ||
@@ -908,9 +940,13 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned | |||
908 | } while (nbytes != 0); | 940 | } while (nbytes != 0); |
909 | atomic_set(&req->wb_complete, requests); | 941 | atomic_set(&req->wb_complete, requests); |
910 | 942 | ||
943 | BUG_ON(desc->pg_lseg); | ||
944 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, | ||
945 | req_offset(req), desc->pg_count, | ||
946 | IOMODE_RW, GFP_NOFS); | ||
911 | ClearPageError(page); | 947 | ClearPageError(page); |
912 | offset = 0; | 948 | offset = 0; |
913 | nbytes = count; | 949 | nbytes = desc->pg_count; |
914 | do { | 950 | do { |
915 | int ret2; | 951 | int ret2; |
916 | 952 | ||
@@ -922,20 +958,22 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned | |||
922 | if (nbytes < wsize) | 958 | if (nbytes < wsize) |
923 | wsize = nbytes; | 959 | wsize = nbytes; |
924 | ret2 = nfs_write_rpcsetup(req, data, &nfs_write_partial_ops, | 960 | ret2 = nfs_write_rpcsetup(req, data, &nfs_write_partial_ops, |
925 | wsize, offset, how); | 961 | wsize, offset, lseg, desc->pg_ioflags); |
926 | if (ret == 0) | 962 | if (ret == 0) |
927 | ret = ret2; | 963 | ret = ret2; |
928 | offset += wsize; | 964 | offset += wsize; |
929 | nbytes -= wsize; | 965 | nbytes -= wsize; |
930 | } while (nbytes != 0); | 966 | } while (nbytes != 0); |
931 | 967 | ||
968 | put_lseg(lseg); | ||
969 | desc->pg_lseg = NULL; | ||
932 | return ret; | 970 | return ret; |
933 | 971 | ||
934 | out_bad: | 972 | out_bad: |
935 | while (!list_empty(&list)) { | 973 | while (!list_empty(&list)) { |
936 | data = list_entry(list.next, struct nfs_write_data, pages); | 974 | data = list_entry(list.next, struct nfs_write_data, pages); |
937 | list_del(&data->pages); | 975 | list_del(&data->pages); |
938 | nfs_writedata_release(data); | 976 | nfs_writedata_free(data); |
939 | } | 977 | } |
940 | nfs_redirty_request(req); | 978 | nfs_redirty_request(req); |
941 | return -ENOMEM; | 979 | return -ENOMEM; |
@@ -949,16 +987,26 @@ out_bad: | |||
949 | * This is the case if nfs_updatepage detects a conflicting request | 987 | * This is the case if nfs_updatepage detects a conflicting request |
950 | * that has been written but not committed. | 988 | * that has been written but not committed. |
951 | */ | 989 | */ |
952 | static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int how) | 990 | static int nfs_flush_one(struct nfs_pageio_descriptor *desc) |
953 | { | 991 | { |
954 | struct nfs_page *req; | 992 | struct nfs_page *req; |
955 | struct page **pages; | 993 | struct page **pages; |
956 | struct nfs_write_data *data; | 994 | struct nfs_write_data *data; |
995 | struct list_head *head = &desc->pg_list; | ||
996 | struct pnfs_layout_segment *lseg = desc->pg_lseg; | ||
997 | int ret; | ||
957 | 998 | ||
958 | data = nfs_writedata_alloc(npages); | 999 | data = nfs_writedata_alloc(nfs_page_array_len(desc->pg_base, |
959 | if (!data) | 1000 | desc->pg_count)); |
960 | goto out_bad; | 1001 | if (!data) { |
961 | 1002 | while (!list_empty(head)) { | |
1003 | req = nfs_list_entry(head->next); | ||
1004 | nfs_list_remove_request(req); | ||
1005 | nfs_redirty_request(req); | ||
1006 | } | ||
1007 | ret = -ENOMEM; | ||
1008 | goto out; | ||
1009 | } | ||
962 | pages = data->pagevec; | 1010 | pages = data->pagevec; |
963 | while (!list_empty(head)) { | 1011 | while (!list_empty(head)) { |
964 | req = nfs_list_entry(head->next); | 1012 | req = nfs_list_entry(head->next); |
@@ -968,16 +1016,21 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned i | |||
968 | *pages++ = req->wb_page; | 1016 | *pages++ = req->wb_page; |
969 | } | 1017 | } |
970 | req = nfs_list_entry(data->pages.next); | 1018 | req = nfs_list_entry(data->pages.next); |
1019 | if ((!lseg) && list_is_singular(&data->pages)) | ||
1020 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, | ||
1021 | req_offset(req), desc->pg_count, | ||
1022 | IOMODE_RW, GFP_NOFS); | ||
1023 | |||
1024 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && | ||
1025 | (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit)) | ||
1026 | desc->pg_ioflags &= ~FLUSH_COND_STABLE; | ||
971 | 1027 | ||
972 | /* Set up the argument struct */ | 1028 | /* Set up the argument struct */ |
973 | return nfs_write_rpcsetup(req, data, &nfs_write_full_ops, count, 0, how); | 1029 | ret = nfs_write_rpcsetup(req, data, &nfs_write_full_ops, desc->pg_count, 0, lseg, desc->pg_ioflags); |
974 | out_bad: | 1030 | out: |
975 | while (!list_empty(head)) { | 1031 | put_lseg(lseg); /* Cleans any gotten in ->pg_test */ |
976 | req = nfs_list_entry(head->next); | 1032 | desc->pg_lseg = NULL; |
977 | nfs_list_remove_request(req); | 1033 | return ret; |
978 | nfs_redirty_request(req); | ||
979 | } | ||
980 | return -ENOMEM; | ||
981 | } | 1034 | } |
982 | 1035 | ||
983 | static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, | 1036 | static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, |
@@ -1042,7 +1095,7 @@ static void nfs_writeback_release_partial(void *calldata) | |||
1042 | 1095 | ||
1043 | out: | 1096 | out: |
1044 | if (atomic_dec_and_test(&req->wb_complete)) | 1097 | if (atomic_dec_and_test(&req->wb_complete)) |
1045 | nfs_writepage_release(req); | 1098 | nfs_writepage_release(req, data); |
1046 | nfs_writedata_release(calldata); | 1099 | nfs_writedata_release(calldata); |
1047 | } | 1100 | } |
1048 | 1101 | ||
@@ -1109,7 +1162,7 @@ static void nfs_writeback_release_full(void *calldata) | |||
1109 | 1162 | ||
1110 | if (nfs_write_need_commit(data)) { | 1163 | if (nfs_write_need_commit(data)) { |
1111 | memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); | 1164 | memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); |
1112 | nfs_mark_request_commit(req); | 1165 | nfs_mark_request_commit(req, data->lseg); |
1113 | dprintk(" marked for commit\n"); | 1166 | dprintk(" marked for commit\n"); |
1114 | goto next; | 1167 | goto next; |
1115 | } | 1168 | } |
@@ -1135,7 +1188,7 @@ static const struct rpc_call_ops nfs_write_full_ops = { | |||
1135 | /* | 1188 | /* |
1136 | * This function is called when the WRITE call is complete. | 1189 | * This function is called when the WRITE call is complete. |
1137 | */ | 1190 | */ |
1138 | int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) | 1191 | void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) |
1139 | { | 1192 | { |
1140 | struct nfs_writeargs *argp = &data->args; | 1193 | struct nfs_writeargs *argp = &data->args; |
1141 | struct nfs_writeres *resp = &data->res; | 1194 | struct nfs_writeres *resp = &data->res; |
@@ -1154,7 +1207,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) | |||
1154 | */ | 1207 | */ |
1155 | status = NFS_PROTO(data->inode)->write_done(task, data); | 1208 | status = NFS_PROTO(data->inode)->write_done(task, data); |
1156 | if (status != 0) | 1209 | if (status != 0) |
1157 | return status; | 1210 | return; |
1158 | nfs_add_stats(data->inode, NFSIOS_SERVERWRITTENBYTES, resp->count); | 1211 | nfs_add_stats(data->inode, NFSIOS_SERVERWRITTENBYTES, resp->count); |
1159 | 1212 | ||
1160 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) | 1213 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) |
@@ -1169,6 +1222,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) | |||
1169 | */ | 1222 | */ |
1170 | static unsigned long complain; | 1223 | static unsigned long complain; |
1171 | 1224 | ||
1225 | /* Note this will print the MDS for a DS write */ | ||
1172 | if (time_before(complain, jiffies)) { | 1226 | if (time_before(complain, jiffies)) { |
1173 | dprintk("NFS: faulty NFS server %s:" | 1227 | dprintk("NFS: faulty NFS server %s:" |
1174 | " (committed = %d) != (stable = %d)\n", | 1228 | " (committed = %d) != (stable = %d)\n", |
@@ -1189,6 +1243,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) | |||
1189 | /* Was this an NFSv2 write or an NFSv3 stable write? */ | 1243 | /* Was this an NFSv2 write or an NFSv3 stable write? */ |
1190 | if (resp->verf->committed != NFS_UNSTABLE) { | 1244 | if (resp->verf->committed != NFS_UNSTABLE) { |
1191 | /* Resend from where the server left off */ | 1245 | /* Resend from where the server left off */ |
1246 | data->mds_offset += resp->count; | ||
1192 | argp->offset += resp->count; | 1247 | argp->offset += resp->count; |
1193 | argp->pgbase += resp->count; | 1248 | argp->pgbase += resp->count; |
1194 | argp->count -= resp->count; | 1249 | argp->count -= resp->count; |
@@ -1199,7 +1254,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) | |||
1199 | argp->stable = NFS_FILE_SYNC; | 1254 | argp->stable = NFS_FILE_SYNC; |
1200 | } | 1255 | } |
1201 | nfs_restart_rpc(task, server->nfs_client); | 1256 | nfs_restart_rpc(task, server->nfs_client); |
1202 | return -EAGAIN; | 1257 | return; |
1203 | } | 1258 | } |
1204 | if (time_before(complain, jiffies)) { | 1259 | if (time_before(complain, jiffies)) { |
1205 | printk(KERN_WARNING | 1260 | printk(KERN_WARNING |
@@ -1210,64 +1265,89 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) | |||
1210 | /* Can't do anything about it except throw an error. */ | 1265 | /* Can't do anything about it except throw an error. */ |
1211 | task->tk_status = -EIO; | 1266 | task->tk_status = -EIO; |
1212 | } | 1267 | } |
1213 | return 0; | 1268 | return; |
1214 | } | 1269 | } |
1215 | 1270 | ||
1216 | 1271 | ||
1217 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) | 1272 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) |
1218 | static int nfs_commit_set_lock(struct nfs_inode *nfsi, int may_wait) | 1273 | static int nfs_commit_set_lock(struct nfs_inode *nfsi, int may_wait) |
1219 | { | 1274 | { |
1275 | int ret; | ||
1276 | |||
1220 | if (!test_and_set_bit(NFS_INO_COMMIT, &nfsi->flags)) | 1277 | if (!test_and_set_bit(NFS_INO_COMMIT, &nfsi->flags)) |
1221 | return 1; | 1278 | return 1; |
1222 | if (may_wait && !out_of_line_wait_on_bit_lock(&nfsi->flags, | 1279 | if (!may_wait) |
1223 | NFS_INO_COMMIT, nfs_wait_bit_killable, | 1280 | return 0; |
1224 | TASK_KILLABLE)) | 1281 | ret = out_of_line_wait_on_bit_lock(&nfsi->flags, |
1225 | return 1; | 1282 | NFS_INO_COMMIT, |
1226 | return 0; | 1283 | nfs_wait_bit_killable, |
1284 | TASK_KILLABLE); | ||
1285 | return (ret < 0) ? ret : 1; | ||
1227 | } | 1286 | } |
1228 | 1287 | ||
1229 | static void nfs_commit_clear_lock(struct nfs_inode *nfsi) | 1288 | void nfs_commit_clear_lock(struct nfs_inode *nfsi) |
1230 | { | 1289 | { |
1231 | clear_bit(NFS_INO_COMMIT, &nfsi->flags); | 1290 | clear_bit(NFS_INO_COMMIT, &nfsi->flags); |
1232 | smp_mb__after_clear_bit(); | 1291 | smp_mb__after_clear_bit(); |
1233 | wake_up_bit(&nfsi->flags, NFS_INO_COMMIT); | 1292 | wake_up_bit(&nfsi->flags, NFS_INO_COMMIT); |
1234 | } | 1293 | } |
1294 | EXPORT_SYMBOL_GPL(nfs_commit_clear_lock); | ||
1235 | 1295 | ||
1236 | 1296 | void nfs_commitdata_release(void *data) | |
1237 | static void nfs_commitdata_release(void *data) | ||
1238 | { | 1297 | { |
1239 | struct nfs_write_data *wdata = data; | 1298 | struct nfs_write_data *wdata = data; |
1240 | 1299 | ||
1300 | put_lseg(wdata->lseg); | ||
1241 | put_nfs_open_context(wdata->args.context); | 1301 | put_nfs_open_context(wdata->args.context); |
1242 | nfs_commit_free(wdata); | 1302 | nfs_commit_free(wdata); |
1243 | } | 1303 | } |
1304 | EXPORT_SYMBOL_GPL(nfs_commitdata_release); | ||
1244 | 1305 | ||
1245 | /* | 1306 | int nfs_initiate_commit(struct nfs_write_data *data, struct rpc_clnt *clnt, |
1246 | * Set up the argument/result storage required for the RPC call. | 1307 | const struct rpc_call_ops *call_ops, |
1247 | */ | 1308 | int how) |
1248 | static int nfs_commit_rpcsetup(struct list_head *head, | ||
1249 | struct nfs_write_data *data, | ||
1250 | int how) | ||
1251 | { | 1309 | { |
1252 | struct nfs_page *first = nfs_list_entry(head->next); | ||
1253 | struct inode *inode = first->wb_context->path.dentry->d_inode; | ||
1254 | int priority = flush_task_priority(how); | ||
1255 | struct rpc_task *task; | 1310 | struct rpc_task *task; |
1311 | int priority = flush_task_priority(how); | ||
1256 | struct rpc_message msg = { | 1312 | struct rpc_message msg = { |
1257 | .rpc_argp = &data->args, | 1313 | .rpc_argp = &data->args, |
1258 | .rpc_resp = &data->res, | 1314 | .rpc_resp = &data->res, |
1259 | .rpc_cred = first->wb_context->cred, | 1315 | .rpc_cred = data->cred, |
1260 | }; | 1316 | }; |
1261 | struct rpc_task_setup task_setup_data = { | 1317 | struct rpc_task_setup task_setup_data = { |
1262 | .task = &data->task, | 1318 | .task = &data->task, |
1263 | .rpc_client = NFS_CLIENT(inode), | 1319 | .rpc_client = clnt, |
1264 | .rpc_message = &msg, | 1320 | .rpc_message = &msg, |
1265 | .callback_ops = &nfs_commit_ops, | 1321 | .callback_ops = call_ops, |
1266 | .callback_data = data, | 1322 | .callback_data = data, |
1267 | .workqueue = nfsiod_workqueue, | 1323 | .workqueue = nfsiod_workqueue, |
1268 | .flags = RPC_TASK_ASYNC, | 1324 | .flags = RPC_TASK_ASYNC, |
1269 | .priority = priority, | 1325 | .priority = priority, |
1270 | }; | 1326 | }; |
1327 | /* Set up the initial task struct. */ | ||
1328 | NFS_PROTO(data->inode)->commit_setup(data, &msg); | ||
1329 | |||
1330 | dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); | ||
1331 | |||
1332 | task = rpc_run_task(&task_setup_data); | ||
1333 | if (IS_ERR(task)) | ||
1334 | return PTR_ERR(task); | ||
1335 | if (how & FLUSH_SYNC) | ||
1336 | rpc_wait_for_completion_task(task); | ||
1337 | rpc_put_task(task); | ||
1338 | return 0; | ||
1339 | } | ||
1340 | EXPORT_SYMBOL_GPL(nfs_initiate_commit); | ||
1341 | |||
1342 | /* | ||
1343 | * Set up the argument/result storage required for the RPC call. | ||
1344 | */ | ||
1345 | void nfs_init_commit(struct nfs_write_data *data, | ||
1346 | struct list_head *head, | ||
1347 | struct pnfs_layout_segment *lseg) | ||
1348 | { | ||
1349 | struct nfs_page *first = nfs_list_entry(head->next); | ||
1350 | struct inode *inode = first->wb_context->path.dentry->d_inode; | ||
1271 | 1351 | ||
1272 | /* Set up the RPC argument and reply structs | 1352 | /* Set up the RPC argument and reply structs |
1273 | * NB: take care not to mess about with data->commit et al. */ | 1353 | * NB: take care not to mess about with data->commit et al. */ |
@@ -1275,7 +1355,9 @@ static int nfs_commit_rpcsetup(struct list_head *head, | |||
1275 | list_splice_init(head, &data->pages); | 1355 | list_splice_init(head, &data->pages); |
1276 | 1356 | ||
1277 | data->inode = inode; | 1357 | data->inode = inode; |
1278 | data->cred = msg.rpc_cred; | 1358 | data->cred = first->wb_context->cred; |
1359 | data->lseg = lseg; /* reference transferred */ | ||
1360 | data->mds_ops = &nfs_commit_ops; | ||
1279 | 1361 | ||
1280 | data->args.fh = NFS_FH(data->inode); | 1362 | data->args.fh = NFS_FH(data->inode); |
1281 | /* Note: we always request a commit of the entire inode */ | 1363 | /* Note: we always request a commit of the entire inode */ |
@@ -1286,18 +1368,25 @@ static int nfs_commit_rpcsetup(struct list_head *head, | |||
1286 | data->res.fattr = &data->fattr; | 1368 | data->res.fattr = &data->fattr; |
1287 | data->res.verf = &data->verf; | 1369 | data->res.verf = &data->verf; |
1288 | nfs_fattr_init(&data->fattr); | 1370 | nfs_fattr_init(&data->fattr); |
1371 | } | ||
1372 | EXPORT_SYMBOL_GPL(nfs_init_commit); | ||
1289 | 1373 | ||
1290 | /* Set up the initial task struct. */ | 1374 | void nfs_retry_commit(struct list_head *page_list, |
1291 | NFS_PROTO(inode)->commit_setup(data, &msg); | 1375 | struct pnfs_layout_segment *lseg) |
1292 | 1376 | { | |
1293 | dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); | 1377 | struct nfs_page *req; |
1294 | 1378 | ||
1295 | task = rpc_run_task(&task_setup_data); | 1379 | while (!list_empty(page_list)) { |
1296 | if (IS_ERR(task)) | 1380 | req = nfs_list_entry(page_list->next); |
1297 | return PTR_ERR(task); | 1381 | nfs_list_remove_request(req); |
1298 | rpc_put_task(task); | 1382 | nfs_mark_request_commit(req, lseg); |
1299 | return 0; | 1383 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); |
1384 | dec_bdi_stat(req->wb_page->mapping->backing_dev_info, | ||
1385 | BDI_RECLAIMABLE); | ||
1386 | nfs_clear_page_tag_locked(req); | ||
1387 | } | ||
1300 | } | 1388 | } |
1389 | EXPORT_SYMBOL_GPL(nfs_retry_commit); | ||
1301 | 1390 | ||
1302 | /* | 1391 | /* |
1303 | * Commit dirty pages | 1392 | * Commit dirty pages |
@@ -1306,7 +1395,6 @@ static int | |||
1306 | nfs_commit_list(struct inode *inode, struct list_head *head, int how) | 1395 | nfs_commit_list(struct inode *inode, struct list_head *head, int how) |
1307 | { | 1396 | { |
1308 | struct nfs_write_data *data; | 1397 | struct nfs_write_data *data; |
1309 | struct nfs_page *req; | ||
1310 | 1398 | ||
1311 | data = nfs_commitdata_alloc(); | 1399 | data = nfs_commitdata_alloc(); |
1312 | 1400 | ||
@@ -1314,17 +1402,10 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how) | |||
1314 | goto out_bad; | 1402 | goto out_bad; |
1315 | 1403 | ||
1316 | /* Set up the argument struct */ | 1404 | /* Set up the argument struct */ |
1317 | return nfs_commit_rpcsetup(head, data, how); | 1405 | nfs_init_commit(data, head, NULL); |
1406 | return nfs_initiate_commit(data, NFS_CLIENT(inode), data->mds_ops, how); | ||
1318 | out_bad: | 1407 | out_bad: |
1319 | while (!list_empty(head)) { | 1408 | nfs_retry_commit(head, NULL); |
1320 | req = nfs_list_entry(head->next); | ||
1321 | nfs_list_remove_request(req); | ||
1322 | nfs_mark_request_commit(req); | ||
1323 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | ||
1324 | dec_bdi_stat(req->wb_page->mapping->backing_dev_info, | ||
1325 | BDI_RECLAIMABLE); | ||
1326 | nfs_clear_page_tag_locked(req); | ||
1327 | } | ||
1328 | nfs_commit_clear_lock(NFS_I(inode)); | 1409 | nfs_commit_clear_lock(NFS_I(inode)); |
1329 | return -ENOMEM; | 1410 | return -ENOMEM; |
1330 | } | 1411 | } |
@@ -1340,14 +1421,12 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata) | |||
1340 | task->tk_pid, task->tk_status); | 1421 | task->tk_pid, task->tk_status); |
1341 | 1422 | ||
1342 | /* Call the NFS version-specific code */ | 1423 | /* Call the NFS version-specific code */ |
1343 | if (NFS_PROTO(data->inode)->commit_done(task, data) != 0) | 1424 | NFS_PROTO(data->inode)->commit_done(task, data); |
1344 | return; | ||
1345 | } | 1425 | } |
1346 | 1426 | ||
1347 | static void nfs_commit_release(void *calldata) | 1427 | void nfs_commit_release_pages(struct nfs_write_data *data) |
1348 | { | 1428 | { |
1349 | struct nfs_write_data *data = calldata; | 1429 | struct nfs_page *req; |
1350 | struct nfs_page *req; | ||
1351 | int status = data->task.tk_status; | 1430 | int status = data->task.tk_status; |
1352 | 1431 | ||
1353 | while (!list_empty(&data->pages)) { | 1432 | while (!list_empty(&data->pages)) { |
@@ -1381,6 +1460,14 @@ static void nfs_commit_release(void *calldata) | |||
1381 | next: | 1460 | next: |
1382 | nfs_clear_page_tag_locked(req); | 1461 | nfs_clear_page_tag_locked(req); |
1383 | } | 1462 | } |
1463 | } | ||
1464 | EXPORT_SYMBOL_GPL(nfs_commit_release_pages); | ||
1465 | |||
1466 | static void nfs_commit_release(void *calldata) | ||
1467 | { | ||
1468 | struct nfs_write_data *data = calldata; | ||
1469 | |||
1470 | nfs_commit_release_pages(data); | ||
1384 | nfs_commit_clear_lock(NFS_I(data->inode)); | 1471 | nfs_commit_clear_lock(NFS_I(data->inode)); |
1385 | nfs_commitdata_release(calldata); | 1472 | nfs_commitdata_release(calldata); |
1386 | } | 1473 | } |
@@ -1397,23 +1484,28 @@ int nfs_commit_inode(struct inode *inode, int how) | |||
1397 | { | 1484 | { |
1398 | LIST_HEAD(head); | 1485 | LIST_HEAD(head); |
1399 | int may_wait = how & FLUSH_SYNC; | 1486 | int may_wait = how & FLUSH_SYNC; |
1400 | int res = 0; | 1487 | int res; |
1401 | 1488 | ||
1402 | if (!nfs_commit_set_lock(NFS_I(inode), may_wait)) | 1489 | res = nfs_commit_set_lock(NFS_I(inode), may_wait); |
1490 | if (res <= 0) | ||
1403 | goto out_mark_dirty; | 1491 | goto out_mark_dirty; |
1404 | spin_lock(&inode->i_lock); | ||
1405 | res = nfs_scan_commit(inode, &head, 0, 0); | 1492 | res = nfs_scan_commit(inode, &head, 0, 0); |
1406 | spin_unlock(&inode->i_lock); | ||
1407 | if (res) { | 1493 | if (res) { |
1408 | int error = nfs_commit_list(inode, &head, how); | 1494 | int error; |
1495 | |||
1496 | error = pnfs_commit_list(inode, &head, how); | ||
1497 | if (error == PNFS_NOT_ATTEMPTED) | ||
1498 | error = nfs_commit_list(inode, &head, how); | ||
1409 | if (error < 0) | 1499 | if (error < 0) |
1410 | return error; | 1500 | return error; |
1411 | if (may_wait) | 1501 | if (!may_wait) |
1412 | wait_on_bit(&NFS_I(inode)->flags, NFS_INO_COMMIT, | ||
1413 | nfs_wait_bit_killable, | ||
1414 | TASK_KILLABLE); | ||
1415 | else | ||
1416 | goto out_mark_dirty; | 1502 | goto out_mark_dirty; |
1503 | error = wait_on_bit(&NFS_I(inode)->flags, | ||
1504 | NFS_INO_COMMIT, | ||
1505 | nfs_wait_bit_killable, | ||
1506 | TASK_KILLABLE); | ||
1507 | if (error < 0) | ||
1508 | return error; | ||
1417 | } else | 1509 | } else |
1418 | nfs_commit_clear_lock(NFS_I(inode)); | 1510 | nfs_commit_clear_lock(NFS_I(inode)); |
1419 | return res; | 1511 | return res; |
@@ -1433,15 +1525,17 @@ static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_contr | |||
1433 | int flags = FLUSH_SYNC; | 1525 | int flags = FLUSH_SYNC; |
1434 | int ret = 0; | 1526 | int ret = 0; |
1435 | 1527 | ||
1436 | /* Don't commit yet if this is a non-blocking flush and there are | 1528 | if (wbc->sync_mode == WB_SYNC_NONE) { |
1437 | * lots of outstanding writes for this mapping. | 1529 | /* Don't commit yet if this is a non-blocking flush and there |
1438 | */ | 1530 | * are a lot of outstanding writes for this mapping. |
1439 | if (wbc->sync_mode == WB_SYNC_NONE && | 1531 | */ |
1440 | nfsi->ncommit <= (nfsi->npages >> 1)) | 1532 | if (nfsi->ncommit <= (nfsi->npages >> 1)) |
1441 | goto out_mark_dirty; | 1533 | goto out_mark_dirty; |
1442 | 1534 | ||
1443 | if (wbc->nonblocking || wbc->for_background) | 1535 | /* don't wait for the COMMIT response */ |
1444 | flags = 0; | 1536 | flags = 0; |
1537 | } | ||
1538 | |||
1445 | ret = nfs_commit_inode(inode, flags); | 1539 | ret = nfs_commit_inode(inode, flags); |
1446 | if (ret >= 0) { | 1540 | if (ret >= 0) { |
1447 | if (wbc->sync_mode == WB_SYNC_NONE) { | 1541 | if (wbc->sync_mode == WB_SYNC_NONE) { |
@@ -1465,7 +1559,22 @@ static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_contr | |||
1465 | 1559 | ||
1466 | int nfs_write_inode(struct inode *inode, struct writeback_control *wbc) | 1560 | int nfs_write_inode(struct inode *inode, struct writeback_control *wbc) |
1467 | { | 1561 | { |
1468 | return nfs_commit_unstable_pages(inode, wbc); | 1562 | int ret; |
1563 | |||
1564 | ret = nfs_commit_unstable_pages(inode, wbc); | ||
1565 | if (ret >= 0 && test_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags)) { | ||
1566 | int status; | ||
1567 | bool sync = true; | ||
1568 | |||
1569 | if (wbc->sync_mode == WB_SYNC_NONE || wbc->nonblocking || | ||
1570 | wbc->for_background) | ||
1571 | sync = false; | ||
1572 | |||
1573 | status = pnfs_layoutcommit_inode(inode, sync); | ||
1574 | if (status < 0) | ||
1575 | return status; | ||
1576 | } | ||
1577 | return ret; | ||
1469 | } | 1578 | } |
1470 | 1579 | ||
1471 | /* | 1580 | /* |