aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/extents.c
diff options
context:
space:
mode:
authorYongqiang Yang <xiaoqiangnk@gmail.com>2011-05-24 11:36:58 -0400
committerTheodore Ts'o <tytso@mit.edu>2011-05-24 11:36:58 -0400
commitb221349fa8b45d13c3650089f0514df7d1eb36c3 (patch)
tree5fb5e797c3f05294dd2e9352c05bb20b29a95d16 /fs/ext4/extents.c
parent072bd7ea74d4b60149a33967d29666bbd84e7709 (diff)
ext4: fix ext4_ext_fiemap_cb() to handle blocks before request range correctly
To get delayed-extent information, ext4_ext_fiemap_cb() looks up pagecache, it thus collects information starting from a page's head block. If blocksize < pagesize, the beginning blocks of a page may lies before the request range. So ext4_ext_fiemap_cb() should proceed ignoring them, because they has been handled before. If no mapped buffer in the range is found in the 1st page, we need to look up the 2nd page, otherwise delayed-extents after a hole will be ignored. Without this patch, xfstests 225 will hung on ext4 with 1K block. Reported-by: Amir Goldstein <amir73il@users.sourceforge.net> Signed-off-by: Yongqiang Yang <xiaoqiangnk@gmail.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r--fs/ext4/extents.c49
1 files changed, 35 insertions, 14 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 4e2bdc26b85c..ca62d748cc65 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -3688,6 +3688,7 @@ static int ext4_ext_fiemap_cb(struct inode *inode, struct ext4_ext_path *path,
3688 pgoff_t last_offset; 3688 pgoff_t last_offset;
3689 pgoff_t offset; 3689 pgoff_t offset;
3690 pgoff_t index; 3690 pgoff_t index;
3691 pgoff_t start_index = 0;
3691 struct page **pages = NULL; 3692 struct page **pages = NULL;
3692 struct buffer_head *bh = NULL; 3693 struct buffer_head *bh = NULL;
3693 struct buffer_head *head = NULL; 3694 struct buffer_head *head = NULL;
@@ -3714,39 +3715,57 @@ out:
3714 kfree(pages); 3715 kfree(pages);
3715 return EXT_CONTINUE; 3716 return EXT_CONTINUE;
3716 } 3717 }
3718 index = 0;
3717 3719
3720next_page:
3718 /* Try to find the 1st mapped buffer. */ 3721 /* Try to find the 1st mapped buffer. */
3719 end = ((__u64)pages[0]->index << PAGE_SHIFT) >> 3722 end = ((__u64)pages[index]->index << PAGE_SHIFT) >>
3720 blksize_bits; 3723 blksize_bits;
3721 if (!page_has_buffers(pages[0])) 3724 if (!page_has_buffers(pages[index]))
3722 goto out; 3725 goto out;
3723 head = page_buffers(pages[0]); 3726 head = page_buffers(pages[index]);
3724 if (!head) 3727 if (!head)
3725 goto out; 3728 goto out;
3726 3729
3730 index++;
3727 bh = head; 3731 bh = head;
3728 do { 3732 do {
3729 if (buffer_mapped(bh)) { 3733 if (end >= newex->ec_block +
3734 newex->ec_len)
3735 /* The buffer is out of
3736 * the request range.
3737 */
3738 goto out;
3739
3740 if (buffer_mapped(bh) &&
3741 end >= newex->ec_block) {
3742 start_index = index - 1;
3730 /* get the 1st mapped buffer. */ 3743 /* get the 1st mapped buffer. */
3731 if (end > newex->ec_block +
3732 newex->ec_len)
3733 /* The buffer is out of
3734 * the request range.
3735 */
3736 goto out;
3737 goto found_mapped_buffer; 3744 goto found_mapped_buffer;
3738 } 3745 }
3746
3739 bh = bh->b_this_page; 3747 bh = bh->b_this_page;
3740 end++; 3748 end++;
3741 } while (bh != head); 3749 } while (bh != head);
3742 3750
3743 /* No mapped buffer found. */ 3751 /* No mapped buffer in the range found in this page,
3744 goto out; 3752 * We need to look up next page.
3753 */
3754 if (index >= ret) {
3755 /* There is no page left, but we need to limit
3756 * newex->ec_len.
3757 */
3758 newex->ec_len = end - newex->ec_block;
3759 goto out;
3760 }
3761 goto next_page;
3745 } else { 3762 } else {
3746 /*Find contiguous delayed buffers. */ 3763 /*Find contiguous delayed buffers. */
3747 if (ret > 0 && pages[0]->index == last_offset) 3764 if (ret > 0 && pages[0]->index == last_offset)
3748 head = page_buffers(pages[0]); 3765 head = page_buffers(pages[0]);
3749 bh = head; 3766 bh = head;
3767 index = 1;
3768 start_index = 0;
3750 } 3769 }
3751 3770
3752found_mapped_buffer: 3771found_mapped_buffer:
@@ -3769,7 +3788,7 @@ found_mapped_buffer:
3769 end++; 3788 end++;
3770 } while (bh != head); 3789 } while (bh != head);
3771 3790
3772 for (index = 1; index < ret; index++) { 3791 for (; index < ret; index++) {
3773 if (!page_has_buffers(pages[index])) { 3792 if (!page_has_buffers(pages[index])) {
3774 bh = NULL; 3793 bh = NULL;
3775 break; 3794 break;
@@ -3779,8 +3798,10 @@ found_mapped_buffer:
3779 bh = NULL; 3798 bh = NULL;
3780 break; 3799 break;
3781 } 3800 }
3801
3782 if (pages[index]->index != 3802 if (pages[index]->index !=
3783 pages[0]->index + index) { 3803 pages[start_index]->index + index
3804 - start_index) {
3784 /* Blocks are not contiguous. */ 3805 /* Blocks are not contiguous. */
3785 bh = NULL; 3806 bh = NULL;
3786 break; 3807 break;