aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Fasheh <mark.fasheh@oracle.com>2007-09-07 17:20:45 -0400
committerMark Fasheh <mark.fasheh@oracle.com>2007-10-12 14:54:35 -0400
commit1d410a6e337a0d2d5543ad1d9bccb670a7a05312 (patch)
tree696f70750482a4a49b61c79e6499659ddb3635b4
parent65ed39d6ca78f07d2958814e08440e4264b6b488 (diff)
ocfs2: Small refactor of truncate zeroing code
We'll want to reuse most of this when pushing inline data back out to an extent. Keeping this part as a seperate patch helps to keep the upcoming changes for write support uncluttered. The core portion of ocfs2_zero_cluster_pages() responsible for making sure a page is mapped and properly dirtied is abstracted out into it's own function, ocfs2_map_and_dirty_page(). Actual functionality doesn't change, though zeroing becomes optional. We also turn part of ocfs2_free_write_ctxt() into a common function for unlocking and freeing a page array. This operation is very common (and uniform) for Ocfs2 cluster sizes greater than page size, so it makes sense to keep the code in one place. Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com> Reviewed-by: Joel Becker <joel.becker@oracle.com>
-rw-r--r--fs/ocfs2/alloc.c151
-rw-r--r--fs/ocfs2/aops.c20
-rw-r--r--fs/ocfs2/aops.h2
3 files changed, 86 insertions, 87 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index c91706f949ff..c81bfdfb9929 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -5633,12 +5633,50 @@ static int ocfs2_ordered_zero_func(handle_t *handle, struct buffer_head *bh)
5633 return ocfs2_journal_dirty_data(handle, bh); 5633 return ocfs2_journal_dirty_data(handle, bh);
5634} 5634}
5635 5635
5636static void ocfs2_map_and_dirty_page(struct inode *inode, handle_t *handle,
5637 unsigned int from, unsigned int to,
5638 struct page *page, int zero, u64 *phys)
5639{
5640 int ret, partial = 0;
5641
5642 ret = ocfs2_map_page_blocks(page, phys, inode, from, to, 0);
5643 if (ret)
5644 mlog_errno(ret);
5645
5646 if (zero)
5647 zero_user_page(page, from, to - from, KM_USER0);
5648
5649 /*
5650 * Need to set the buffers we zero'd into uptodate
5651 * here if they aren't - ocfs2_map_page_blocks()
5652 * might've skipped some
5653 */
5654 if (ocfs2_should_order_data(inode)) {
5655 ret = walk_page_buffers(handle,
5656 page_buffers(page),
5657 from, to, &partial,
5658 ocfs2_ordered_zero_func);
5659 if (ret < 0)
5660 mlog_errno(ret);
5661 } else {
5662 ret = walk_page_buffers(handle, page_buffers(page),
5663 from, to, &partial,
5664 ocfs2_writeback_zero_func);
5665 if (ret < 0)
5666 mlog_errno(ret);
5667 }
5668
5669 if (!partial)
5670 SetPageUptodate(page);
5671
5672 flush_dcache_page(page);
5673}
5674
5636static void ocfs2_zero_cluster_pages(struct inode *inode, loff_t start, 5675static void ocfs2_zero_cluster_pages(struct inode *inode, loff_t start,
5637 loff_t end, struct page **pages, 5676 loff_t end, struct page **pages,
5638 int numpages, u64 phys, handle_t *handle) 5677 int numpages, u64 phys, handle_t *handle)
5639{ 5678{
5640 int i, ret, partial = 0; 5679 int i;
5641 void *kaddr;
5642 struct page *page; 5680 struct page *page;
5643 unsigned int from, to = PAGE_CACHE_SIZE; 5681 unsigned int from, to = PAGE_CACHE_SIZE;
5644 struct super_block *sb = inode->i_sb; 5682 struct super_block *sb = inode->i_sb;
@@ -5659,87 +5697,31 @@ static void ocfs2_zero_cluster_pages(struct inode *inode, loff_t start,
5659 BUG_ON(from > PAGE_CACHE_SIZE); 5697 BUG_ON(from > PAGE_CACHE_SIZE);
5660 BUG_ON(to > PAGE_CACHE_SIZE); 5698 BUG_ON(to > PAGE_CACHE_SIZE);
5661 5699
5662 ret = ocfs2_map_page_blocks(page, &phys, inode, from, to, 0); 5700 ocfs2_map_and_dirty_page(inode, handle, from, to, page, 1,
5663 if (ret) 5701 &phys);
5664 mlog_errno(ret);
5665
5666 kaddr = kmap_atomic(page, KM_USER0);
5667 memset(kaddr + from, 0, to - from);
5668 kunmap_atomic(kaddr, KM_USER0);
5669
5670 /*
5671 * Need to set the buffers we zero'd into uptodate
5672 * here if they aren't - ocfs2_map_page_blocks()
5673 * might've skipped some
5674 */
5675 if (ocfs2_should_order_data(inode)) {
5676 ret = walk_page_buffers(handle,
5677 page_buffers(page),
5678 from, to, &partial,
5679 ocfs2_ordered_zero_func);
5680 if (ret < 0)
5681 mlog_errno(ret);
5682 } else {
5683 ret = walk_page_buffers(handle, page_buffers(page),
5684 from, to, &partial,
5685 ocfs2_writeback_zero_func);
5686 if (ret < 0)
5687 mlog_errno(ret);
5688 }
5689
5690 if (!partial)
5691 SetPageUptodate(page);
5692
5693 flush_dcache_page(page);
5694 5702
5695 start = (page->index + 1) << PAGE_CACHE_SHIFT; 5703 start = (page->index + 1) << PAGE_CACHE_SHIFT;
5696 } 5704 }
5697out: 5705out:
5698 if (pages) { 5706 if (pages)
5699 for (i = 0; i < numpages; i++) { 5707 ocfs2_unlock_and_free_pages(pages, numpages);
5700 page = pages[i];
5701 unlock_page(page);
5702 mark_page_accessed(page);
5703 page_cache_release(page);
5704 }
5705 }
5706} 5708}
5707 5709
5708static int ocfs2_grab_eof_pages(struct inode *inode, loff_t start, loff_t end, 5710static int ocfs2_grab_eof_pages(struct inode *inode, loff_t start, loff_t end,
5709 struct page **pages, int *num, u64 *phys) 5711 struct page **pages, int *num)
5710{ 5712{
5711 int i, numpages = 0, ret = 0; 5713 int numpages, ret = 0;
5712 unsigned int ext_flags;
5713 struct super_block *sb = inode->i_sb; 5714 struct super_block *sb = inode->i_sb;
5714 struct address_space *mapping = inode->i_mapping; 5715 struct address_space *mapping = inode->i_mapping;
5715 unsigned long index; 5716 unsigned long index;
5716 loff_t last_page_bytes; 5717 loff_t last_page_bytes;
5717 5718
5718 BUG_ON(!ocfs2_sparse_alloc(OCFS2_SB(sb)));
5719 BUG_ON(start > end); 5719 BUG_ON(start > end);
5720 5720
5721 if (start == end)
5722 goto out;
5723
5724 BUG_ON(start >> OCFS2_SB(sb)->s_clustersize_bits != 5721 BUG_ON(start >> OCFS2_SB(sb)->s_clustersize_bits !=
5725 (end - 1) >> OCFS2_SB(sb)->s_clustersize_bits); 5722 (end - 1) >> OCFS2_SB(sb)->s_clustersize_bits);
5726 5723
5727 ret = ocfs2_extent_map_get_blocks(inode, start >> sb->s_blocksize_bits, 5724 numpages = 0;
5728 phys, NULL, &ext_flags);
5729 if (ret) {
5730 mlog_errno(ret);
5731 goto out;
5732 }
5733
5734 /* Tail is a hole. */
5735 if (*phys == 0)
5736 goto out;
5737
5738 /* Tail is marked as unwritten, we can count on write to zero
5739 * in that case. */
5740 if (ext_flags & OCFS2_EXT_UNWRITTEN)
5741 goto out;
5742
5743 last_page_bytes = PAGE_ALIGN(end); 5725 last_page_bytes = PAGE_ALIGN(end);
5744 index = start >> PAGE_CACHE_SHIFT; 5726 index = start >> PAGE_CACHE_SHIFT;
5745 do { 5727 do {
@@ -5756,14 +5738,8 @@ static int ocfs2_grab_eof_pages(struct inode *inode, loff_t start, loff_t end,
5756 5738
5757out: 5739out:
5758 if (ret != 0) { 5740 if (ret != 0) {
5759 if (pages) { 5741 if (pages)
5760 for (i = 0; i < numpages; i++) { 5742 ocfs2_unlock_and_free_pages(pages, numpages);
5761 if (pages[i]) {
5762 unlock_page(pages[i]);
5763 page_cache_release(pages[i]);
5764 }
5765 }
5766 }
5767 numpages = 0; 5743 numpages = 0;
5768 } 5744 }
5769 5745
@@ -5784,18 +5760,20 @@ out:
5784int ocfs2_zero_range_for_truncate(struct inode *inode, handle_t *handle, 5760int ocfs2_zero_range_for_truncate(struct inode *inode, handle_t *handle,
5785 u64 range_start, u64 range_end) 5761 u64 range_start, u64 range_end)
5786{ 5762{
5787 int ret, numpages; 5763 int ret = 0, numpages;
5788 struct page **pages = NULL; 5764 struct page **pages = NULL;
5789 u64 phys; 5765 u64 phys;
5766 unsigned int ext_flags;
5767 struct super_block *sb = inode->i_sb;
5790 5768
5791 /* 5769 /*
5792 * File systems which don't support sparse files zero on every 5770 * File systems which don't support sparse files zero on every
5793 * extend. 5771 * extend.
5794 */ 5772 */
5795 if (!ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) 5773 if (!ocfs2_sparse_alloc(OCFS2_SB(sb)))
5796 return 0; 5774 return 0;
5797 5775
5798 pages = kcalloc(ocfs2_pages_per_cluster(inode->i_sb), 5776 pages = kcalloc(ocfs2_pages_per_cluster(sb),
5799 sizeof(struct page *), GFP_NOFS); 5777 sizeof(struct page *), GFP_NOFS);
5800 if (pages == NULL) { 5778 if (pages == NULL) {
5801 ret = -ENOMEM; 5779 ret = -ENOMEM;
@@ -5803,15 +5781,30 @@ int ocfs2_zero_range_for_truncate(struct inode *inode, handle_t *handle,
5803 goto out; 5781 goto out;
5804 } 5782 }
5805 5783
5806 ret = ocfs2_grab_eof_pages(inode, range_start, range_end, pages, 5784 if (range_start == range_end)
5807 &numpages, &phys); 5785 goto out;
5786
5787 ret = ocfs2_extent_map_get_blocks(inode,
5788 range_start >> sb->s_blocksize_bits,
5789 &phys, NULL, &ext_flags);
5808 if (ret) { 5790 if (ret) {
5809 mlog_errno(ret); 5791 mlog_errno(ret);
5810 goto out; 5792 goto out;
5811 } 5793 }
5812 5794
5813 if (numpages == 0) 5795 /*
5796 * Tail is a hole, or is marked unwritten. In either case, we
5797 * can count on read and write to return/push zero's.
5798 */
5799 if (phys == 0 || ext_flags & OCFS2_EXT_UNWRITTEN)
5800 goto out;
5801
5802 ret = ocfs2_grab_eof_pages(inode, range_start, range_end, pages,
5803 &numpages);
5804 if (ret) {
5805 mlog_errno(ret);
5814 goto out; 5806 goto out;
5807 }
5815 5808
5816 ocfs2_zero_cluster_pages(inode, range_start, range_end, pages, 5809 ocfs2_zero_cluster_pages(inode, range_start, range_end, pages,
5817 numpages, phys, handle); 5810 numpages, phys, handle);
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index fae07672eb18..8416e383197c 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -830,18 +830,22 @@ struct ocfs2_write_ctxt {
830 struct ocfs2_cached_dealloc_ctxt w_dealloc; 830 struct ocfs2_cached_dealloc_ctxt w_dealloc;
831}; 831};
832 832
833static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc) 833void ocfs2_unlock_and_free_pages(struct page **pages, int num_pages)
834{ 834{
835 int i; 835 int i;
836 836
837 for(i = 0; i < wc->w_num_pages; i++) { 837 for(i = 0; i < num_pages; i++) {
838 if (wc->w_pages[i] == NULL) 838 if (pages[i]) {
839 continue; 839 unlock_page(pages[i]);
840 840 mark_page_accessed(pages[i]);
841 unlock_page(wc->w_pages[i]); 841 page_cache_release(pages[i]);
842 mark_page_accessed(wc->w_pages[i]); 842 }
843 page_cache_release(wc->w_pages[i]);
844 } 843 }
844}
845
846static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc)
847{
848 ocfs2_unlock_and_free_pages(wc->w_pages, wc->w_num_pages);
845 849
846 brelse(wc->w_di_bh); 850 brelse(wc->w_di_bh);
847 kfree(wc); 851 kfree(wc);
diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h
index 389579bd64e3..b4fa37d40db4 100644
--- a/fs/ocfs2/aops.h
+++ b/fs/ocfs2/aops.h
@@ -34,6 +34,8 @@ int ocfs2_map_page_blocks(struct page *page, u64 *p_blkno,
34 struct inode *inode, unsigned int from, 34 struct inode *inode, unsigned int from,
35 unsigned int to, int new); 35 unsigned int to, int new);
36 36
37void ocfs2_unlock_and_free_pages(struct page **pages, int num_pages);
38
37int walk_page_buffers( handle_t *handle, 39int walk_page_buffers( handle_t *handle,
38 struct buffer_head *head, 40 struct buffer_head *head,
39 unsigned from, 41 unsigned from,