diff options
Diffstat (limited to 'fs/nfs/write.c')
| -rw-r--r-- | fs/nfs/write.c | 307 |
1 files changed, 147 insertions, 160 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index f333848fd3be..feca8c648766 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
| @@ -34,9 +34,6 @@ | |||
| 34 | /* | 34 | /* |
| 35 | * Local function declarations | 35 | * Local function declarations |
| 36 | */ | 36 | */ |
| 37 | static struct nfs_page * nfs_update_request(struct nfs_open_context*, | ||
| 38 | struct page *, | ||
| 39 | unsigned int, unsigned int); | ||
| 40 | static void nfs_pageio_init_write(struct nfs_pageio_descriptor *desc, | 37 | static void nfs_pageio_init_write(struct nfs_pageio_descriptor *desc, |
| 41 | struct inode *inode, int ioflags); | 38 | struct inode *inode, int ioflags); |
| 42 | static void nfs_redirty_request(struct nfs_page *req); | 39 | static void nfs_redirty_request(struct nfs_page *req); |
| @@ -169,29 +166,6 @@ static void nfs_mark_uptodate(struct page *page, unsigned int base, unsigned int | |||
| 169 | SetPageUptodate(page); | 166 | SetPageUptodate(page); |
| 170 | } | 167 | } |
| 171 | 168 | ||
| 172 | static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page, | ||
| 173 | unsigned int offset, unsigned int count) | ||
| 174 | { | ||
| 175 | struct nfs_page *req; | ||
| 176 | int ret; | ||
| 177 | |||
| 178 | for (;;) { | ||
| 179 | req = nfs_update_request(ctx, page, offset, count); | ||
| 180 | if (!IS_ERR(req)) | ||
| 181 | break; | ||
| 182 | ret = PTR_ERR(req); | ||
| 183 | if (ret != -EBUSY) | ||
| 184 | return ret; | ||
| 185 | ret = nfs_wb_page(page->mapping->host, page); | ||
| 186 | if (ret != 0) | ||
| 187 | return ret; | ||
| 188 | } | ||
| 189 | /* Update file length */ | ||
| 190 | nfs_grow_file(page, offset, count); | ||
| 191 | nfs_clear_page_tag_locked(req); | ||
| 192 | return 0; | ||
| 193 | } | ||
| 194 | |||
| 195 | static int wb_priority(struct writeback_control *wbc) | 169 | static int wb_priority(struct writeback_control *wbc) |
| 196 | { | 170 | { |
| 197 | if (wbc->for_reclaim) | 171 | if (wbc->for_reclaim) |
| @@ -268,12 +242,9 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | |||
| 268 | return ret; | 242 | return ret; |
| 269 | spin_lock(&inode->i_lock); | 243 | spin_lock(&inode->i_lock); |
| 270 | } | 244 | } |
| 271 | if (test_bit(PG_NEED_COMMIT, &req->wb_flags)) { | 245 | if (test_bit(PG_CLEAN, &req->wb_flags)) { |
| 272 | /* This request is marked for commit */ | ||
| 273 | spin_unlock(&inode->i_lock); | 246 | spin_unlock(&inode->i_lock); |
| 274 | nfs_clear_page_tag_locked(req); | 247 | BUG(); |
| 275 | nfs_pageio_complete(pgio); | ||
| 276 | return 0; | ||
| 277 | } | 248 | } |
| 278 | if (nfs_set_page_writeback(page) != 0) { | 249 | if (nfs_set_page_writeback(page) != 0) { |
| 279 | spin_unlock(&inode->i_lock); | 250 | spin_unlock(&inode->i_lock); |
| @@ -355,11 +326,19 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) | |||
| 355 | /* | 326 | /* |
| 356 | * Insert a write request into an inode | 327 | * Insert a write request into an inode |
| 357 | */ | 328 | */ |
| 358 | static void nfs_inode_add_request(struct inode *inode, struct nfs_page *req) | 329 | static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req) |
| 359 | { | 330 | { |
| 360 | struct nfs_inode *nfsi = NFS_I(inode); | 331 | struct nfs_inode *nfsi = NFS_I(inode); |
| 361 | int error; | 332 | int error; |
| 362 | 333 | ||
| 334 | error = radix_tree_preload(GFP_NOFS); | ||
| 335 | if (error != 0) | ||
| 336 | goto out; | ||
| 337 | |||
| 338 | /* Lock the request! */ | ||
| 339 | nfs_lock_request_dontget(req); | ||
| 340 | |||
| 341 | spin_lock(&inode->i_lock); | ||
| 363 | error = radix_tree_insert(&nfsi->nfs_page_tree, req->wb_index, req); | 342 | error = radix_tree_insert(&nfsi->nfs_page_tree, req->wb_index, req); |
| 364 | BUG_ON(error); | 343 | BUG_ON(error); |
| 365 | if (!nfsi->npages) { | 344 | if (!nfsi->npages) { |
| @@ -373,6 +352,10 @@ static void nfs_inode_add_request(struct inode *inode, struct nfs_page *req) | |||
| 373 | kref_get(&req->wb_kref); | 352 | kref_get(&req->wb_kref); |
| 374 | radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, | 353 | radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, |
| 375 | NFS_PAGE_TAG_LOCKED); | 354 | NFS_PAGE_TAG_LOCKED); |
| 355 | spin_unlock(&inode->i_lock); | ||
| 356 | radix_tree_preload_end(); | ||
| 357 | out: | ||
| 358 | return error; | ||
| 376 | } | 359 | } |
| 377 | 360 | ||
| 378 | /* | 361 | /* |
| @@ -405,19 +388,6 @@ nfs_mark_request_dirty(struct nfs_page *req) | |||
| 405 | __set_page_dirty_nobuffers(req->wb_page); | 388 | __set_page_dirty_nobuffers(req->wb_page); |
| 406 | } | 389 | } |
| 407 | 390 | ||
| 408 | /* | ||
| 409 | * Check if a request is dirty | ||
| 410 | */ | ||
| 411 | static inline int | ||
| 412 | nfs_dirty_request(struct nfs_page *req) | ||
| 413 | { | ||
| 414 | struct page *page = req->wb_page; | ||
| 415 | |||
| 416 | if (page == NULL || test_bit(PG_NEED_COMMIT, &req->wb_flags)) | ||
| 417 | return 0; | ||
| 418 | return !PageWriteback(page); | ||
| 419 | } | ||
| 420 | |||
| 421 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) | 391 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) |
| 422 | /* | 392 | /* |
| 423 | * Add a request to the inode's commit list. | 393 | * Add a request to the inode's commit list. |
| @@ -430,7 +400,7 @@ nfs_mark_request_commit(struct nfs_page *req) | |||
| 430 | 400 | ||
| 431 | spin_lock(&inode->i_lock); | 401 | spin_lock(&inode->i_lock); |
| 432 | nfsi->ncommit++; | 402 | nfsi->ncommit++; |
| 433 | set_bit(PG_NEED_COMMIT, &(req)->wb_flags); | 403 | set_bit(PG_CLEAN, &(req)->wb_flags); |
| 434 | radix_tree_tag_set(&nfsi->nfs_page_tree, | 404 | radix_tree_tag_set(&nfsi->nfs_page_tree, |
| 435 | req->wb_index, | 405 | req->wb_index, |
| 436 | NFS_PAGE_TAG_COMMIT); | 406 | NFS_PAGE_TAG_COMMIT); |
| @@ -440,6 +410,19 @@ nfs_mark_request_commit(struct nfs_page *req) | |||
| 440 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); | 410 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); |
| 441 | } | 411 | } |
| 442 | 412 | ||
| 413 | static int | ||
| 414 | nfs_clear_request_commit(struct nfs_page *req) | ||
| 415 | { | ||
| 416 | struct page *page = req->wb_page; | ||
| 417 | |||
| 418 | if (test_and_clear_bit(PG_CLEAN, &(req)->wb_flags)) { | ||
| 419 | dec_zone_page_state(page, NR_UNSTABLE_NFS); | ||
| 420 | dec_bdi_stat(page->mapping->backing_dev_info, BDI_RECLAIMABLE); | ||
| 421 | return 1; | ||
| 422 | } | ||
| 423 | return 0; | ||
| 424 | } | ||
| 425 | |||
| 443 | static inline | 426 | static inline |
| 444 | int nfs_write_need_commit(struct nfs_write_data *data) | 427 | int nfs_write_need_commit(struct nfs_write_data *data) |
| 445 | { | 428 | { |
| @@ -449,7 +432,7 @@ int nfs_write_need_commit(struct nfs_write_data *data) | |||
| 449 | static inline | 432 | static inline |
| 450 | int nfs_reschedule_unstable_write(struct nfs_page *req) | 433 | int nfs_reschedule_unstable_write(struct nfs_page *req) |
| 451 | { | 434 | { |
| 452 | if (test_bit(PG_NEED_COMMIT, &req->wb_flags)) { | 435 | if (test_and_clear_bit(PG_NEED_COMMIT, &req->wb_flags)) { |
| 453 | nfs_mark_request_commit(req); | 436 | nfs_mark_request_commit(req); |
| 454 | return 1; | 437 | return 1; |
| 455 | } | 438 | } |
| @@ -465,6 +448,12 @@ nfs_mark_request_commit(struct nfs_page *req) | |||
| 465 | { | 448 | { |
| 466 | } | 449 | } |
| 467 | 450 | ||
| 451 | static inline int | ||
| 452 | nfs_clear_request_commit(struct nfs_page *req) | ||
| 453 | { | ||
| 454 | return 0; | ||
| 455 | } | ||
| 456 | |||
| 468 | static inline | 457 | static inline |
| 469 | int nfs_write_need_commit(struct nfs_write_data *data) | 458 | int nfs_write_need_commit(struct nfs_write_data *data) |
| 470 | { | 459 | { |
| @@ -522,11 +511,8 @@ static void nfs_cancel_commit_list(struct list_head *head) | |||
| 522 | 511 | ||
| 523 | while(!list_empty(head)) { | 512 | while(!list_empty(head)) { |
| 524 | req = nfs_list_entry(head->next); | 513 | req = nfs_list_entry(head->next); |
| 525 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | ||
| 526 | dec_bdi_stat(req->wb_page->mapping->backing_dev_info, | ||
| 527 | BDI_RECLAIMABLE); | ||
| 528 | nfs_list_remove_request(req); | 514 | nfs_list_remove_request(req); |
| 529 | clear_bit(PG_NEED_COMMIT, &(req)->wb_flags); | 515 | nfs_clear_request_commit(req); |
| 530 | nfs_inode_remove_request(req); | 516 | nfs_inode_remove_request(req); |
| 531 | nfs_unlock_request(req); | 517 | nfs_unlock_request(req); |
| 532 | } | 518 | } |
| @@ -564,110 +550,124 @@ static inline int nfs_scan_commit(struct inode *inode, struct list_head *dst, pg | |||
| 564 | #endif | 550 | #endif |
| 565 | 551 | ||
| 566 | /* | 552 | /* |
| 567 | * Try to update any existing write request, or create one if there is none. | 553 | * Search for an existing write request, and attempt to update |
| 568 | * In order to match, the request's credentials must match those of | 554 | * it to reflect a new dirty region on a given page. |
| 569 | * the calling process. | ||
| 570 | * | 555 | * |
| 571 | * Note: Should always be called with the Page Lock held! | 556 | * If the attempt fails, then the existing request is flushed out |
| 557 | * to disk. | ||
| 572 | */ | 558 | */ |
| 573 | static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx, | 559 | static struct nfs_page *nfs_try_to_update_request(struct inode *inode, |
| 574 | struct page *page, unsigned int offset, unsigned int bytes) | 560 | struct page *page, |
| 561 | unsigned int offset, | ||
| 562 | unsigned int bytes) | ||
| 575 | { | 563 | { |
| 576 | struct address_space *mapping = page->mapping; | 564 | struct nfs_page *req; |
| 577 | struct inode *inode = mapping->host; | 565 | unsigned int rqend; |
| 578 | struct nfs_page *req, *new = NULL; | 566 | unsigned int end; |
| 579 | pgoff_t rqend, end; | 567 | int error; |
| 568 | |||
| 569 | if (!PagePrivate(page)) | ||
| 570 | return NULL; | ||
| 580 | 571 | ||
| 581 | end = offset + bytes; | 572 | end = offset + bytes; |
| 573 | spin_lock(&inode->i_lock); | ||
| 582 | 574 | ||
| 583 | for (;;) { | 575 | for (;;) { |
| 584 | /* Loop over all inode entries and see if we find | 576 | req = nfs_page_find_request_locked(page); |
| 585 | * A request for the page we wish to update | 577 | if (req == NULL) |
| 578 | goto out_unlock; | ||
| 579 | |||
| 580 | rqend = req->wb_offset + req->wb_bytes; | ||
| 581 | /* | ||
| 582 | * Tell the caller to flush out the request if | ||
| 583 | * the offsets are non-contiguous. | ||
| 584 | * Note: nfs_flush_incompatible() will already | ||
| 585 | * have flushed out requests having wrong owners. | ||
| 586 | */ | 586 | */ |
| 587 | if (new) { | 587 | if (offset > rqend |
| 588 | if (radix_tree_preload(GFP_NOFS)) { | 588 | || end < req->wb_offset) |
| 589 | nfs_release_request(new); | 589 | goto out_flushme; |
| 590 | return ERR_PTR(-ENOMEM); | ||
| 591 | } | ||
| 592 | } | ||
| 593 | 590 | ||
| 594 | spin_lock(&inode->i_lock); | 591 | if (nfs_set_page_tag_locked(req)) |
| 595 | req = nfs_page_find_request_locked(page); | ||
| 596 | if (req) { | ||
| 597 | if (!nfs_set_page_tag_locked(req)) { | ||
| 598 | int error; | ||
| 599 | |||
| 600 | spin_unlock(&inode->i_lock); | ||
| 601 | error = nfs_wait_on_request(req); | ||
| 602 | nfs_release_request(req); | ||
| 603 | if (error < 0) { | ||
| 604 | if (new) { | ||
| 605 | radix_tree_preload_end(); | ||
| 606 | nfs_release_request(new); | ||
| 607 | } | ||
| 608 | return ERR_PTR(error); | ||
| 609 | } | ||
| 610 | continue; | ||
| 611 | } | ||
| 612 | spin_unlock(&inode->i_lock); | ||
| 613 | if (new) { | ||
| 614 | radix_tree_preload_end(); | ||
| 615 | nfs_release_request(new); | ||
| 616 | } | ||
| 617 | break; | 592 | break; |
| 618 | } | ||
| 619 | 593 | ||
| 620 | if (new) { | 594 | /* The request is locked, so wait and then retry */ |
| 621 | nfs_lock_request_dontget(new); | ||
| 622 | nfs_inode_add_request(inode, new); | ||
| 623 | spin_unlock(&inode->i_lock); | ||
| 624 | radix_tree_preload_end(); | ||
| 625 | req = new; | ||
| 626 | goto zero_page; | ||
| 627 | } | ||
| 628 | spin_unlock(&inode->i_lock); | 595 | spin_unlock(&inode->i_lock); |
| 629 | 596 | error = nfs_wait_on_request(req); | |
| 630 | new = nfs_create_request(ctx, inode, page, offset, bytes); | 597 | nfs_release_request(req); |
| 631 | if (IS_ERR(new)) | 598 | if (error != 0) |
| 632 | return new; | 599 | goto out_err; |
| 600 | spin_lock(&inode->i_lock); | ||
| 633 | } | 601 | } |
| 634 | 602 | ||
| 635 | /* We have a request for our page. | 603 | if (nfs_clear_request_commit(req)) |
| 636 | * If the creds don't match, or the | 604 | radix_tree_tag_clear(&NFS_I(inode)->nfs_page_tree, |
| 637 | * page addresses don't match, | 605 | req->wb_index, NFS_PAGE_TAG_COMMIT); |
| 638 | * tell the caller to wait on the conflicting | ||
| 639 | * request. | ||
| 640 | */ | ||
| 641 | rqend = req->wb_offset + req->wb_bytes; | ||
| 642 | if (req->wb_context != ctx | ||
| 643 | || req->wb_page != page | ||
| 644 | || !nfs_dirty_request(req) | ||
| 645 | || offset > rqend || end < req->wb_offset) { | ||
| 646 | nfs_clear_page_tag_locked(req); | ||
| 647 | return ERR_PTR(-EBUSY); | ||
| 648 | } | ||
| 649 | 606 | ||
| 650 | /* Okay, the request matches. Update the region */ | 607 | /* Okay, the request matches. Update the region */ |
| 651 | if (offset < req->wb_offset) { | 608 | if (offset < req->wb_offset) { |
| 652 | req->wb_offset = offset; | 609 | req->wb_offset = offset; |
| 653 | req->wb_pgbase = offset; | 610 | req->wb_pgbase = offset; |
| 654 | req->wb_bytes = max(end, rqend) - req->wb_offset; | ||
| 655 | goto zero_page; | ||
| 656 | } | 611 | } |
| 657 | |||
| 658 | if (end > rqend) | 612 | if (end > rqend) |
| 659 | req->wb_bytes = end - req->wb_offset; | 613 | req->wb_bytes = end - req->wb_offset; |
| 660 | 614 | else | |
| 615 | req->wb_bytes = rqend - req->wb_offset; | ||
| 616 | out_unlock: | ||
| 617 | spin_unlock(&inode->i_lock); | ||
| 661 | return req; | 618 | return req; |
| 662 | zero_page: | 619 | out_flushme: |
| 663 | /* If this page might potentially be marked as up to date, | 620 | spin_unlock(&inode->i_lock); |
| 664 | * then we need to zero any uninitalised data. */ | 621 | nfs_release_request(req); |
| 665 | if (req->wb_pgbase == 0 && req->wb_bytes != PAGE_CACHE_SIZE | 622 | error = nfs_wb_page(inode, page); |
| 666 | && !PageUptodate(req->wb_page)) | 623 | out_err: |
| 667 | zero_user_segment(req->wb_page, req->wb_bytes, PAGE_CACHE_SIZE); | 624 | return ERR_PTR(error); |
| 625 | } | ||
| 626 | |||
| 627 | /* | ||
| 628 | * Try to update an existing write request, or create one if there is none. | ||
| 629 | * | ||
| 630 | * Note: Should always be called with the Page Lock held to prevent races | ||
| 631 | * if we have to add a new request. Also assumes that the caller has | ||
| 632 | * already called nfs_flush_incompatible() if necessary. | ||
| 633 | */ | ||
| 634 | static struct nfs_page * nfs_setup_write_request(struct nfs_open_context* ctx, | ||
| 635 | struct page *page, unsigned int offset, unsigned int bytes) | ||
| 636 | { | ||
| 637 | struct inode *inode = page->mapping->host; | ||
| 638 | struct nfs_page *req; | ||
| 639 | int error; | ||
| 640 | |||
| 641 | req = nfs_try_to_update_request(inode, page, offset, bytes); | ||
| 642 | if (req != NULL) | ||
| 643 | goto out; | ||
| 644 | req = nfs_create_request(ctx, inode, page, offset, bytes); | ||
| 645 | if (IS_ERR(req)) | ||
| 646 | goto out; | ||
| 647 | error = nfs_inode_add_request(inode, req); | ||
| 648 | if (error != 0) { | ||
| 649 | nfs_release_request(req); | ||
| 650 | req = ERR_PTR(error); | ||
| 651 | } | ||
| 652 | out: | ||
| 668 | return req; | 653 | return req; |
| 669 | } | 654 | } |
| 670 | 655 | ||
| 656 | static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page, | ||
| 657 | unsigned int offset, unsigned int count) | ||
| 658 | { | ||
| 659 | struct nfs_page *req; | ||
| 660 | |||
| 661 | req = nfs_setup_write_request(ctx, page, offset, count); | ||
| 662 | if (IS_ERR(req)) | ||
| 663 | return PTR_ERR(req); | ||
| 664 | /* Update file length */ | ||
| 665 | nfs_grow_file(page, offset, count); | ||
| 666 | nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes); | ||
| 667 | nfs_clear_page_tag_locked(req); | ||
| 668 | return 0; | ||
| 669 | } | ||
| 670 | |||
| 671 | int nfs_flush_incompatible(struct file *file, struct page *page) | 671 | int nfs_flush_incompatible(struct file *file, struct page *page) |
| 672 | { | 672 | { |
| 673 | struct nfs_open_context *ctx = nfs_file_open_context(file); | 673 | struct nfs_open_context *ctx = nfs_file_open_context(file); |
| @@ -685,8 +685,7 @@ int nfs_flush_incompatible(struct file *file, struct page *page) | |||
| 685 | req = nfs_page_find_request(page); | 685 | req = nfs_page_find_request(page); |
| 686 | if (req == NULL) | 686 | if (req == NULL) |
| 687 | return 0; | 687 | return 0; |
| 688 | do_flush = req->wb_page != page || req->wb_context != ctx | 688 | do_flush = req->wb_page != page || req->wb_context != ctx; |
| 689 | || !nfs_dirty_request(req); | ||
| 690 | nfs_release_request(req); | 689 | nfs_release_request(req); |
| 691 | if (!do_flush) | 690 | if (!do_flush) |
| 692 | return 0; | 691 | return 0; |
| @@ -721,10 +720,10 @@ int nfs_updatepage(struct file *file, struct page *page, | |||
| 721 | 720 | ||
| 722 | nfs_inc_stats(inode, NFSIOS_VFSUPDATEPAGE); | 721 | nfs_inc_stats(inode, NFSIOS_VFSUPDATEPAGE); |
| 723 | 722 | ||
| 724 | dprintk("NFS: nfs_updatepage(%s/%s %d@%Ld)\n", | 723 | dprintk("NFS: nfs_updatepage(%s/%s %d@%lld)\n", |
| 725 | file->f_path.dentry->d_parent->d_name.name, | 724 | file->f_path.dentry->d_parent->d_name.name, |
| 726 | file->f_path.dentry->d_name.name, count, | 725 | file->f_path.dentry->d_name.name, count, |
| 727 | (long long)(page_offset(page) +offset)); | 726 | (long long)(page_offset(page) + offset)); |
| 728 | 727 | ||
| 729 | /* If we're not using byte range locks, and we know the page | 728 | /* If we're not using byte range locks, and we know the page |
| 730 | * is up to date, it may be more efficient to extend the write | 729 | * is up to date, it may be more efficient to extend the write |
| @@ -744,7 +743,7 @@ int nfs_updatepage(struct file *file, struct page *page, | |||
| 744 | else | 743 | else |
| 745 | __set_page_dirty_nobuffers(page); | 744 | __set_page_dirty_nobuffers(page); |
| 746 | 745 | ||
| 747 | dprintk("NFS: nfs_updatepage returns %d (isize %Ld)\n", | 746 | dprintk("NFS: nfs_updatepage returns %d (isize %lld)\n", |
| 748 | status, (long long)i_size_read(inode)); | 747 | status, (long long)i_size_read(inode)); |
| 749 | return status; | 748 | return status; |
| 750 | } | 749 | } |
| @@ -752,12 +751,7 @@ int nfs_updatepage(struct file *file, struct page *page, | |||
| 752 | static void nfs_writepage_release(struct nfs_page *req) | 751 | static void nfs_writepage_release(struct nfs_page *req) |
| 753 | { | 752 | { |
| 754 | 753 | ||
| 755 | if (PageError(req->wb_page)) { | 754 | if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req)) { |
| 756 | nfs_end_page_writeback(req->wb_page); | ||
| 757 | nfs_inode_remove_request(req); | ||
| 758 | } else if (!nfs_reschedule_unstable_write(req)) { | ||
| 759 | /* Set the PG_uptodate flag */ | ||
| 760 | nfs_mark_uptodate(req->wb_page, req->wb_pgbase, req->wb_bytes); | ||
| 761 | nfs_end_page_writeback(req->wb_page); | 755 | nfs_end_page_writeback(req->wb_page); |
| 762 | nfs_inode_remove_request(req); | 756 | nfs_inode_remove_request(req); |
| 763 | } else | 757 | } else |
| @@ -834,7 +828,7 @@ static int nfs_write_rpcsetup(struct nfs_page *req, | |||
| 834 | NFS_PROTO(inode)->write_setup(data, &msg); | 828 | NFS_PROTO(inode)->write_setup(data, &msg); |
| 835 | 829 | ||
| 836 | dprintk("NFS: %5u initiated write call " | 830 | dprintk("NFS: %5u initiated write call " |
| 837 | "(req %s/%Ld, %u bytes @ offset %Lu)\n", | 831 | "(req %s/%lld, %u bytes @ offset %llu)\n", |
| 838 | data->task.tk_pid, | 832 | data->task.tk_pid, |
| 839 | inode->i_sb->s_id, | 833 | inode->i_sb->s_id, |
| 840 | (long long)NFS_FILEID(inode), | 834 | (long long)NFS_FILEID(inode), |
| @@ -978,13 +972,13 @@ static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, | |||
| 978 | static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata) | 972 | static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata) |
| 979 | { | 973 | { |
| 980 | struct nfs_write_data *data = calldata; | 974 | struct nfs_write_data *data = calldata; |
| 981 | struct nfs_page *req = data->req; | ||
| 982 | 975 | ||
| 983 | dprintk("NFS: write (%s/%Ld %d@%Ld)", | 976 | dprintk("NFS: %5u write(%s/%lld %d@%lld)", |
| 984 | req->wb_context->path.dentry->d_inode->i_sb->s_id, | 977 | task->tk_pid, |
| 985 | (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode), | 978 | data->req->wb_context->path.dentry->d_inode->i_sb->s_id, |
| 986 | req->wb_bytes, | 979 | (long long) |
| 987 | (long long)req_offset(req)); | 980 | NFS_FILEID(data->req->wb_context->path.dentry->d_inode), |
| 981 | data->req->wb_bytes, (long long)req_offset(data->req)); | ||
| 988 | 982 | ||
| 989 | nfs_writeback_done(task, data); | 983 | nfs_writeback_done(task, data); |
| 990 | } | 984 | } |
| @@ -1058,7 +1052,8 @@ static void nfs_writeback_release_full(void *calldata) | |||
| 1058 | 1052 | ||
| 1059 | nfs_list_remove_request(req); | 1053 | nfs_list_remove_request(req); |
| 1060 | 1054 | ||
| 1061 | dprintk("NFS: write (%s/%Ld %d@%Ld)", | 1055 | dprintk("NFS: %5u write (%s/%lld %d@%lld)", |
| 1056 | data->task.tk_pid, | ||
| 1062 | req->wb_context->path.dentry->d_inode->i_sb->s_id, | 1057 | req->wb_context->path.dentry->d_inode->i_sb->s_id, |
| 1063 | (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode), | 1058 | (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode), |
| 1064 | req->wb_bytes, | 1059 | req->wb_bytes, |
| @@ -1078,8 +1073,6 @@ static void nfs_writeback_release_full(void *calldata) | |||
| 1078 | dprintk(" marked for commit\n"); | 1073 | dprintk(" marked for commit\n"); |
| 1079 | goto next; | 1074 | goto next; |
| 1080 | } | 1075 | } |
| 1081 | /* Set the PG_uptodate flag? */ | ||
| 1082 | nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes); | ||
| 1083 | dprintk(" OK\n"); | 1076 | dprintk(" OK\n"); |
| 1084 | remove_request: | 1077 | remove_request: |
| 1085 | nfs_end_page_writeback(page); | 1078 | nfs_end_page_writeback(page); |
| @@ -1133,7 +1126,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) | |||
| 1133 | static unsigned long complain; | 1126 | static unsigned long complain; |
| 1134 | 1127 | ||
| 1135 | if (time_before(complain, jiffies)) { | 1128 | if (time_before(complain, jiffies)) { |
| 1136 | dprintk("NFS: faulty NFS server %s:" | 1129 | dprintk("NFS: faulty NFS server %s:" |
| 1137 | " (committed = %d) != (stable = %d)\n", | 1130 | " (committed = %d) != (stable = %d)\n", |
| 1138 | NFS_SERVER(data->inode)->nfs_client->cl_hostname, | 1131 | NFS_SERVER(data->inode)->nfs_client->cl_hostname, |
| 1139 | resp->verf->committed, argp->stable); | 1132 | resp->verf->committed, argp->stable); |
| @@ -1297,12 +1290,9 @@ static void nfs_commit_release(void *calldata) | |||
| 1297 | while (!list_empty(&data->pages)) { | 1290 | while (!list_empty(&data->pages)) { |
| 1298 | req = nfs_list_entry(data->pages.next); | 1291 | req = nfs_list_entry(data->pages.next); |
| 1299 | nfs_list_remove_request(req); | 1292 | nfs_list_remove_request(req); |
| 1300 | clear_bit(PG_NEED_COMMIT, &(req)->wb_flags); | 1293 | nfs_clear_request_commit(req); |
| 1301 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | ||
| 1302 | dec_bdi_stat(req->wb_page->mapping->backing_dev_info, | ||
| 1303 | BDI_RECLAIMABLE); | ||
| 1304 | 1294 | ||
| 1305 | dprintk("NFS: commit (%s/%Ld %d@%Ld)", | 1295 | dprintk("NFS: commit (%s/%lld %d@%lld)", |
| 1306 | req->wb_context->path.dentry->d_inode->i_sb->s_id, | 1296 | req->wb_context->path.dentry->d_inode->i_sb->s_id, |
| 1307 | (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode), | 1297 | (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode), |
| 1308 | req->wb_bytes, | 1298 | req->wb_bytes, |
| @@ -1318,9 +1308,6 @@ static void nfs_commit_release(void *calldata) | |||
| 1318 | * returned by the server against all stored verfs. */ | 1308 | * returned by the server against all stored verfs. */ |
| 1319 | if (!memcmp(req->wb_verf.verifier, data->verf.verifier, sizeof(data->verf.verifier))) { | 1309 | if (!memcmp(req->wb_verf.verifier, data->verf.verifier, sizeof(data->verf.verifier))) { |
| 1320 | /* We have a match */ | 1310 | /* We have a match */ |
| 1321 | /* Set the PG_uptodate flag */ | ||
| 1322 | nfs_mark_uptodate(req->wb_page, req->wb_pgbase, | ||
| 1323 | req->wb_bytes); | ||
| 1324 | nfs_inode_remove_request(req); | 1311 | nfs_inode_remove_request(req); |
| 1325 | dprintk(" OK\n"); | 1312 | dprintk(" OK\n"); |
| 1326 | goto next; | 1313 | goto next; |
| @@ -1479,7 +1466,7 @@ int nfs_wb_page_cancel(struct inode *inode, struct page *page) | |||
| 1479 | req = nfs_page_find_request(page); | 1466 | req = nfs_page_find_request(page); |
| 1480 | if (req == NULL) | 1467 | if (req == NULL) |
| 1481 | goto out; | 1468 | goto out; |
| 1482 | if (test_bit(PG_NEED_COMMIT, &req->wb_flags)) { | 1469 | if (test_bit(PG_CLEAN, &req->wb_flags)) { |
| 1483 | nfs_release_request(req); | 1470 | nfs_release_request(req); |
| 1484 | break; | 1471 | break; |
| 1485 | } | 1472 | } |
