diff options
author | Peng Tao <bergwolf@gmail.com> | 2012-01-12 10:18:42 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-01-12 16:52:10 -0500 |
commit | 72c508879979522de347bcec706507e00d7c443d (patch) | |
tree | e5e7729cf427f390b8314b83143342274f8d3d03 /fs/nfs/blocklayout/blocklayout.c | |
parent | 60c52e3a72fda10e82f38b6f979956eb2dcb3d4e (diff) |
pnfsblock: move find lock page logic out of bl_write_pagelist
Also avoid unnecessary lock_page if page is handled by others.
Signed-off-by: Peng Tao <peng_tao@emc.com>
Signed-off-by: Benny Halevy <bhalevy@tonian.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/blocklayout/blocklayout.c')
-rw-r--r-- | fs/nfs/blocklayout/blocklayout.c | 78 |
1 files changed, 54 insertions, 24 deletions
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index a263810803c1..234273621854 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c | |||
@@ -490,6 +490,55 @@ cleanup: | |||
490 | return ret; | 490 | return ret; |
491 | } | 491 | } |
492 | 492 | ||
493 | /* Find or create a zeroing page marked being writeback. | ||
494 | * Return ERR_PTR on error, NULL to indicate skip this page and page itself | ||
495 | * to indicate write out. | ||
496 | */ | ||
497 | static struct page * | ||
498 | bl_find_get_zeroing_page(struct inode *inode, pgoff_t index, | ||
499 | struct pnfs_block_extent *cow_read) | ||
500 | { | ||
501 | struct page *page; | ||
502 | int locked = 0; | ||
503 | page = find_get_page(inode->i_mapping, index); | ||
504 | if (page) | ||
505 | goto check_page; | ||
506 | |||
507 | page = find_or_create_page(inode->i_mapping, index, GFP_NOFS); | ||
508 | if (unlikely(!page)) { | ||
509 | dprintk("%s oom\n", __func__); | ||
510 | return ERR_PTR(-ENOMEM); | ||
511 | } | ||
512 | locked = 1; | ||
513 | |||
514 | check_page: | ||
515 | /* PageDirty: Other will write this out | ||
516 | * PageWriteback: Other is writing this out | ||
517 | * PageUptodate: It was read before | ||
518 | */ | ||
519 | if (PageDirty(page) || PageWriteback(page)) { | ||
520 | print_page(page); | ||
521 | if (locked) | ||
522 | unlock_page(page); | ||
523 | page_cache_release(page); | ||
524 | return NULL; | ||
525 | } | ||
526 | |||
527 | if (!locked) { | ||
528 | lock_page(page); | ||
529 | locked = 1; | ||
530 | goto check_page; | ||
531 | } | ||
532 | if (!PageUptodate(page)) { | ||
533 | /* New page, readin or zero it */ | ||
534 | init_page_for_write(page, cow_read); | ||
535 | } | ||
536 | set_page_writeback(page); | ||
537 | unlock_page(page); | ||
538 | |||
539 | return page; | ||
540 | } | ||
541 | |||
493 | static enum pnfs_try_status | 542 | static enum pnfs_try_status |
494 | bl_write_pagelist(struct nfs_write_data *wdata, int sync) | 543 | bl_write_pagelist(struct nfs_write_data *wdata, int sync) |
495 | { | 544 | { |
@@ -549,32 +598,13 @@ fill_invalid_ext: | |||
549 | dprintk("%s zero %dth page: index %lu isect %llu\n", | 598 | dprintk("%s zero %dth page: index %lu isect %llu\n", |
550 | __func__, npg_zero, index, | 599 | __func__, npg_zero, index, |
551 | (unsigned long long)isect); | 600 | (unsigned long long)isect); |
552 | page = | 601 | page = bl_find_get_zeroing_page(wdata->inode, index, |
553 | find_or_create_page(wdata->inode->i_mapping, index, | 602 | cow_read); |
554 | GFP_NOFS); | 603 | if (unlikely(IS_ERR(page))) { |
555 | if (!page) { | 604 | wdata->pnfs_error = PTR_ERR(page); |
556 | dprintk("%s oom\n", __func__); | ||
557 | wdata->pnfs_error = -ENOMEM; | ||
558 | goto out; | 605 | goto out; |
559 | } | 606 | } else if (page == NULL) |
560 | |||
561 | /* PageDirty: Other will write this out | ||
562 | * PageWriteback: Other is writing this out | ||
563 | * PageUptodate: It was read before | ||
564 | * sector_initialized: already written out | ||
565 | */ | ||
566 | if (PageDirty(page) || PageWriteback(page)) { | ||
567 | print_page(page); | ||
568 | unlock_page(page); | ||
569 | page_cache_release(page); | ||
570 | goto next_page; | 607 | goto next_page; |
571 | } | ||
572 | if (!PageUptodate(page)) { | ||
573 | /* New page, readin or zero it */ | ||
574 | init_page_for_write(page, cow_read); | ||
575 | } | ||
576 | set_page_writeback(page); | ||
577 | unlock_page(page); | ||
578 | 608 | ||
579 | ret = bl_mark_sectors_init(be->be_inval, isect, | 609 | ret = bl_mark_sectors_init(be->be_inval, isect, |
580 | PAGE_CACHE_SECTORS); | 610 | PAGE_CACHE_SECTORS); |