aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMark Fasheh <mark.fasheh@oracle.com>2007-07-06 17:41:18 -0400
committerMark Fasheh <mark.fasheh@oracle.com>2007-07-10 20:32:07 -0400
commit35edec1d52c075975991471d624b33b9336226f2 (patch)
tree4fc59b9d60826b8eb44bc5c1e558a15bea171193 /fs
parentd0c7d7082ee1ec4f95ee57bf86ed39d1a27c4037 (diff)
ocfs2: update truncate handling of partial clusters
The partial cluster zeroing code used during truncate usually assumes that the rightmost byte in the range to be zeroed lies on a cluster boundary. This makes sense for truncate, but punching holes might require zeroing on non-aligned rightmost boundaries. Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/ocfs2/alloc.c72
-rw-r--r--fs/ocfs2/alloc.h4
-rw-r--r--fs/ocfs2/file.c5
3 files changed, 35 insertions, 46 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index fac1adb3880a..df186d2e8248 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -5668,9 +5668,9 @@ static int ocfs2_ordered_zero_func(handle_t *handle, struct buffer_head *bh)
5668 return ocfs2_journal_dirty_data(handle, bh); 5668 return ocfs2_journal_dirty_data(handle, bh);
5669} 5669}
5670 5670
5671static void ocfs2_zero_cluster_pages(struct inode *inode, loff_t isize, 5671static void ocfs2_zero_cluster_pages(struct inode *inode, loff_t start,
5672 struct page **pages, int numpages, 5672 loff_t end, struct page **pages,
5673 u64 phys, handle_t *handle) 5673 int numpages, u64 phys, handle_t *handle)
5674{ 5674{
5675 int i, ret, partial = 0; 5675 int i, ret, partial = 0;
5676 void *kaddr; 5676 void *kaddr;
@@ -5683,26 +5683,14 @@ static void ocfs2_zero_cluster_pages(struct inode *inode, loff_t isize,
5683 if (numpages == 0) 5683 if (numpages == 0)
5684 goto out; 5684 goto out;
5685 5685
5686 from = isize & (PAGE_CACHE_SIZE - 1); /* 1st page offset */ 5686 to = PAGE_CACHE_SIZE;
5687 if (PAGE_CACHE_SHIFT > OCFS2_SB(sb)->s_clustersize_bits) {
5688 /*
5689 * Since 'from' has been capped to a value below page
5690 * size, this calculation won't be able to overflow
5691 * 'to'
5692 */
5693 to = ocfs2_align_bytes_to_clusters(sb, from);
5694
5695 /*
5696 * The truncate tail in this case should never contain
5697 * more than one page at maximum. The loop below also
5698 * assumes this.
5699 */
5700 BUG_ON(numpages != 1);
5701 }
5702
5703 for(i = 0; i < numpages; i++) { 5687 for(i = 0; i < numpages; i++) {
5704 page = pages[i]; 5688 page = pages[i];
5705 5689
5690 from = start & (PAGE_CACHE_SIZE - 1);
5691 if ((end >> PAGE_CACHE_SHIFT) == page->index)
5692 to = end & (PAGE_CACHE_SIZE - 1);
5693
5706 BUG_ON(from > PAGE_CACHE_SIZE); 5694 BUG_ON(from > PAGE_CACHE_SIZE);
5707 BUG_ON(to > PAGE_CACHE_SIZE); 5695 BUG_ON(to > PAGE_CACHE_SIZE);
5708 5696
@@ -5739,10 +5727,7 @@ static void ocfs2_zero_cluster_pages(struct inode *inode, loff_t isize,
5739 5727
5740 flush_dcache_page(page); 5728 flush_dcache_page(page);
5741 5729
5742 /* 5730 start = (page->index + 1) << PAGE_CACHE_SHIFT;
5743 * Every page after the 1st one should be completely zero'd.
5744 */
5745 from = 0;
5746 } 5731 }
5747out: 5732out:
5748 if (pages) { 5733 if (pages) {
@@ -5755,24 +5740,26 @@ out:
5755 } 5740 }
5756} 5741}
5757 5742
5758static int ocfs2_grab_eof_pages(struct inode *inode, loff_t isize, struct page **pages, 5743static int ocfs2_grab_eof_pages(struct inode *inode, loff_t start, loff_t end,
5759 int *num, u64 *phys) 5744 struct page **pages, int *num, u64 *phys)
5760{ 5745{
5761 int i, numpages = 0, ret = 0; 5746 int i, numpages = 0, ret = 0;
5762 unsigned int csize = OCFS2_SB(inode->i_sb)->s_clustersize;
5763 unsigned int ext_flags; 5747 unsigned int ext_flags;
5764 struct super_block *sb = inode->i_sb; 5748 struct super_block *sb = inode->i_sb;
5765 struct address_space *mapping = inode->i_mapping; 5749 struct address_space *mapping = inode->i_mapping;
5766 unsigned long index; 5750 unsigned long index;
5767 u64 next_cluster_bytes; 5751 loff_t last_page_bytes;
5768 5752
5769 BUG_ON(!ocfs2_sparse_alloc(OCFS2_SB(sb))); 5753 BUG_ON(!ocfs2_sparse_alloc(OCFS2_SB(sb)));
5754 BUG_ON(start > end);
5770 5755
5771 /* Cluster boundary, so we don't need to grab any pages. */ 5756 if (start == end)
5772 if ((isize & (csize - 1)) == 0)
5773 goto out; 5757 goto out;
5774 5758
5775 ret = ocfs2_extent_map_get_blocks(inode, isize >> sb->s_blocksize_bits, 5759 BUG_ON(start >> OCFS2_SB(sb)->s_clustersize_bits !=
5760 (end - 1) >> OCFS2_SB(sb)->s_clustersize_bits);
5761
5762 ret = ocfs2_extent_map_get_blocks(inode, start >> sb->s_blocksize_bits,
5776 phys, NULL, &ext_flags); 5763 phys, NULL, &ext_flags);
5777 if (ret) { 5764 if (ret) {
5778 mlog_errno(ret); 5765 mlog_errno(ret);
@@ -5788,8 +5775,8 @@ static int ocfs2_grab_eof_pages(struct inode *inode, loff_t isize, struct page *
5788 if (ext_flags & OCFS2_EXT_UNWRITTEN) 5775 if (ext_flags & OCFS2_EXT_UNWRITTEN)
5789 goto out; 5776 goto out;
5790 5777
5791 next_cluster_bytes = ocfs2_align_bytes_to_clusters(inode->i_sb, isize); 5778 last_page_bytes = PAGE_ALIGN(end);
5792 index = isize >> PAGE_CACHE_SHIFT; 5779 index = start >> PAGE_CACHE_SHIFT;
5793 do { 5780 do {
5794 pages[numpages] = grab_cache_page(mapping, index); 5781 pages[numpages] = grab_cache_page(mapping, index);
5795 if (!pages[numpages]) { 5782 if (!pages[numpages]) {
@@ -5800,7 +5787,7 @@ static int ocfs2_grab_eof_pages(struct inode *inode, loff_t isize, struct page *
5800 5787
5801 numpages++; 5788 numpages++;
5802 index++; 5789 index++;
5803 } while (index < (next_cluster_bytes >> PAGE_CACHE_SHIFT)); 5790 } while (index < (last_page_bytes >> PAGE_CACHE_SHIFT));
5804 5791
5805out: 5792out:
5806 if (ret != 0) { 5793 if (ret != 0) {
@@ -5829,11 +5816,10 @@ out:
5829 * otherwise block_write_full_page() will skip writeout of pages past 5816 * otherwise block_write_full_page() will skip writeout of pages past
5830 * i_size. The new_i_size parameter is passed for this reason. 5817 * i_size. The new_i_size parameter is passed for this reason.
5831 */ 5818 */
5832int ocfs2_zero_tail_for_truncate(struct inode *inode, handle_t *handle, 5819int ocfs2_zero_range_for_truncate(struct inode *inode, handle_t *handle,
5833 u64 new_i_size) 5820 u64 range_start, u64 range_end)
5834{ 5821{
5835 int ret, numpages; 5822 int ret, numpages;
5836 loff_t endbyte;
5837 struct page **pages = NULL; 5823 struct page **pages = NULL;
5838 u64 phys; 5824 u64 phys;
5839 5825
@@ -5852,7 +5838,8 @@ int ocfs2_zero_tail_for_truncate(struct inode *inode, handle_t *handle,
5852 goto out; 5838 goto out;
5853 } 5839 }
5854 5840
5855 ret = ocfs2_grab_eof_pages(inode, new_i_size, pages, &numpages, &phys); 5841 ret = ocfs2_grab_eof_pages(inode, range_start, range_end, pages,
5842 &numpages, &phys);
5856 if (ret) { 5843 if (ret) {
5857 mlog_errno(ret); 5844 mlog_errno(ret);
5858 goto out; 5845 goto out;
@@ -5861,17 +5848,16 @@ int ocfs2_zero_tail_for_truncate(struct inode *inode, handle_t *handle,
5861 if (numpages == 0) 5848 if (numpages == 0)
5862 goto out; 5849 goto out;
5863 5850
5864 ocfs2_zero_cluster_pages(inode, new_i_size, pages, numpages, phys, 5851 ocfs2_zero_cluster_pages(inode, range_start, range_end, pages,
5865 handle); 5852 numpages, phys, handle);
5866 5853
5867 /* 5854 /*
5868 * Initiate writeout of the pages we zero'd here. We don't 5855 * Initiate writeout of the pages we zero'd here. We don't
5869 * wait on them - the truncate_inode_pages() call later will 5856 * wait on them - the truncate_inode_pages() call later will
5870 * do that for us. 5857 * do that for us.
5871 */ 5858 */
5872 endbyte = ocfs2_align_bytes_to_clusters(inode->i_sb, new_i_size); 5859 ret = do_sync_mapping_range(inode->i_mapping, range_start,
5873 ret = do_sync_mapping_range(inode->i_mapping, new_i_size, 5860 range_end - 1, SYNC_FILE_RANGE_WRITE);
5874 endbyte - 1, SYNC_FILE_RANGE_WRITE);
5875 if (ret) 5861 if (ret)
5876 mlog_errno(ret); 5862 mlog_errno(ret);
5877 5863
diff --git a/fs/ocfs2/alloc.h b/fs/ocfs2/alloc.h
index e3284f3eb6b9..752ef860873d 100644
--- a/fs/ocfs2/alloc.h
+++ b/fs/ocfs2/alloc.h
@@ -95,8 +95,8 @@ struct ocfs2_truncate_context {
95 struct buffer_head *tc_last_eb_bh; 95 struct buffer_head *tc_last_eb_bh;
96}; 96};
97 97
98int ocfs2_zero_tail_for_truncate(struct inode *inode, handle_t *handle, 98int ocfs2_zero_range_for_truncate(struct inode *inode, handle_t *handle,
99 u64 new_i_size); 99 u64 range_start, u64 range_end);
100int ocfs2_prepare_truncate(struct ocfs2_super *osb, 100int ocfs2_prepare_truncate(struct ocfs2_super *osb,
101 struct inode *inode, 101 struct inode *inode,
102 struct buffer_head *fe_bh, 102 struct buffer_head *fe_bh,
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 3e21ad9a6dde..f0a6b1330a6e 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -263,6 +263,7 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb,
263 int status; 263 int status;
264 handle_t *handle; 264 handle_t *handle;
265 struct ocfs2_dinode *di; 265 struct ocfs2_dinode *di;
266 u64 cluster_bytes;
266 267
267 mlog_entry_void(); 268 mlog_entry_void();
268 269
@@ -286,7 +287,9 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb,
286 /* 287 /*
287 * Do this before setting i_size. 288 * Do this before setting i_size.
288 */ 289 */
289 status = ocfs2_zero_tail_for_truncate(inode, handle, new_i_size); 290 cluster_bytes = ocfs2_align_bytes_to_clusters(inode->i_sb, new_i_size);
291 status = ocfs2_zero_range_for_truncate(inode, handle, new_i_size,
292 cluster_bytes);
290 if (status) { 293 if (status) {
291 mlog_errno(status); 294 mlog_errno(status);
292 goto out_commit; 295 goto out_commit;