diff options
author | Dmitry Monakhov <dmonakhov@openvz.org> | 2014-08-27 18:40:03 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-09-05 16:34:17 -0700 |
commit | 08dc1706c61301a0476284edabd06618e9567674 (patch) | |
tree | 4a4270e5f8d30a2b7451838650a3312e97bf00f8 /fs/ext4 | |
parent | 3e6c4753bc410f788d81566d6d915f26ff315ba2 (diff) |
ext4: update i_disksize coherently with block allocation on error path
commit 6603120e96eae9a5d6228681ae55c7fdc998d1bb upstream.
In case of delalloc block i_disksize may be less than i_size. So we
have to update i_disksize each time we allocated and submitted some
blocks beyond i_disksize. We weren't doing this on the error paths,
so fix this.
testcase: xfstest generic/019
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/inode.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index a7029f481b7b..b56062dc8b62 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2195,6 +2195,7 @@ static int mpage_map_and_submit_extent(handle_t *handle, struct ext4_map_blocks *map = &mpd->map; int err; loff_t disksize; + int progress = 0; mpd->io_submit.io_end->offset = ((loff_t)map->m_lblk) << inode->i_blkbits; @@ -2211,8 +2212,11 @@ static int mpage_map_and_submit_extent(handle_t *handle, * is non-zero, a commit should free up blocks. */ if ((err == -ENOMEM) || - (err == -ENOSPC && ext4_count_free_clusters(sb))) + (err == -ENOSPC && ext4_count_free_clusters(sb))) { + if (progress) + goto update_disksize; return err; + } ext4_msg(sb, KERN_CRIT, "Delayed block allocation failed for " "inode %lu at logical offset %llu with" @@ -2229,15 +2233,17 @@ static int mpage_map_and_submit_extent(handle_t *handle, *give_up_on_write = true; return err; } + progress = 1; /* * Update buffer state, submit mapped pages, and get us new * extent to map */ err = mpage_map_and_submit_buffers(mpd); if (err < 0) - return err; + goto update_disksize; } while (map->m_len); +update_disksize: /* * Update on-disk size after IO is submitted. Races with * truncate are avoided by checking i_size under i_data_sem. |