diff options
| -rw-r--r-- | fs/exofs/inode.c | 61 |
1 files changed, 59 insertions, 2 deletions
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index 86c0ac87b8e3..3e5f3a6be90a 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c | |||
| @@ -63,6 +63,7 @@ struct page_collect { | |||
| 63 | bool read_4_write; /* This means two things: that the read is sync | 63 | bool read_4_write; /* This means two things: that the read is sync |
| 64 | * And the pages should not be unlocked. | 64 | * And the pages should not be unlocked. |
| 65 | */ | 65 | */ |
| 66 | struct page *that_locked_page; | ||
| 66 | }; | 67 | }; |
| 67 | 68 | ||
| 68 | static void _pcol_init(struct page_collect *pcol, unsigned expected_pages, | 69 | static void _pcol_init(struct page_collect *pcol, unsigned expected_pages, |
| @@ -81,6 +82,7 @@ static void _pcol_init(struct page_collect *pcol, unsigned expected_pages, | |||
| 81 | pcol->length = 0; | 82 | pcol->length = 0; |
| 82 | pcol->pg_first = -1; | 83 | pcol->pg_first = -1; |
| 83 | pcol->read_4_write = false; | 84 | pcol->read_4_write = false; |
| 85 | pcol->that_locked_page = NULL; | ||
| 84 | } | 86 | } |
| 85 | 87 | ||
| 86 | static void _pcol_reset(struct page_collect *pcol) | 88 | static void _pcol_reset(struct page_collect *pcol) |
| @@ -93,6 +95,7 @@ static void _pcol_reset(struct page_collect *pcol) | |||
| 93 | pcol->length = 0; | 95 | pcol->length = 0; |
| 94 | pcol->pg_first = -1; | 96 | pcol->pg_first = -1; |
| 95 | pcol->ios = NULL; | 97 | pcol->ios = NULL; |
| 98 | pcol->that_locked_page = NULL; | ||
| 96 | 99 | ||
| 97 | /* this is probably the end of the loop but in writes | 100 | /* this is probably the end of the loop but in writes |
| 98 | * it might not end here. don't be left with nothing | 101 | * it might not end here. don't be left with nothing |
| @@ -391,6 +394,8 @@ static int readpage_strip(void *data, struct page *page) | |||
| 391 | EXOFS_ERR("PageUptodate(0x%lx, 0x%lx)\n", pcol->inode->i_ino, | 394 | EXOFS_ERR("PageUptodate(0x%lx, 0x%lx)\n", pcol->inode->i_ino, |
| 392 | page->index); | 395 | page->index); |
| 393 | 396 | ||
| 397 | pcol->that_locked_page = page; | ||
| 398 | |||
| 394 | if (page->index < end_index) | 399 | if (page->index < end_index) |
| 395 | len = PAGE_CACHE_SIZE; | 400 | len = PAGE_CACHE_SIZE; |
| 396 | else if (page->index == end_index) | 401 | else if (page->index == end_index) |
| @@ -560,6 +565,56 @@ static void writepages_done(struct ore_io_state *ios, void *p) | |||
| 560 | EXOFS_DBGMSG2("writepages_done END\n"); | 565 | EXOFS_DBGMSG2("writepages_done END\n"); |
| 561 | } | 566 | } |
| 562 | 567 | ||
| 568 | static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate) | ||
| 569 | { | ||
| 570 | struct page_collect *pcol = priv; | ||
| 571 | pgoff_t index = offset / PAGE_SIZE; | ||
| 572 | |||
| 573 | if (!pcol->that_locked_page || | ||
| 574 | (pcol->that_locked_page->index != index)) { | ||
| 575 | struct page *page = find_get_page(pcol->inode->i_mapping, index); | ||
| 576 | |||
| 577 | if (!page) { | ||
| 578 | page = find_or_create_page(pcol->inode->i_mapping, | ||
| 579 | index, GFP_NOFS); | ||
| 580 | if (unlikely(!page)) { | ||
| 581 | EXOFS_DBGMSG("grab_cache_page Failed " | ||
| 582 | "index=0x%llx\n", _LLU(index)); | ||
| 583 | return NULL; | ||
| 584 | } | ||
| 585 | unlock_page(page); | ||
| 586 | } | ||
| 587 | if (PageDirty(page) || PageWriteback(page)) | ||
| 588 | *uptodate = true; | ||
| 589 | else | ||
| 590 | *uptodate = PageUptodate(page); | ||
| 591 | EXOFS_DBGMSG("index=0x%lx uptodate=%d\n", index, *uptodate); | ||
| 592 | return page; | ||
| 593 | } else { | ||
| 594 | EXOFS_DBGMSG("YES that_locked_page index=0x%lx\n", | ||
| 595 | pcol->that_locked_page->index); | ||
| 596 | *uptodate = true; | ||
| 597 | return pcol->that_locked_page; | ||
| 598 | } | ||
| 599 | } | ||
| 600 | |||
| 601 | static void __r4w_put_page(void *priv, struct page *page) | ||
| 602 | { | ||
| 603 | struct page_collect *pcol = priv; | ||
| 604 | |||
| 605 | if (pcol->that_locked_page != page) { | ||
| 606 | EXOFS_DBGMSG("index=0x%lx\n", page->index); | ||
| 607 | page_cache_release(page); | ||
| 608 | return; | ||
| 609 | } | ||
| 610 | EXOFS_DBGMSG("that_locked_page index=0x%lx\n", page->index); | ||
| 611 | } | ||
| 612 | |||
| 613 | static const struct _ore_r4w_op _r4w_op = { | ||
| 614 | .get_page = &__r4w_get_page, | ||
| 615 | .put_page = &__r4w_put_page, | ||
| 616 | }; | ||
| 617 | |||
| 563 | static int write_exec(struct page_collect *pcol) | 618 | static int write_exec(struct page_collect *pcol) |
| 564 | { | 619 | { |
| 565 | struct exofs_i_info *oi = exofs_i(pcol->inode); | 620 | struct exofs_i_info *oi = exofs_i(pcol->inode); |
| @@ -589,6 +644,7 @@ static int write_exec(struct page_collect *pcol) | |||
| 589 | ios = pcol->ios; | 644 | ios = pcol->ios; |
| 590 | ios->pages = pcol_copy->pages; | 645 | ios->pages = pcol_copy->pages; |
| 591 | ios->done = writepages_done; | 646 | ios->done = writepages_done; |
| 647 | ios->r4w = &_r4w_op; | ||
| 592 | ios->private = pcol_copy; | 648 | ios->private = pcol_copy; |
| 593 | 649 | ||
| 594 | /* pages ownership was passed to pcol_copy */ | 650 | /* pages ownership was passed to pcol_copy */ |
| @@ -773,6 +829,7 @@ static int exofs_writepages(struct address_space *mapping, | |||
| 773 | return 0; | 829 | return 0; |
| 774 | } | 830 | } |
| 775 | 831 | ||
| 832 | /* | ||
| 776 | static int exofs_writepage(struct page *page, struct writeback_control *wbc) | 833 | static int exofs_writepage(struct page *page, struct writeback_control *wbc) |
| 777 | { | 834 | { |
| 778 | struct page_collect pcol; | 835 | struct page_collect pcol; |
| @@ -788,7 +845,7 @@ static int exofs_writepage(struct page *page, struct writeback_control *wbc) | |||
| 788 | 845 | ||
| 789 | return write_exec(&pcol); | 846 | return write_exec(&pcol); |
| 790 | } | 847 | } |
| 791 | 848 | */ | |
| 792 | /* i_mutex held using inode->i_size directly */ | 849 | /* i_mutex held using inode->i_size directly */ |
| 793 | static void _write_failed(struct inode *inode, loff_t to) | 850 | static void _write_failed(struct inode *inode, loff_t to) |
| 794 | { | 851 | { |
| @@ -894,7 +951,7 @@ static void exofs_invalidatepage(struct page *page, unsigned long offset) | |||
| 894 | const struct address_space_operations exofs_aops = { | 951 | const struct address_space_operations exofs_aops = { |
| 895 | .readpage = exofs_readpage, | 952 | .readpage = exofs_readpage, |
| 896 | .readpages = exofs_readpages, | 953 | .readpages = exofs_readpages, |
| 897 | .writepage = exofs_writepage, | 954 | .writepage = NULL, |
| 898 | .writepages = exofs_writepages, | 955 | .writepages = exofs_writepages, |
| 899 | .write_begin = exofs_write_begin_export, | 956 | .write_begin = exofs_write_begin_export, |
| 900 | .write_end = exofs_write_end, | 957 | .write_end = exofs_write_end, |
