aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorPeng Tao <bergwolf@gmail.com>2012-01-12 10:18:42 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-01-12 16:52:10 -0500
commit72c508879979522de347bcec706507e00d7c443d (patch)
treee5e7729cf427f390b8314b83143342274f8d3d03 /fs/nfs
parent60c52e3a72fda10e82f38b6f979956eb2dcb3d4e (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')
-rw-r--r--fs/nfs/blocklayout/blocklayout.c78
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 */
497static struct page *
498bl_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
514check_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
493static enum pnfs_try_status 542static enum pnfs_try_status
494bl_write_pagelist(struct nfs_write_data *wdata, int sync) 543bl_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);