Commit c03f8aa9abdd517477c2021ea1251939b4da49e6

Authored by Lukas Czerner
Committed by Theodore Ts'o
1 parent f17722f917

ext4: use FIEMAP_EXTENT_LAST flag for last extent in fiemap

Currently we are not marking the extent as the last one
(FIEMAP_EXTENT_LAST) if there is a hole at the end of the file. This is
because we just do not check for it right now and continue searching for
next extent. But at the point we hit the hole at the end of the file, it
is too late.

This commit adds check for the allocated block in subsequent extent and
if there is no more extents (block = EXT_MAX_BLOCKS) just flag the
current one as the last one.

This behaviour has been spotted unintentionally by 252 xfstest, when the
test hangs out, because of wrong loop condition. However on other
filesystems (like xfs) it will exit anyway, because we notice the last
extent flag and exit.

With this patch xfstest 252 does not hang anymore, ext4 fiemap
implementation still reports bad extent type in some cases, however
this seems to be different issue.

Signed-off-by: Lukas Czerner <lczerner@redhat.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>

Showing 2 changed files with 4 additions and 6 deletions Side-by-side Diff

fs/ext4/ext4_extents.h
... ... @@ -125,7 +125,7 @@
125 125 * positive retcode - signal for ext4_ext_walk_space(), see below
126 126 * callback must return valid extent (passed or newly created)
127 127 */
128   -typedef int (*ext_prepare_callback)(struct inode *, struct ext4_ext_path *,
  128 +typedef int (*ext_prepare_callback)(struct inode *, ext4_lblk_t,
129 129 struct ext4_ext_cache *,
130 130 struct ext4_extent *, void *);
131 131  
... ... @@ -1958,7 +1958,7 @@
1958 1958 err = -EIO;
1959 1959 break;
1960 1960 }
1961   - err = func(inode, path, &cbex, ex, cbdata);
  1961 + err = func(inode, next, &cbex, ex, cbdata);
1962 1962 ext4_ext_drop_refs(path);
1963 1963  
1964 1964 if (err < 0)
1965 1965  
... ... @@ -3914,14 +3914,13 @@
3914 3914 /*
3915 3915 * Callback function called for each extent to gather FIEMAP information.
3916 3916 */
3917   -static int ext4_ext_fiemap_cb(struct inode *inode, struct ext4_ext_path *path,
  3917 +static int ext4_ext_fiemap_cb(struct inode *inode, ext4_lblk_t next,
3918 3918 struct ext4_ext_cache *newex, struct ext4_extent *ex,
3919 3919 void *data)
3920 3920 {
3921 3921 __u64 logical;
3922 3922 __u64 physical;
3923 3923 __u64 length;
3924   - loff_t size;
3925 3924 __u32 flags = 0;
3926 3925 int ret = 0;
3927 3926 struct fiemap_extent_info *fieinfo = data;
... ... @@ -4103,8 +4102,7 @@
4103 4102 if (ex && ext4_ext_is_uninitialized(ex))
4104 4103 flags |= FIEMAP_EXTENT_UNWRITTEN;
4105 4104  
4106   - size = i_size_read(inode);
4107   - if (logical + length >= size)
  4105 + if (next == EXT_MAX_BLOCKS)
4108 4106 flags |= FIEMAP_EXTENT_LAST;
4109 4107  
4110 4108 ret = fiemap_fill_next_extent(fieinfo, logical, physical,