diff options
author | Ryan Ding <ryan.ding@oracle.com> | 2016-03-25 17:21:20 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-25 19:37:42 -0400 |
commit | ce170828e24959c69e7a40364731edc0535c550f (patch) | |
tree | 2b05b56f6aae6888099a358422c8308d3ac94fc9 /fs/ocfs2/aops.c | |
parent | a86a72a4a4e0ec109a98e2737948864ed6794bf7 (diff) |
ocfs2: fix disk file size and memory file size mismatch
When doing append direct write in an already allocated cluster, and fast
path in ocfs2_dio_get_block() is triggered, function
ocfs2_dio_end_io_write() will be skipped as there is no context
allocated.
As a result, the disk file size will not be changed as it should be.
The solution is to skip fast path when we are about to change file size.
Fixes: af1310367f41 ("ocfs2: fix sparse file & data ordering issue in direct io.")
Signed-off-by: Ryan Ding <ryan.ding@oracle.com>
Acked-by: Junxiao Bi <junxiao.bi@oracle.com>
Cc: Joseph Qi <joseph.qi@huawei.com>
Cc: Mark Fasheh <mfasheh@suse.de>
Cc: Joel Becker <jlbec@evilplan.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ocfs2/aops.c')
-rw-r--r-- | fs/ocfs2/aops.c | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 0f3816325808..328ac7f99d52 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -2167,19 +2167,26 @@ static int ocfs2_dio_get_block(struct inode *inode, sector_t iblock, | |||
2167 | mlog(0, "get block of %lu at %llu:%u req %u\n", | 2167 | mlog(0, "get block of %lu at %llu:%u req %u\n", |
2168 | inode->i_ino, pos, len, total_len); | 2168 | inode->i_ino, pos, len, total_len); |
2169 | 2169 | ||
2170 | down_read(&oi->ip_alloc_sem); | 2170 | /* |
2171 | /* This is the fast path for re-write. */ | 2171 | * Because we need to change file size in ocfs2_dio_end_io_write(), or |
2172 | ret = ocfs2_get_block(inode, iblock, bh_result, create); | 2172 | * we may need to add it to orphan dir. So can not fall to fast path |
2173 | * while file size will be changed. | ||
2174 | */ | ||
2175 | if (pos + total_len <= i_size_read(inode)) { | ||
2176 | down_read(&oi->ip_alloc_sem); | ||
2177 | /* This is the fast path for re-write. */ | ||
2178 | ret = ocfs2_get_block(inode, iblock, bh_result, create); | ||
2173 | 2179 | ||
2174 | up_read(&oi->ip_alloc_sem); | 2180 | up_read(&oi->ip_alloc_sem); |
2175 | 2181 | ||
2176 | if (buffer_mapped(bh_result) && | 2182 | if (buffer_mapped(bh_result) && |
2177 | !buffer_new(bh_result) && | 2183 | !buffer_new(bh_result) && |
2178 | ret == 0) | 2184 | ret == 0) |
2179 | goto out; | 2185 | goto out; |
2180 | 2186 | ||
2181 | /* Clear state set by ocfs2_get_block. */ | 2187 | /* Clear state set by ocfs2_get_block. */ |
2182 | bh_result->b_state = 0; | 2188 | bh_result->b_state = 0; |
2189 | } | ||
2183 | 2190 | ||
2184 | dwc = ocfs2_dio_alloc_write_ctx(bh_result, &first_get_block); | 2191 | dwc = ocfs2_dio_alloc_write_ctx(bh_result, &first_get_block); |
2185 | if (unlikely(dwc == NULL)) { | 2192 | if (unlikely(dwc == NULL)) { |