aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/write.c
diff options
context:
space:
mode:
authorFred Isaman <iisaman@netapp.com>2012-03-08 17:29:35 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-03-10 17:14:10 -0500
commitd6d6dc7cdfda7c8f49a89a7b7261846f319da6d1 (patch)
treefd26cf912b676f2752c16ccce1f410872a2a485c /fs/nfs/write.c
parent9994b62b5621f88828d442fcd03fe3ce4c43344b (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.c120
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 */
378static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req) 378static 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();
402out:
403 return error;
404} 394}
405 395
396static 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
455static int 448static void
449nfs_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
455static struct pnfs_layout_segment *
456nfs_clear_request_commit(struct nfs_page *req) 456nfs_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
468static inline 469static inline
@@ -494,10 +495,10 @@ nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg)
494{ 495{
495} 496}
496 497
497static inline int 498static inline struct pnfs_layout_segment *
498nfs_clear_request_commit(struct nfs_page *req) 499nfs_clear_request_commit(struct nfs_page *req)
499{ 500{
500 return 0; 501 return NULL;
501} 502}
502 503
503static inline 504static inline
@@ -518,46 +519,67 @@ int nfs_reschedule_unstable_write(struct nfs_page *req,
518static int 519static int
519nfs_need_commit(struct nfs_inode *nfsi) 520nfs_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 */
526int
527nfs_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}
544EXPORT_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 */
534static int 554static int
535nfs_scan_commit(struct inode *inode, struct list_head *dst, pgoff_t idx_start, unsigned int npages) 555nfs_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
555static inline int nfs_need_commit(struct nfs_inode *nfsi) 577static inline int nfs_need_commit(struct nfs_inode *nfsi)
556{ 578{
557 return 0; 579 return 0;
558} 580}
559 581
560static inline int nfs_scan_commit(struct inode *inode, struct list_head *dst, pgoff_t idx_start, unsigned int npages) 582static 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;
633out_unlock: 651out_unlock:
634 spin_unlock(&inode->i_lock); 652 spin_unlock(&inode->i_lock);
653 put_lseg(lseg);
635 return req; 654 return req;
636out_flushme: 655out_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 }
669out: 683out:
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