diff options
author | Dmitry Monakhov <dmonakhov@openvz.org> | 2014-08-27 18:40:03 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2014-08-28 22:20:41 -0400 |
commit | 6603120e96eae9a5d6228681ae55c7fdc998d1bb (patch) | |
tree | 7be8007807786ae2437e62c374f8fded7682b65e /fs | |
parent | c174e6d6979a04b7b77b93f244396be4b81f8bfb (diff) |
ext4: update i_disksize coherently with block allocation on error path
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>
Cc: stable@vger.kernel.org
Diffstat (limited to 'fs')
-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 b1ddd9352644..3aa26e9117c4 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -2077,6 +2077,7 @@ static int mpage_map_and_submit_extent(handle_t *handle, | |||
2077 | struct ext4_map_blocks *map = &mpd->map; | 2077 | struct ext4_map_blocks *map = &mpd->map; |
2078 | int err; | 2078 | int err; |
2079 | loff_t disksize; | 2079 | loff_t disksize; |
2080 | int progress = 0; | ||
2080 | 2081 | ||
2081 | mpd->io_submit.io_end->offset = | 2082 | mpd->io_submit.io_end->offset = |
2082 | ((loff_t)map->m_lblk) << inode->i_blkbits; | 2083 | ((loff_t)map->m_lblk) << inode->i_blkbits; |
@@ -2093,8 +2094,11 @@ static int mpage_map_and_submit_extent(handle_t *handle, | |||
2093 | * is non-zero, a commit should free up blocks. | 2094 | * is non-zero, a commit should free up blocks. |
2094 | */ | 2095 | */ |
2095 | if ((err == -ENOMEM) || | 2096 | if ((err == -ENOMEM) || |
2096 | (err == -ENOSPC && ext4_count_free_clusters(sb))) | 2097 | (err == -ENOSPC && ext4_count_free_clusters(sb))) { |
2098 | if (progress) | ||
2099 | goto update_disksize; | ||
2097 | return err; | 2100 | return err; |
2101 | } | ||
2098 | ext4_msg(sb, KERN_CRIT, | 2102 | ext4_msg(sb, KERN_CRIT, |
2099 | "Delayed block allocation failed for " | 2103 | "Delayed block allocation failed for " |
2100 | "inode %lu at logical offset %llu with" | 2104 | "inode %lu at logical offset %llu with" |
@@ -2111,15 +2115,17 @@ static int mpage_map_and_submit_extent(handle_t *handle, | |||
2111 | *give_up_on_write = true; | 2115 | *give_up_on_write = true; |
2112 | return err; | 2116 | return err; |
2113 | } | 2117 | } |
2118 | progress = 1; | ||
2114 | /* | 2119 | /* |
2115 | * Update buffer state, submit mapped pages, and get us new | 2120 | * Update buffer state, submit mapped pages, and get us new |
2116 | * extent to map | 2121 | * extent to map |
2117 | */ | 2122 | */ |
2118 | err = mpage_map_and_submit_buffers(mpd); | 2123 | err = mpage_map_and_submit_buffers(mpd); |
2119 | if (err < 0) | 2124 | if (err < 0) |
2120 | return err; | 2125 | goto update_disksize; |
2121 | } while (map->m_len); | 2126 | } while (map->m_len); |
2122 | 2127 | ||
2128 | update_disksize: | ||
2123 | /* | 2129 | /* |
2124 | * Update on-disk size after IO is submitted. Races with | 2130 | * Update on-disk size after IO is submitted. Races with |
2125 | * truncate are avoided by checking i_size under i_data_sem. | 2131 | * truncate are avoided by checking i_size under i_data_sem. |