diff options
author | Fan Li <fanofcode.li@samsung.com> | 2015-12-26 05:07:41 -0500 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2015-12-30 13:14:16 -0500 |
commit | 9a950d52b7f0e1c64c2cc70d350562fb18c8b451 (patch) | |
tree | 2dabc8cc670cc4aa93561f753d0f723941a9f564 /fs/f2fs/data.c | |
parent | 6d5a1495eebd441216dc96913a4270100b26e104 (diff) |
f2fs: fix bugs and simplify codes of f2fs_fiemap
fix bugs:
1. len could be updated incorrectly when start+len is beyond isize.
2. If there is a hole consisting of more than two blocks, it could
fail to add FIEMAP_EXTENT_LAST flag for the last extent.
3. If there is an extent beyond isize, when we search extents in a range
that ends at isize, it will also return the extent beyond isize,
which is outside the range.
Signed-off-by: Fan li <fanofcode.li@samsung.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fs/f2fs/data.c')
-rw-r--r-- | fs/f2fs/data.c | 80 |
1 files changed, 27 insertions, 53 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 5c43b2d606ec..d67c599510d9 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c | |||
@@ -783,7 +783,6 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
783 | loff_t isize = i_size_read(inode); | 783 | loff_t isize = i_size_read(inode); |
784 | u64 logical = 0, phys = 0, size = 0; | 784 | u64 logical = 0, phys = 0, size = 0; |
785 | u32 flags = 0; | 785 | u32 flags = 0; |
786 | bool past_eof = false, whole_file = false; | ||
787 | int ret = 0; | 786 | int ret = 0; |
788 | 787 | ||
789 | ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC); | 788 | ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC); |
@@ -797,17 +796,18 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
797 | } | 796 | } |
798 | 797 | ||
799 | mutex_lock(&inode->i_mutex); | 798 | mutex_lock(&inode->i_mutex); |
799 | if (start >= isize) | ||
800 | goto out; | ||
800 | 801 | ||
801 | if (len >= isize) { | 802 | if (start + len > isize) |
802 | whole_file = true; | 803 | len = isize - start; |
803 | len = isize; | ||
804 | } | ||
805 | 804 | ||
806 | if (logical_to_blk(inode, len) == 0) | 805 | if (logical_to_blk(inode, len) == 0) |
807 | len = blk_to_logical(inode, 1); | 806 | len = blk_to_logical(inode, 1); |
808 | 807 | ||
809 | start_blk = logical_to_blk(inode, start); | 808 | start_blk = logical_to_blk(inode, start); |
810 | last_blk = logical_to_blk(inode, start + len - 1); | 809 | last_blk = logical_to_blk(inode, start + len - 1); |
810 | |||
811 | next: | 811 | next: |
812 | memset(&map_bh, 0, sizeof(struct buffer_head)); | 812 | memset(&map_bh, 0, sizeof(struct buffer_head)); |
813 | map_bh.b_size = len; | 813 | map_bh.b_size = len; |
@@ -819,59 +819,33 @@ next: | |||
819 | 819 | ||
820 | /* HOLE */ | 820 | /* HOLE */ |
821 | if (!buffer_mapped(&map_bh)) { | 821 | if (!buffer_mapped(&map_bh)) { |
822 | start_blk++; | 822 | /* Go through holes util pass the EOF */ |
823 | 823 | if (blk_to_logical(inode, start_blk++) < isize) | |
824 | if (!past_eof && blk_to_logical(inode, start_blk) >= isize) | 824 | goto prep_next; |
825 | past_eof = 1; | 825 | /* Found a hole beyond isize means no more extents. |
826 | 826 | * Note that the premise is that filesystems don't | |
827 | if (past_eof && size) { | 827 | * punch holes beyond isize and keep size unchanged. |
828 | flags |= FIEMAP_EXTENT_LAST; | 828 | */ |
829 | ret = fiemap_fill_next_extent(fieinfo, logical, | 829 | flags |= FIEMAP_EXTENT_LAST; |
830 | phys, size, flags); | 830 | } |
831 | } else if (size) { | ||
832 | ret = fiemap_fill_next_extent(fieinfo, logical, | ||
833 | phys, size, flags); | ||
834 | size = 0; | ||
835 | } | ||
836 | 831 | ||
837 | /* if we have holes up to/past EOF then we're done */ | 832 | if (size) |
838 | if (start_blk > last_blk || past_eof || ret) | 833 | ret = fiemap_fill_next_extent(fieinfo, logical, |
839 | goto out; | 834 | phys, size, flags); |
840 | } else { | ||
841 | if (start_blk > last_blk && !whole_file) { | ||
842 | ret = fiemap_fill_next_extent(fieinfo, logical, | ||
843 | phys, size, flags); | ||
844 | goto out; | ||
845 | } | ||
846 | 835 | ||
847 | /* | 836 | if (start_blk > last_blk || ret) |
848 | * if size != 0 then we know we already have an extent | 837 | goto out; |
849 | * to add, so add it. | ||
850 | */ | ||
851 | if (size) { | ||
852 | ret = fiemap_fill_next_extent(fieinfo, logical, | ||
853 | phys, size, flags); | ||
854 | if (ret) | ||
855 | goto out; | ||
856 | } | ||
857 | 838 | ||
858 | logical = blk_to_logical(inode, start_blk); | 839 | logical = blk_to_logical(inode, start_blk); |
859 | phys = blk_to_logical(inode, map_bh.b_blocknr); | 840 | phys = blk_to_logical(inode, map_bh.b_blocknr); |
860 | size = map_bh.b_size; | 841 | size = map_bh.b_size; |
861 | flags = 0; | 842 | flags = 0; |
862 | if (buffer_unwritten(&map_bh)) | 843 | if (buffer_unwritten(&map_bh)) |
863 | flags = FIEMAP_EXTENT_UNWRITTEN; | 844 | flags = FIEMAP_EXTENT_UNWRITTEN; |
864 | 845 | ||
865 | start_blk += logical_to_blk(inode, size); | 846 | start_blk += logical_to_blk(inode, size); |
866 | 847 | ||
867 | /* | 848 | prep_next: |
868 | * If we are past the EOF, then we need to make sure as | ||
869 | * soon as we find a hole that the last extent we found | ||
870 | * is marked with FIEMAP_EXTENT_LAST | ||
871 | */ | ||
872 | if (!past_eof && logical + size >= isize) | ||
873 | past_eof = true; | ||
874 | } | ||
875 | cond_resched(); | 849 | cond_resched(); |
876 | if (fatal_signal_pending(current)) | 850 | if (fatal_signal_pending(current)) |
877 | ret = -EINTR; | 851 | ret = -EINTR; |