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>
This commit is contained in:
Fan Li 2015-12-26 18:07:41 +08:00 committed by Jaegeuk Kim
parent 6d5a1495ee
commit 9a950d52b7

View File

@ -783,7 +783,6 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
loff_t isize = i_size_read(inode);
u64 logical = 0, phys = 0, size = 0;
u32 flags = 0;
bool past_eof = false, whole_file = false;
int ret = 0;
ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC);
@ -797,17 +796,18 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
}
mutex_lock(&inode->i_mutex);
if (start >= isize)
goto out;
if (len >= isize) {
whole_file = true;
len = isize;
}
if (start + len > isize)
len = isize - start;
if (logical_to_blk(inode, len) == 0)
len = blk_to_logical(inode, 1);
start_blk = logical_to_blk(inode, start);
last_blk = logical_to_blk(inode, start + len - 1);
next:
memset(&map_bh, 0, sizeof(struct buffer_head));
map_bh.b_size = len;
@ -819,59 +819,33 @@ next:
/* HOLE */
if (!buffer_mapped(&map_bh)) {
start_blk++;
if (!past_eof && blk_to_logical(inode, start_blk) >= isize)
past_eof = 1;
if (past_eof && size) {
flags |= FIEMAP_EXTENT_LAST;
ret = fiemap_fill_next_extent(fieinfo, logical,
phys, size, flags);
} else if (size) {
ret = fiemap_fill_next_extent(fieinfo, logical,
phys, size, flags);
size = 0;
}
/* if we have holes up to/past EOF then we're done */
if (start_blk > last_blk || past_eof || ret)
goto out;
} else {
if (start_blk > last_blk && !whole_file) {
ret = fiemap_fill_next_extent(fieinfo, logical,
phys, size, flags);
goto out;
}
/*
* if size != 0 then we know we already have an extent
* to add, so add it.
/* Go through holes util pass the EOF */
if (blk_to_logical(inode, start_blk++) < isize)
goto prep_next;
/* Found a hole beyond isize means no more extents.
* Note that the premise is that filesystems don't
* punch holes beyond isize and keep size unchanged.
*/
if (size) {
ret = fiemap_fill_next_extent(fieinfo, logical,
phys, size, flags);
if (ret)
goto out;
}
logical = blk_to_logical(inode, start_blk);
phys = blk_to_logical(inode, map_bh.b_blocknr);
size = map_bh.b_size;
flags = 0;
if (buffer_unwritten(&map_bh))
flags = FIEMAP_EXTENT_UNWRITTEN;
start_blk += logical_to_blk(inode, size);
/*
* If we are past the EOF, then we need to make sure as
* soon as we find a hole that the last extent we found
* is marked with FIEMAP_EXTENT_LAST
*/
if (!past_eof && logical + size >= isize)
past_eof = true;
flags |= FIEMAP_EXTENT_LAST;
}
if (size)
ret = fiemap_fill_next_extent(fieinfo, logical,
phys, size, flags);
if (start_blk > last_blk || ret)
goto out;
logical = blk_to_logical(inode, start_blk);
phys = blk_to_logical(inode, map_bh.b_blocknr);
size = map_bh.b_size;
flags = 0;
if (buffer_unwritten(&map_bh))
flags = FIEMAP_EXTENT_UNWRITTEN;
start_blk += logical_to_blk(inode, size);
prep_next:
cond_resched();
if (fatal_signal_pending(current))
ret = -EINTR;