diff options
author | Fred Isaman <iisaman@netapp.com> | 2012-03-08 17:29:35 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-03-10 17:14:10 -0500 |
commit | d6d6dc7cdfda7c8f49a89a7b7261846f319da6d1 (patch) | |
tree | fd26cf912b676f2752c16ccce1f410872a2a485c /fs/nfs/write.c | |
parent | 9994b62b5621f88828d442fcd03fe3ce4c43344b (diff) |
NFS: remove nfs_inode radix tree
The radix tree is only being used to compile lists of reqs needing commit.
It is simpler to just put the reqs directly into a list.
Signed-off-by: Fred Isaman <iisaman@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r-- | fs/nfs/write.c | 120 |
1 files changed, 67 insertions, 53 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index fd8a4f07bc0c..a630ad65d64c 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -375,21 +375,14 @@ out_err: | |||
375 | /* | 375 | /* |
376 | * Insert a write request into an inode | 376 | * Insert a write request into an inode |
377 | */ | 377 | */ |
378 | static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req) | 378 | static void nfs_inode_add_request(struct inode *inode, struct nfs_page *req) |
379 | { | 379 | { |
380 | struct nfs_inode *nfsi = NFS_I(inode); | 380 | struct nfs_inode *nfsi = NFS_I(inode); |
381 | int error; | ||
382 | |||
383 | error = radix_tree_preload(GFP_NOFS); | ||
384 | if (error != 0) | ||
385 | goto out; | ||
386 | 381 | ||
387 | /* Lock the request! */ | 382 | /* Lock the request! */ |
388 | nfs_lock_request_dontget(req); | 383 | nfs_lock_request_dontget(req); |
389 | 384 | ||
390 | spin_lock(&inode->i_lock); | 385 | spin_lock(&inode->i_lock); |
391 | error = radix_tree_insert(&nfsi->nfs_page_tree, req->wb_index, req); | ||
392 | BUG_ON(error); | ||
393 | if (!nfsi->npages && nfs_have_delegation(inode, FMODE_WRITE)) | 386 | if (!nfsi->npages && nfs_have_delegation(inode, FMODE_WRITE)) |
394 | inode->i_version++; | 387 | inode->i_version++; |
395 | set_bit(PG_MAPPED, &req->wb_flags); | 388 | set_bit(PG_MAPPED, &req->wb_flags); |
@@ -398,11 +391,10 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req) | |||
398 | nfsi->npages++; | 391 | nfsi->npages++; |
399 | kref_get(&req->wb_kref); | 392 | kref_get(&req->wb_kref); |
400 | spin_unlock(&inode->i_lock); | 393 | spin_unlock(&inode->i_lock); |
401 | radix_tree_preload_end(); | ||
402 | out: | ||
403 | return error; | ||
404 | } | 394 | } |
405 | 395 | ||
396 | static struct pnfs_layout_segment *nfs_clear_request_commit(struct nfs_page *req); | ||
397 | |||
406 | /* | 398 | /* |
407 | * Remove a write request from an inode | 399 | * Remove a write request from an inode |
408 | */ | 400 | */ |
@@ -410,16 +402,18 @@ static void nfs_inode_remove_request(struct nfs_page *req) | |||
410 | { | 402 | { |
411 | struct inode *inode = req->wb_context->dentry->d_inode; | 403 | struct inode *inode = req->wb_context->dentry->d_inode; |
412 | struct nfs_inode *nfsi = NFS_I(inode); | 404 | struct nfs_inode *nfsi = NFS_I(inode); |
405 | struct pnfs_layout_segment *lseg; | ||
413 | 406 | ||
414 | BUG_ON (!NFS_WBACK_BUSY(req)); | 407 | BUG_ON (!NFS_WBACK_BUSY(req)); |
415 | 408 | ||
416 | spin_lock(&inode->i_lock); | 409 | spin_lock(&inode->i_lock); |
410 | lseg = nfs_clear_request_commit(req); | ||
417 | set_page_private(req->wb_page, 0); | 411 | set_page_private(req->wb_page, 0); |
418 | ClearPagePrivate(req->wb_page); | 412 | ClearPagePrivate(req->wb_page); |
419 | clear_bit(PG_MAPPED, &req->wb_flags); | 413 | clear_bit(PG_MAPPED, &req->wb_flags); |
420 | radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index); | ||
421 | nfsi->npages--; | 414 | nfsi->npages--; |
422 | spin_unlock(&inode->i_lock); | 415 | spin_unlock(&inode->i_lock); |
416 | put_lseg(lseg); | ||
423 | nfs_release_request(req); | 417 | nfs_release_request(req); |
424 | } | 418 | } |
425 | 419 | ||
@@ -438,31 +432,38 @@ nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) | |||
438 | { | 432 | { |
439 | struct inode *inode = req->wb_context->dentry->d_inode; | 433 | struct inode *inode = req->wb_context->dentry->d_inode; |
440 | struct nfs_inode *nfsi = NFS_I(inode); | 434 | struct nfs_inode *nfsi = NFS_I(inode); |
435 | struct list_head *clist; | ||
441 | 436 | ||
437 | clist = pnfs_choose_commit_list(req, lseg); | ||
442 | spin_lock(&inode->i_lock); | 438 | spin_lock(&inode->i_lock); |
443 | set_bit(PG_CLEAN, &(req)->wb_flags); | 439 | set_bit(PG_CLEAN, &(req)->wb_flags); |
444 | radix_tree_tag_set(&nfsi->nfs_page_tree, | 440 | nfs_list_add_request(req, clist); |
445 | req->wb_index, | ||
446 | NFS_PAGE_TAG_COMMIT); | ||
447 | nfsi->ncommit++; | 441 | nfsi->ncommit++; |
448 | spin_unlock(&inode->i_lock); | 442 | spin_unlock(&inode->i_lock); |
449 | pnfs_mark_request_commit(req, lseg); | ||
450 | inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | 443 | inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); |
451 | inc_bdi_stat(req->wb_page->mapping->backing_dev_info, BDI_RECLAIMABLE); | 444 | inc_bdi_stat(req->wb_page->mapping->backing_dev_info, BDI_RECLAIMABLE); |
452 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); | 445 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); |
453 | } | 446 | } |
454 | 447 | ||
455 | static int | 448 | static void |
449 | nfs_clear_page_commit(struct page *page) | ||
450 | { | ||
451 | dec_zone_page_state(page, NR_UNSTABLE_NFS); | ||
452 | dec_bdi_stat(page->mapping->backing_dev_info, BDI_RECLAIMABLE); | ||
453 | } | ||
454 | |||
455 | static struct pnfs_layout_segment * | ||
456 | nfs_clear_request_commit(struct nfs_page *req) | 456 | nfs_clear_request_commit(struct nfs_page *req) |
457 | { | 457 | { |
458 | struct page *page = req->wb_page; | 458 | struct pnfs_layout_segment *lseg = NULL; |
459 | 459 | ||
460 | if (test_and_clear_bit(PG_CLEAN, &(req)->wb_flags)) { | 460 | if (test_and_clear_bit(PG_CLEAN, &(req)->wb_flags)) { |
461 | dec_zone_page_state(page, NR_UNSTABLE_NFS); | 461 | nfs_clear_page_commit(req->wb_page); |
462 | dec_bdi_stat(page->mapping->backing_dev_info, BDI_RECLAIMABLE); | 462 | lseg = pnfs_clear_request_commit(req); |
463 | return 1; | 463 | NFS_I(req->wb_context->dentry->d_inode)->ncommit--; |
464 | list_del(&req->wb_list); | ||
464 | } | 465 | } |
465 | return 0; | 466 | return lseg; |
466 | } | 467 | } |
467 | 468 | ||
468 | static inline | 469 | static inline |
@@ -494,10 +495,10 @@ nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) | |||
494 | { | 495 | { |
495 | } | 496 | } |
496 | 497 | ||
497 | static inline int | 498 | static inline struct pnfs_layout_segment * |
498 | nfs_clear_request_commit(struct nfs_page *req) | 499 | nfs_clear_request_commit(struct nfs_page *req) |
499 | { | 500 | { |
500 | return 0; | 501 | return NULL; |
501 | } | 502 | } |
502 | 503 | ||
503 | static inline | 504 | static inline |
@@ -518,46 +519,67 @@ int nfs_reschedule_unstable_write(struct nfs_page *req, | |||
518 | static int | 519 | static int |
519 | nfs_need_commit(struct nfs_inode *nfsi) | 520 | nfs_need_commit(struct nfs_inode *nfsi) |
520 | { | 521 | { |
521 | return radix_tree_tagged(&nfsi->nfs_page_tree, NFS_PAGE_TAG_COMMIT); | 522 | return nfsi->ncommit > 0; |
522 | } | 523 | } |
523 | 524 | ||
525 | /* i_lock held by caller */ | ||
526 | int | ||
527 | nfs_scan_commit_list(struct list_head *src, struct list_head *dst, int max) | ||
528 | { | ||
529 | struct nfs_page *req, *tmp; | ||
530 | int ret = 0; | ||
531 | |||
532 | list_for_each_entry_safe(req, tmp, src, wb_list) { | ||
533 | if (nfs_lock_request_dontget(req)) { | ||
534 | kref_get(&req->wb_kref); | ||
535 | list_move_tail(&req->wb_list, dst); | ||
536 | clear_bit(PG_CLEAN, &(req)->wb_flags); | ||
537 | ret++; | ||
538 | if (ret == max) | ||
539 | break; | ||
540 | } | ||
541 | } | ||
542 | return ret; | ||
543 | } | ||
544 | EXPORT_SYMBOL_GPL(nfs_scan_commit_list); | ||
545 | |||
524 | /* | 546 | /* |
525 | * nfs_scan_commit - Scan an inode for commit requests | 547 | * nfs_scan_commit - Scan an inode for commit requests |
526 | * @inode: NFS inode to scan | 548 | * @inode: NFS inode to scan |
527 | * @dst: destination list | 549 | * @dst: destination list |
528 | * @idx_start: lower bound of page->index to scan. | ||
529 | * @npages: idx_start + npages sets the upper bound to scan. | ||
530 | * | 550 | * |
531 | * Moves requests from the inode's 'commit' request list. | 551 | * Moves requests from the inode's 'commit' request list. |
532 | * The requests are *not* checked to ensure that they form a contiguous set. | 552 | * The requests are *not* checked to ensure that they form a contiguous set. |
533 | */ | 553 | */ |
534 | static int | 554 | static int |
535 | nfs_scan_commit(struct inode *inode, struct list_head *dst, pgoff_t idx_start, unsigned int npages) | 555 | nfs_scan_commit(struct inode *inode, struct list_head *dst) |
536 | { | 556 | { |
537 | struct nfs_inode *nfsi = NFS_I(inode); | 557 | struct nfs_inode *nfsi = NFS_I(inode); |
538 | int ret; | 558 | int ret = 0; |
539 | |||
540 | if (!nfs_need_commit(nfsi)) | ||
541 | return 0; | ||
542 | 559 | ||
543 | spin_lock(&inode->i_lock); | 560 | spin_lock(&inode->i_lock); |
544 | ret = nfs_scan_list(nfsi, dst, idx_start, npages, NFS_PAGE_TAG_COMMIT); | 561 | if (nfsi->ncommit > 0) { |
545 | if (ret > 0) | 562 | int pnfs_ret; |
563 | |||
564 | ret = nfs_scan_commit_list(&nfsi->commit_list, dst, INT_MAX); | ||
565 | pnfs_ret = pnfs_scan_commit_lists(inode, INT_MAX - ret); | ||
566 | if (pnfs_ret) { | ||
567 | ret += pnfs_ret; | ||
568 | set_bit(NFS_INO_PNFS_COMMIT, &nfsi->flags); | ||
569 | } | ||
546 | nfsi->ncommit -= ret; | 570 | nfsi->ncommit -= ret; |
571 | } | ||
547 | spin_unlock(&inode->i_lock); | 572 | spin_unlock(&inode->i_lock); |
548 | |||
549 | if (nfs_need_commit(NFS_I(inode))) | ||
550 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); | ||
551 | |||
552 | return ret; | 573 | return ret; |
553 | } | 574 | } |
575 | |||
554 | #else | 576 | #else |
555 | static inline int nfs_need_commit(struct nfs_inode *nfsi) | 577 | static inline int nfs_need_commit(struct nfs_inode *nfsi) |
556 | { | 578 | { |
557 | return 0; | 579 | return 0; |
558 | } | 580 | } |
559 | 581 | ||
560 | static inline int nfs_scan_commit(struct inode *inode, struct list_head *dst, pgoff_t idx_start, unsigned int npages) | 582 | static inline int nfs_scan_commit(struct inode *inode, struct list_head *dst) |
561 | { | 583 | { |
562 | return 0; | 584 | return 0; |
563 | } | 585 | } |
@@ -579,6 +601,7 @@ static struct nfs_page *nfs_try_to_update_request(struct inode *inode, | |||
579 | unsigned int rqend; | 601 | unsigned int rqend; |
580 | unsigned int end; | 602 | unsigned int end; |
581 | int error; | 603 | int error; |
604 | struct pnfs_layout_segment *lseg = NULL; | ||
582 | 605 | ||
583 | if (!PagePrivate(page)) | 606 | if (!PagePrivate(page)) |
584 | return NULL; | 607 | return NULL; |
@@ -614,12 +637,7 @@ static struct nfs_page *nfs_try_to_update_request(struct inode *inode, | |||
614 | spin_lock(&inode->i_lock); | 637 | spin_lock(&inode->i_lock); |
615 | } | 638 | } |
616 | 639 | ||
617 | if (nfs_clear_request_commit(req) && | 640 | lseg = nfs_clear_request_commit(req); |
618 | radix_tree_tag_clear(&NFS_I(inode)->nfs_page_tree, | ||
619 | req->wb_index, NFS_PAGE_TAG_COMMIT) != NULL) { | ||
620 | NFS_I(inode)->ncommit--; | ||
621 | pnfs_clear_request_commit(req); | ||
622 | } | ||
623 | 641 | ||
624 | /* Okay, the request matches. Update the region */ | 642 | /* Okay, the request matches. Update the region */ |
625 | if (offset < req->wb_offset) { | 643 | if (offset < req->wb_offset) { |
@@ -632,6 +650,7 @@ static struct nfs_page *nfs_try_to_update_request(struct inode *inode, | |||
632 | req->wb_bytes = rqend - req->wb_offset; | 650 | req->wb_bytes = rqend - req->wb_offset; |
633 | out_unlock: | 651 | out_unlock: |
634 | spin_unlock(&inode->i_lock); | 652 | spin_unlock(&inode->i_lock); |
653 | put_lseg(lseg); | ||
635 | return req; | 654 | return req; |
636 | out_flushme: | 655 | out_flushme: |
637 | spin_unlock(&inode->i_lock); | 656 | spin_unlock(&inode->i_lock); |
@@ -653,7 +672,6 @@ static struct nfs_page * nfs_setup_write_request(struct nfs_open_context* ctx, | |||
653 | { | 672 | { |
654 | struct inode *inode = page->mapping->host; | 673 | struct inode *inode = page->mapping->host; |
655 | struct nfs_page *req; | 674 | struct nfs_page *req; |
656 | int error; | ||
657 | 675 | ||
658 | req = nfs_try_to_update_request(inode, page, offset, bytes); | 676 | req = nfs_try_to_update_request(inode, page, offset, bytes); |
659 | if (req != NULL) | 677 | if (req != NULL) |
@@ -661,11 +679,7 @@ static struct nfs_page * nfs_setup_write_request(struct nfs_open_context* ctx, | |||
661 | req = nfs_create_request(ctx, inode, page, offset, bytes); | 679 | req = nfs_create_request(ctx, inode, page, offset, bytes); |
662 | if (IS_ERR(req)) | 680 | if (IS_ERR(req)) |
663 | goto out; | 681 | goto out; |
664 | error = nfs_inode_add_request(inode, req); | 682 | nfs_inode_add_request(inode, req); |
665 | if (error != 0) { | ||
666 | nfs_release_request(req); | ||
667 | req = ERR_PTR(error); | ||
668 | } | ||
669 | out: | 683 | out: |
670 | return req; | 684 | return req; |
671 | } | 685 | } |
@@ -1458,7 +1472,7 @@ void nfs_commit_release_pages(struct nfs_write_data *data) | |||
1458 | while (!list_empty(&data->pages)) { | 1472 | while (!list_empty(&data->pages)) { |
1459 | req = nfs_list_entry(data->pages.next); | 1473 | req = nfs_list_entry(data->pages.next); |
1460 | nfs_list_remove_request(req); | 1474 | nfs_list_remove_request(req); |
1461 | nfs_clear_request_commit(req); | 1475 | nfs_clear_page_commit(req->wb_page); |
1462 | 1476 | ||
1463 | dprintk("NFS: commit (%s/%lld %d@%lld)", | 1477 | dprintk("NFS: commit (%s/%lld %d@%lld)", |
1464 | req->wb_context->dentry->d_sb->s_id, | 1478 | req->wb_context->dentry->d_sb->s_id, |
@@ -1515,7 +1529,7 @@ int nfs_commit_inode(struct inode *inode, int how) | |||
1515 | res = nfs_commit_set_lock(NFS_I(inode), may_wait); | 1529 | res = nfs_commit_set_lock(NFS_I(inode), may_wait); |
1516 | if (res <= 0) | 1530 | if (res <= 0) |
1517 | goto out_mark_dirty; | 1531 | goto out_mark_dirty; |
1518 | res = nfs_scan_commit(inode, &head, 0, 0); | 1532 | res = nfs_scan_commit(inode, &head); |
1519 | if (res) { | 1533 | if (res) { |
1520 | int error; | 1534 | int error; |
1521 | 1535 | ||