diff options
Diffstat (limited to 'fs/nfs/write.c')
| -rw-r--r-- | fs/nfs/write.c | 149 |
1 files changed, 77 insertions, 72 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index af344a158e01..73ac992ece85 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
| @@ -117,19 +117,19 @@ static struct nfs_page *nfs_page_find_request_locked(struct page *page) | |||
| 117 | if (PagePrivate(page)) { | 117 | if (PagePrivate(page)) { |
| 118 | req = (struct nfs_page *)page_private(page); | 118 | req = (struct nfs_page *)page_private(page); |
| 119 | if (req != NULL) | 119 | if (req != NULL) |
| 120 | atomic_inc(&req->wb_count); | 120 | kref_get(&req->wb_kref); |
| 121 | } | 121 | } |
| 122 | return req; | 122 | return req; |
| 123 | } | 123 | } |
| 124 | 124 | ||
| 125 | static struct nfs_page *nfs_page_find_request(struct page *page) | 125 | static struct nfs_page *nfs_page_find_request(struct page *page) |
| 126 | { | 126 | { |
| 127 | struct inode *inode = page->mapping->host; | ||
| 127 | struct nfs_page *req = NULL; | 128 | struct nfs_page *req = NULL; |
| 128 | spinlock_t *req_lock = &NFS_I(page->mapping->host)->req_lock; | ||
| 129 | 129 | ||
| 130 | spin_lock(req_lock); | 130 | spin_lock(&inode->i_lock); |
| 131 | req = nfs_page_find_request_locked(page); | 131 | req = nfs_page_find_request_locked(page); |
| 132 | spin_unlock(req_lock); | 132 | spin_unlock(&inode->i_lock); |
| 133 | return req; | 133 | return req; |
| 134 | } | 134 | } |
| 135 | 135 | ||
| @@ -191,8 +191,6 @@ static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page, | |||
| 191 | } | 191 | } |
| 192 | /* Update file length */ | 192 | /* Update file length */ |
| 193 | nfs_grow_file(page, offset, count); | 193 | nfs_grow_file(page, offset, count); |
| 194 | /* Set the PG_uptodate flag? */ | ||
| 195 | nfs_mark_uptodate(page, offset, count); | ||
| 196 | nfs_unlock_request(req); | 194 | nfs_unlock_request(req); |
| 197 | return 0; | 195 | return 0; |
| 198 | } | 196 | } |
| @@ -253,16 +251,16 @@ static void nfs_end_page_writeback(struct page *page) | |||
| 253 | static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | 251 | static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, |
| 254 | struct page *page) | 252 | struct page *page) |
| 255 | { | 253 | { |
| 254 | struct inode *inode = page->mapping->host; | ||
| 255 | struct nfs_inode *nfsi = NFS_I(inode); | ||
| 256 | struct nfs_page *req; | 256 | struct nfs_page *req; |
| 257 | struct nfs_inode *nfsi = NFS_I(page->mapping->host); | ||
| 258 | spinlock_t *req_lock = &nfsi->req_lock; | ||
| 259 | int ret; | 257 | int ret; |
| 260 | 258 | ||
| 261 | spin_lock(req_lock); | 259 | spin_lock(&inode->i_lock); |
| 262 | for(;;) { | 260 | for(;;) { |
| 263 | req = nfs_page_find_request_locked(page); | 261 | req = nfs_page_find_request_locked(page); |
| 264 | if (req == NULL) { | 262 | if (req == NULL) { |
| 265 | spin_unlock(req_lock); | 263 | spin_unlock(&inode->i_lock); |
| 266 | return 1; | 264 | return 1; |
| 267 | } | 265 | } |
| 268 | if (nfs_lock_request_dontget(req)) | 266 | if (nfs_lock_request_dontget(req)) |
| @@ -272,28 +270,28 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | |||
| 272 | * succeed provided that someone hasn't already marked the | 270 | * succeed provided that someone hasn't already marked the |
| 273 | * request as dirty (in which case we don't care). | 271 | * request as dirty (in which case we don't care). |
| 274 | */ | 272 | */ |
| 275 | spin_unlock(req_lock); | 273 | spin_unlock(&inode->i_lock); |
| 276 | ret = nfs_wait_on_request(req); | 274 | ret = nfs_wait_on_request(req); |
| 277 | nfs_release_request(req); | 275 | nfs_release_request(req); |
| 278 | if (ret != 0) | 276 | if (ret != 0) |
| 279 | return ret; | 277 | return ret; |
| 280 | spin_lock(req_lock); | 278 | spin_lock(&inode->i_lock); |
| 281 | } | 279 | } |
| 282 | if (test_bit(PG_NEED_COMMIT, &req->wb_flags)) { | 280 | if (test_bit(PG_NEED_COMMIT, &req->wb_flags)) { |
| 283 | /* This request is marked for commit */ | 281 | /* This request is marked for commit */ |
| 284 | spin_unlock(req_lock); | 282 | spin_unlock(&inode->i_lock); |
| 285 | nfs_unlock_request(req); | 283 | nfs_unlock_request(req); |
| 286 | nfs_pageio_complete(pgio); | 284 | nfs_pageio_complete(pgio); |
| 287 | return 1; | 285 | return 1; |
| 288 | } | 286 | } |
| 289 | if (nfs_set_page_writeback(page) != 0) { | 287 | if (nfs_set_page_writeback(page) != 0) { |
| 290 | spin_unlock(req_lock); | 288 | spin_unlock(&inode->i_lock); |
| 291 | BUG(); | 289 | BUG(); |
| 292 | } | 290 | } |
| 293 | radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, | 291 | radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, |
| 294 | NFS_PAGE_TAG_WRITEBACK); | 292 | NFS_PAGE_TAG_LOCKED); |
| 295 | ret = test_bit(PG_NEED_FLUSH, &req->wb_flags); | 293 | ret = test_bit(PG_NEED_FLUSH, &req->wb_flags); |
| 296 | spin_unlock(req_lock); | 294 | spin_unlock(&inode->i_lock); |
| 297 | nfs_pageio_add_request(pgio, req); | 295 | nfs_pageio_add_request(pgio, req); |
| 298 | return ret; | 296 | return ret; |
| 299 | } | 297 | } |
| @@ -400,7 +398,7 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req) | |||
| 400 | if (PageDirty(req->wb_page)) | 398 | if (PageDirty(req->wb_page)) |
| 401 | set_bit(PG_NEED_FLUSH, &req->wb_flags); | 399 | set_bit(PG_NEED_FLUSH, &req->wb_flags); |
| 402 | nfsi->npages++; | 400 | nfsi->npages++; |
| 403 | atomic_inc(&req->wb_count); | 401 | kref_get(&req->wb_kref); |
| 404 | return 0; | 402 | return 0; |
| 405 | } | 403 | } |
| 406 | 404 | ||
| @@ -409,12 +407,12 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req) | |||
| 409 | */ | 407 | */ |
| 410 | static void nfs_inode_remove_request(struct nfs_page *req) | 408 | static void nfs_inode_remove_request(struct nfs_page *req) |
| 411 | { | 409 | { |
| 412 | struct inode *inode = req->wb_context->dentry->d_inode; | 410 | struct inode *inode = req->wb_context->path.dentry->d_inode; |
| 413 | struct nfs_inode *nfsi = NFS_I(inode); | 411 | struct nfs_inode *nfsi = NFS_I(inode); |
| 414 | 412 | ||
| 415 | BUG_ON (!NFS_WBACK_BUSY(req)); | 413 | BUG_ON (!NFS_WBACK_BUSY(req)); |
| 416 | 414 | ||
| 417 | spin_lock(&nfsi->req_lock); | 415 | spin_lock(&inode->i_lock); |
| 418 | set_page_private(req->wb_page, 0); | 416 | set_page_private(req->wb_page, 0); |
| 419 | ClearPagePrivate(req->wb_page); | 417 | ClearPagePrivate(req->wb_page); |
| 420 | radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index); | 418 | radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index); |
| @@ -422,11 +420,11 @@ static void nfs_inode_remove_request(struct nfs_page *req) | |||
| 422 | __set_page_dirty_nobuffers(req->wb_page); | 420 | __set_page_dirty_nobuffers(req->wb_page); |
| 423 | nfsi->npages--; | 421 | nfsi->npages--; |
| 424 | if (!nfsi->npages) { | 422 | if (!nfsi->npages) { |
| 425 | spin_unlock(&nfsi->req_lock); | 423 | spin_unlock(&inode->i_lock); |
| 426 | nfs_end_data_update(inode); | 424 | nfs_end_data_update(inode); |
| 427 | iput(inode); | 425 | iput(inode); |
| 428 | } else | 426 | } else |
| 429 | spin_unlock(&nfsi->req_lock); | 427 | spin_unlock(&inode->i_lock); |
| 430 | nfs_clear_request(req); | 428 | nfs_clear_request(req); |
| 431 | nfs_release_request(req); | 429 | nfs_release_request(req); |
| 432 | } | 430 | } |
| @@ -457,14 +455,16 @@ nfs_dirty_request(struct nfs_page *req) | |||
| 457 | static void | 455 | static void |
| 458 | nfs_mark_request_commit(struct nfs_page *req) | 456 | nfs_mark_request_commit(struct nfs_page *req) |
| 459 | { | 457 | { |
| 460 | struct inode *inode = req->wb_context->dentry->d_inode; | 458 | struct inode *inode = req->wb_context->path.dentry->d_inode; |
| 461 | struct nfs_inode *nfsi = NFS_I(inode); | 459 | struct nfs_inode *nfsi = NFS_I(inode); |
| 462 | 460 | ||
| 463 | spin_lock(&nfsi->req_lock); | 461 | spin_lock(&inode->i_lock); |
| 464 | nfs_list_add_request(req, &nfsi->commit); | ||
| 465 | nfsi->ncommit++; | 462 | nfsi->ncommit++; |
| 466 | set_bit(PG_NEED_COMMIT, &(req)->wb_flags); | 463 | set_bit(PG_NEED_COMMIT, &(req)->wb_flags); |
| 467 | spin_unlock(&nfsi->req_lock); | 464 | radix_tree_tag_set(&nfsi->nfs_page_tree, |
| 465 | req->wb_index, | ||
| 466 | NFS_PAGE_TAG_COMMIT); | ||
| 467 | spin_unlock(&inode->i_lock); | ||
| 468 | inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | 468 | inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); |
| 469 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); | 469 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); |
| 470 | } | 470 | } |
| @@ -526,18 +526,18 @@ static int nfs_wait_on_requests_locked(struct inode *inode, pgoff_t idx_start, u | |||
| 526 | idx_end = idx_start + npages - 1; | 526 | idx_end = idx_start + npages - 1; |
| 527 | 527 | ||
| 528 | next = idx_start; | 528 | next = idx_start; |
| 529 | while (radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, (void **)&req, next, 1, NFS_PAGE_TAG_WRITEBACK)) { | 529 | while (radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, (void **)&req, next, 1, NFS_PAGE_TAG_LOCKED)) { |
| 530 | if (req->wb_index > idx_end) | 530 | if (req->wb_index > idx_end) |
| 531 | break; | 531 | break; |
| 532 | 532 | ||
| 533 | next = req->wb_index + 1; | 533 | next = req->wb_index + 1; |
| 534 | BUG_ON(!NFS_WBACK_BUSY(req)); | 534 | BUG_ON(!NFS_WBACK_BUSY(req)); |
| 535 | 535 | ||
| 536 | atomic_inc(&req->wb_count); | 536 | kref_get(&req->wb_kref); |
| 537 | spin_unlock(&nfsi->req_lock); | 537 | spin_unlock(&inode->i_lock); |
| 538 | error = nfs_wait_on_request(req); | 538 | error = nfs_wait_on_request(req); |
| 539 | nfs_release_request(req); | 539 | nfs_release_request(req); |
| 540 | spin_lock(&nfsi->req_lock); | 540 | spin_lock(&inode->i_lock); |
| 541 | if (error < 0) | 541 | if (error < 0) |
| 542 | return error; | 542 | return error; |
| 543 | res++; | 543 | res++; |
| @@ -577,10 +577,9 @@ nfs_scan_commit(struct inode *inode, struct list_head *dst, pgoff_t idx_start, u | |||
| 577 | int res = 0; | 577 | int res = 0; |
| 578 | 578 | ||
| 579 | if (nfsi->ncommit != 0) { | 579 | if (nfsi->ncommit != 0) { |
| 580 | res = nfs_scan_list(nfsi, &nfsi->commit, dst, idx_start, npages); | 580 | res = nfs_scan_list(nfsi, dst, idx_start, npages, |
| 581 | NFS_PAGE_TAG_COMMIT); | ||
| 581 | nfsi->ncommit -= res; | 582 | nfsi->ncommit -= res; |
| 582 | if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit)) | ||
| 583 | printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n"); | ||
| 584 | } | 583 | } |
| 585 | return res; | 584 | return res; |
| 586 | } | 585 | } |
| @@ -603,7 +602,6 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx, | |||
| 603 | { | 602 | { |
| 604 | struct address_space *mapping = page->mapping; | 603 | struct address_space *mapping = page->mapping; |
| 605 | struct inode *inode = mapping->host; | 604 | struct inode *inode = mapping->host; |
| 606 | struct nfs_inode *nfsi = NFS_I(inode); | ||
| 607 | struct nfs_page *req, *new = NULL; | 605 | struct nfs_page *req, *new = NULL; |
| 608 | pgoff_t rqend, end; | 606 | pgoff_t rqend, end; |
| 609 | 607 | ||
| @@ -613,13 +611,13 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx, | |||
| 613 | /* Loop over all inode entries and see if we find | 611 | /* Loop over all inode entries and see if we find |
| 614 | * A request for the page we wish to update | 612 | * A request for the page we wish to update |
| 615 | */ | 613 | */ |
| 616 | spin_lock(&nfsi->req_lock); | 614 | spin_lock(&inode->i_lock); |
| 617 | req = nfs_page_find_request_locked(page); | 615 | req = nfs_page_find_request_locked(page); |
| 618 | if (req) { | 616 | if (req) { |
| 619 | if (!nfs_lock_request_dontget(req)) { | 617 | if (!nfs_lock_request_dontget(req)) { |
| 620 | int error; | 618 | int error; |
| 621 | 619 | ||
| 622 | spin_unlock(&nfsi->req_lock); | 620 | spin_unlock(&inode->i_lock); |
| 623 | error = nfs_wait_on_request(req); | 621 | error = nfs_wait_on_request(req); |
| 624 | nfs_release_request(req); | 622 | nfs_release_request(req); |
| 625 | if (error < 0) { | 623 | if (error < 0) { |
| @@ -629,7 +627,7 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx, | |||
| 629 | } | 627 | } |
| 630 | continue; | 628 | continue; |
| 631 | } | 629 | } |
| 632 | spin_unlock(&nfsi->req_lock); | 630 | spin_unlock(&inode->i_lock); |
| 633 | if (new) | 631 | if (new) |
| 634 | nfs_release_request(new); | 632 | nfs_release_request(new); |
| 635 | break; | 633 | break; |
| @@ -640,14 +638,14 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx, | |||
| 640 | nfs_lock_request_dontget(new); | 638 | nfs_lock_request_dontget(new); |
| 641 | error = nfs_inode_add_request(inode, new); | 639 | error = nfs_inode_add_request(inode, new); |
| 642 | if (error) { | 640 | if (error) { |
| 643 | spin_unlock(&nfsi->req_lock); | 641 | spin_unlock(&inode->i_lock); |
| 644 | nfs_unlock_request(new); | 642 | nfs_unlock_request(new); |
| 645 | return ERR_PTR(error); | 643 | return ERR_PTR(error); |
| 646 | } | 644 | } |
| 647 | spin_unlock(&nfsi->req_lock); | 645 | spin_unlock(&inode->i_lock); |
| 648 | return new; | 646 | return new; |
| 649 | } | 647 | } |
| 650 | spin_unlock(&nfsi->req_lock); | 648 | spin_unlock(&inode->i_lock); |
| 651 | 649 | ||
| 652 | new = nfs_create_request(ctx, inode, page, offset, bytes); | 650 | new = nfs_create_request(ctx, inode, page, offset, bytes); |
| 653 | if (IS_ERR(new)) | 651 | if (IS_ERR(new)) |
| @@ -751,12 +749,17 @@ int nfs_updatepage(struct file *file, struct page *page, | |||
| 751 | static void nfs_writepage_release(struct nfs_page *req) | 749 | static void nfs_writepage_release(struct nfs_page *req) |
| 752 | { | 750 | { |
| 753 | 751 | ||
| 754 | if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req)) { | 752 | if (PageError(req->wb_page)) { |
| 753 | nfs_end_page_writeback(req->wb_page); | ||
| 754 | nfs_inode_remove_request(req); | ||
| 755 | } else if (!nfs_reschedule_unstable_write(req)) { | ||
| 756 | /* Set the PG_uptodate flag */ | ||
| 757 | nfs_mark_uptodate(req->wb_page, req->wb_pgbase, req->wb_bytes); | ||
| 755 | nfs_end_page_writeback(req->wb_page); | 758 | nfs_end_page_writeback(req->wb_page); |
| 756 | nfs_inode_remove_request(req); | 759 | nfs_inode_remove_request(req); |
| 757 | } else | 760 | } else |
| 758 | nfs_end_page_writeback(req->wb_page); | 761 | nfs_end_page_writeback(req->wb_page); |
| 759 | nfs_clear_page_writeback(req); | 762 | nfs_clear_page_tag_locked(req); |
| 760 | } | 763 | } |
| 761 | 764 | ||
| 762 | static inline int flush_task_priority(int how) | 765 | static inline int flush_task_priority(int how) |
| @@ -786,7 +789,7 @@ static void nfs_write_rpcsetup(struct nfs_page *req, | |||
| 786 | * NB: take care not to mess about with data->commit et al. */ | 789 | * NB: take care not to mess about with data->commit et al. */ |
| 787 | 790 | ||
| 788 | data->req = req; | 791 | data->req = req; |
| 789 | data->inode = inode = req->wb_context->dentry->d_inode; | 792 | data->inode = inode = req->wb_context->path.dentry->d_inode; |
| 790 | data->cred = req->wb_context->cred; | 793 | data->cred = req->wb_context->cred; |
| 791 | 794 | ||
| 792 | data->args.fh = NFS_FH(inode); | 795 | data->args.fh = NFS_FH(inode); |
| @@ -885,7 +888,7 @@ out_bad: | |||
| 885 | } | 888 | } |
| 886 | nfs_redirty_request(req); | 889 | nfs_redirty_request(req); |
| 887 | nfs_end_page_writeback(req->wb_page); | 890 | nfs_end_page_writeback(req->wb_page); |
| 888 | nfs_clear_page_writeback(req); | 891 | nfs_clear_page_tag_locked(req); |
| 889 | return -ENOMEM; | 892 | return -ENOMEM; |
| 890 | } | 893 | } |
| 891 | 894 | ||
| @@ -928,7 +931,7 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned i | |||
| 928 | nfs_list_remove_request(req); | 931 | nfs_list_remove_request(req); |
| 929 | nfs_redirty_request(req); | 932 | nfs_redirty_request(req); |
| 930 | nfs_end_page_writeback(req->wb_page); | 933 | nfs_end_page_writeback(req->wb_page); |
| 931 | nfs_clear_page_writeback(req); | 934 | nfs_clear_page_tag_locked(req); |
| 932 | } | 935 | } |
| 933 | return -ENOMEM; | 936 | return -ENOMEM; |
| 934 | } | 937 | } |
| @@ -954,8 +957,8 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata) | |||
| 954 | struct page *page = req->wb_page; | 957 | struct page *page = req->wb_page; |
| 955 | 958 | ||
| 956 | dprintk("NFS: write (%s/%Ld %d@%Ld)", | 959 | dprintk("NFS: write (%s/%Ld %d@%Ld)", |
| 957 | req->wb_context->dentry->d_inode->i_sb->s_id, | 960 | req->wb_context->path.dentry->d_inode->i_sb->s_id, |
| 958 | (long long)NFS_FILEID(req->wb_context->dentry->d_inode), | 961 | (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode), |
| 959 | req->wb_bytes, | 962 | req->wb_bytes, |
| 960 | (long long)req_offset(req)); | 963 | (long long)req_offset(req)); |
| 961 | 964 | ||
| @@ -970,9 +973,9 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata) | |||
| 970 | } | 973 | } |
| 971 | 974 | ||
| 972 | if (nfs_write_need_commit(data)) { | 975 | if (nfs_write_need_commit(data)) { |
| 973 | spinlock_t *req_lock = &NFS_I(page->mapping->host)->req_lock; | 976 | struct inode *inode = page->mapping->host; |
| 974 | 977 | ||
| 975 | spin_lock(req_lock); | 978 | spin_lock(&inode->i_lock); |
| 976 | if (test_bit(PG_NEED_RESCHED, &req->wb_flags)) { | 979 | if (test_bit(PG_NEED_RESCHED, &req->wb_flags)) { |
| 977 | /* Do nothing we need to resend the writes */ | 980 | /* Do nothing we need to resend the writes */ |
| 978 | } else if (!test_and_set_bit(PG_NEED_COMMIT, &req->wb_flags)) { | 981 | } else if (!test_and_set_bit(PG_NEED_COMMIT, &req->wb_flags)) { |
| @@ -983,7 +986,7 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata) | |||
| 983 | clear_bit(PG_NEED_COMMIT, &req->wb_flags); | 986 | clear_bit(PG_NEED_COMMIT, &req->wb_flags); |
| 984 | dprintk(" server reboot detected\n"); | 987 | dprintk(" server reboot detected\n"); |
| 985 | } | 988 | } |
| 986 | spin_unlock(req_lock); | 989 | spin_unlock(&inode->i_lock); |
| 987 | } else | 990 | } else |
| 988 | dprintk(" OK\n"); | 991 | dprintk(" OK\n"); |
| 989 | 992 | ||
| @@ -1020,8 +1023,8 @@ static void nfs_writeback_done_full(struct rpc_task *task, void *calldata) | |||
| 1020 | page = req->wb_page; | 1023 | page = req->wb_page; |
| 1021 | 1024 | ||
| 1022 | dprintk("NFS: write (%s/%Ld %d@%Ld)", | 1025 | dprintk("NFS: write (%s/%Ld %d@%Ld)", |
| 1023 | req->wb_context->dentry->d_inode->i_sb->s_id, | 1026 | req->wb_context->path.dentry->d_inode->i_sb->s_id, |
| 1024 | (long long)NFS_FILEID(req->wb_context->dentry->d_inode), | 1027 | (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode), |
| 1025 | req->wb_bytes, | 1028 | req->wb_bytes, |
| 1026 | (long long)req_offset(req)); | 1029 | (long long)req_offset(req)); |
| 1027 | 1030 | ||
| @@ -1039,12 +1042,14 @@ static void nfs_writeback_done_full(struct rpc_task *task, void *calldata) | |||
| 1039 | dprintk(" marked for commit\n"); | 1042 | dprintk(" marked for commit\n"); |
| 1040 | goto next; | 1043 | goto next; |
| 1041 | } | 1044 | } |
| 1045 | /* Set the PG_uptodate flag? */ | ||
| 1046 | nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes); | ||
| 1042 | dprintk(" OK\n"); | 1047 | dprintk(" OK\n"); |
| 1043 | remove_request: | 1048 | remove_request: |
| 1044 | nfs_end_page_writeback(page); | 1049 | nfs_end_page_writeback(page); |
| 1045 | nfs_inode_remove_request(req); | 1050 | nfs_inode_remove_request(req); |
| 1046 | next: | 1051 | next: |
| 1047 | nfs_clear_page_writeback(req); | 1052 | nfs_clear_page_tag_locked(req); |
| 1048 | } | 1053 | } |
| 1049 | } | 1054 | } |
| 1050 | 1055 | ||
| @@ -1157,7 +1162,7 @@ static void nfs_commit_rpcsetup(struct list_head *head, | |||
| 1157 | 1162 | ||
| 1158 | list_splice_init(head, &data->pages); | 1163 | list_splice_init(head, &data->pages); |
| 1159 | first = nfs_list_entry(data->pages.next); | 1164 | first = nfs_list_entry(data->pages.next); |
| 1160 | inode = first->wb_context->dentry->d_inode; | 1165 | inode = first->wb_context->path.dentry->d_inode; |
| 1161 | 1166 | ||
| 1162 | data->inode = inode; | 1167 | data->inode = inode; |
| 1163 | data->cred = first->wb_context->cred; | 1168 | data->cred = first->wb_context->cred; |
| @@ -1207,7 +1212,7 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how) | |||
| 1207 | nfs_list_remove_request(req); | 1212 | nfs_list_remove_request(req); |
| 1208 | nfs_mark_request_commit(req); | 1213 | nfs_mark_request_commit(req); |
| 1209 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | 1214 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); |
| 1210 | nfs_clear_page_writeback(req); | 1215 | nfs_clear_page_tag_locked(req); |
| 1211 | } | 1216 | } |
| 1212 | return -ENOMEM; | 1217 | return -ENOMEM; |
| 1213 | } | 1218 | } |
| @@ -1234,8 +1239,8 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata) | |||
| 1234 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | 1239 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); |
| 1235 | 1240 | ||
| 1236 | dprintk("NFS: commit (%s/%Ld %d@%Ld)", | 1241 | dprintk("NFS: commit (%s/%Ld %d@%Ld)", |
| 1237 | req->wb_context->dentry->d_inode->i_sb->s_id, | 1242 | req->wb_context->path.dentry->d_inode->i_sb->s_id, |
| 1238 | (long long)NFS_FILEID(req->wb_context->dentry->d_inode), | 1243 | (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode), |
| 1239 | req->wb_bytes, | 1244 | req->wb_bytes, |
| 1240 | (long long)req_offset(req)); | 1245 | (long long)req_offset(req)); |
| 1241 | if (task->tk_status < 0) { | 1246 | if (task->tk_status < 0) { |
| @@ -1249,6 +1254,9 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata) | |||
| 1249 | * returned by the server against all stored verfs. */ | 1254 | * returned by the server against all stored verfs. */ |
| 1250 | if (!memcmp(req->wb_verf.verifier, data->verf.verifier, sizeof(data->verf.verifier))) { | 1255 | if (!memcmp(req->wb_verf.verifier, data->verf.verifier, sizeof(data->verf.verifier))) { |
| 1251 | /* We have a match */ | 1256 | /* We have a match */ |
| 1257 | /* Set the PG_uptodate flag */ | ||
| 1258 | nfs_mark_uptodate(req->wb_page, req->wb_pgbase, | ||
| 1259 | req->wb_bytes); | ||
| 1252 | nfs_inode_remove_request(req); | 1260 | nfs_inode_remove_request(req); |
| 1253 | dprintk(" OK\n"); | 1261 | dprintk(" OK\n"); |
| 1254 | goto next; | 1262 | goto next; |
| @@ -1257,7 +1265,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata) | |||
| 1257 | dprintk(" mismatch\n"); | 1265 | dprintk(" mismatch\n"); |
| 1258 | nfs_redirty_request(req); | 1266 | nfs_redirty_request(req); |
| 1259 | next: | 1267 | next: |
| 1260 | nfs_clear_page_writeback(req); | 1268 | nfs_clear_page_tag_locked(req); |
| 1261 | } | 1269 | } |
| 1262 | } | 1270 | } |
| 1263 | 1271 | ||
| @@ -1268,13 +1276,12 @@ static const struct rpc_call_ops nfs_commit_ops = { | |||
| 1268 | 1276 | ||
| 1269 | int nfs_commit_inode(struct inode *inode, int how) | 1277 | int nfs_commit_inode(struct inode *inode, int how) |
| 1270 | { | 1278 | { |
| 1271 | struct nfs_inode *nfsi = NFS_I(inode); | ||
| 1272 | LIST_HEAD(head); | 1279 | LIST_HEAD(head); |
| 1273 | int res; | 1280 | int res; |
| 1274 | 1281 | ||
| 1275 | spin_lock(&nfsi->req_lock); | 1282 | spin_lock(&inode->i_lock); |
| 1276 | res = nfs_scan_commit(inode, &head, 0, 0); | 1283 | res = nfs_scan_commit(inode, &head, 0, 0); |
| 1277 | spin_unlock(&nfsi->req_lock); | 1284 | spin_unlock(&inode->i_lock); |
| 1278 | if (res) { | 1285 | if (res) { |
| 1279 | int error = nfs_commit_list(inode, &head, how); | 1286 | int error = nfs_commit_list(inode, &head, how); |
| 1280 | if (error < 0) | 1287 | if (error < 0) |
| @@ -1292,7 +1299,6 @@ static inline int nfs_commit_list(struct inode *inode, struct list_head *head, i | |||
| 1292 | long nfs_sync_mapping_wait(struct address_space *mapping, struct writeback_control *wbc, int how) | 1299 | long nfs_sync_mapping_wait(struct address_space *mapping, struct writeback_control *wbc, int how) |
| 1293 | { | 1300 | { |
| 1294 | struct inode *inode = mapping->host; | 1301 | struct inode *inode = mapping->host; |
| 1295 | struct nfs_inode *nfsi = NFS_I(inode); | ||
| 1296 | pgoff_t idx_start, idx_end; | 1302 | pgoff_t idx_start, idx_end; |
| 1297 | unsigned int npages = 0; | 1303 | unsigned int npages = 0; |
| 1298 | LIST_HEAD(head); | 1304 | LIST_HEAD(head); |
| @@ -1314,7 +1320,7 @@ long nfs_sync_mapping_wait(struct address_space *mapping, struct writeback_contr | |||
| 1314 | } | 1320 | } |
| 1315 | } | 1321 | } |
| 1316 | how &= ~FLUSH_NOCOMMIT; | 1322 | how &= ~FLUSH_NOCOMMIT; |
| 1317 | spin_lock(&nfsi->req_lock); | 1323 | spin_lock(&inode->i_lock); |
| 1318 | do { | 1324 | do { |
| 1319 | ret = nfs_wait_on_requests_locked(inode, idx_start, npages); | 1325 | ret = nfs_wait_on_requests_locked(inode, idx_start, npages); |
| 1320 | if (ret != 0) | 1326 | if (ret != 0) |
| @@ -1325,18 +1331,19 @@ long nfs_sync_mapping_wait(struct address_space *mapping, struct writeback_contr | |||
| 1325 | if (pages == 0) | 1331 | if (pages == 0) |
| 1326 | break; | 1332 | break; |
| 1327 | if (how & FLUSH_INVALIDATE) { | 1333 | if (how & FLUSH_INVALIDATE) { |
| 1328 | spin_unlock(&nfsi->req_lock); | 1334 | spin_unlock(&inode->i_lock); |
| 1329 | nfs_cancel_commit_list(&head); | 1335 | nfs_cancel_commit_list(&head); |
| 1330 | ret = pages; | 1336 | ret = pages; |
| 1331 | spin_lock(&nfsi->req_lock); | 1337 | spin_lock(&inode->i_lock); |
| 1332 | continue; | 1338 | continue; |
| 1333 | } | 1339 | } |
| 1334 | pages += nfs_scan_commit(inode, &head, 0, 0); | 1340 | pages += nfs_scan_commit(inode, &head, 0, 0); |
| 1335 | spin_unlock(&nfsi->req_lock); | 1341 | spin_unlock(&inode->i_lock); |
| 1336 | ret = nfs_commit_list(inode, &head, how); | 1342 | ret = nfs_commit_list(inode, &head, how); |
| 1337 | spin_lock(&nfsi->req_lock); | 1343 | spin_lock(&inode->i_lock); |
| 1344 | |||
| 1338 | } while (ret >= 0); | 1345 | } while (ret >= 0); |
| 1339 | spin_unlock(&nfsi->req_lock); | 1346 | spin_unlock(&inode->i_lock); |
| 1340 | return ret; | 1347 | return ret; |
| 1341 | } | 1348 | } |
| 1342 | 1349 | ||
| @@ -1430,7 +1437,6 @@ int nfs_set_page_dirty(struct page *page) | |||
| 1430 | { | 1437 | { |
| 1431 | struct address_space *mapping = page->mapping; | 1438 | struct address_space *mapping = page->mapping; |
| 1432 | struct inode *inode; | 1439 | struct inode *inode; |
| 1433 | spinlock_t *req_lock; | ||
| 1434 | struct nfs_page *req; | 1440 | struct nfs_page *req; |
| 1435 | int ret; | 1441 | int ret; |
| 1436 | 1442 | ||
| @@ -1439,18 +1445,17 @@ int nfs_set_page_dirty(struct page *page) | |||
| 1439 | inode = mapping->host; | 1445 | inode = mapping->host; |
| 1440 | if (!inode) | 1446 | if (!inode) |
| 1441 | goto out_raced; | 1447 | goto out_raced; |
| 1442 | req_lock = &NFS_I(inode)->req_lock; | 1448 | spin_lock(&inode->i_lock); |
| 1443 | spin_lock(req_lock); | ||
| 1444 | req = nfs_page_find_request_locked(page); | 1449 | req = nfs_page_find_request_locked(page); |
| 1445 | if (req != NULL) { | 1450 | if (req != NULL) { |
| 1446 | /* Mark any existing write requests for flushing */ | 1451 | /* Mark any existing write requests for flushing */ |
| 1447 | ret = !test_and_set_bit(PG_NEED_FLUSH, &req->wb_flags); | 1452 | ret = !test_and_set_bit(PG_NEED_FLUSH, &req->wb_flags); |
| 1448 | spin_unlock(req_lock); | 1453 | spin_unlock(&inode->i_lock); |
| 1449 | nfs_release_request(req); | 1454 | nfs_release_request(req); |
| 1450 | return ret; | 1455 | return ret; |
| 1451 | } | 1456 | } |
| 1452 | ret = __set_page_dirty_nobuffers(page); | 1457 | ret = __set_page_dirty_nobuffers(page); |
| 1453 | spin_unlock(req_lock); | 1458 | spin_unlock(&inode->i_lock); |
| 1454 | return ret; | 1459 | return ret; |
| 1455 | out_raced: | 1460 | out_raced: |
| 1456 | return !TestSetPageDirty(page); | 1461 | return !TestSetPageDirty(page); |
