diff options
| -rw-r--r-- | fs/ocfs2/alloc.c | 72 | ||||
| -rw-r--r-- | fs/ocfs2/alloc.h | 4 | ||||
| -rw-r--r-- | fs/ocfs2/file.c | 5 |
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 | ||
| 5671 | static void ocfs2_zero_cluster_pages(struct inode *inode, loff_t isize, | 5671 | static 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 | } |
| 5747 | out: | 5732 | out: |
| 5748 | if (pages) { | 5733 | if (pages) { |
| @@ -5755,24 +5740,26 @@ out: | |||
| 5755 | } | 5740 | } |
| 5756 | } | 5741 | } |
| 5757 | 5742 | ||
| 5758 | static int ocfs2_grab_eof_pages(struct inode *inode, loff_t isize, struct page **pages, | 5743 | static 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 | ||
| 5805 | out: | 5792 | out: |
| 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 | */ |
| 5832 | int ocfs2_zero_tail_for_truncate(struct inode *inode, handle_t *handle, | 5819 | int 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 | ||
| 98 | int ocfs2_zero_tail_for_truncate(struct inode *inode, handle_t *handle, | 98 | int ocfs2_zero_range_for_truncate(struct inode *inode, handle_t *handle, |
| 99 | u64 new_i_size); | 99 | u64 range_start, u64 range_end); |
| 100 | int ocfs2_prepare_truncate(struct ocfs2_super *osb, | 100 | int 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; |
