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>
This commit is contained in:
parent
a86a72a4a4
commit
ce170828e2
1 changed files with 17 additions and 10 deletions
|
@ -2167,19 +2167,26 @@ static int ocfs2_dio_get_block(struct inode *inode, sector_t iblock,
|
|||
mlog(0, "get block of %lu at %llu:%u req %u\n",
|
||||
inode->i_ino, pos, len, total_len);
|
||||
|
||||
down_read(&oi->ip_alloc_sem);
|
||||
/* This is the fast path for re-write. */
|
||||
ret = ocfs2_get_block(inode, iblock, bh_result, create);
|
||||
/*
|
||||
* Because we need to change file size in ocfs2_dio_end_io_write(), or
|
||||
* we may need to add it to orphan dir. So can not fall to fast path
|
||||
* while file size will be changed.
|
||||
*/
|
||||
if (pos + total_len <= i_size_read(inode)) {
|
||||
down_read(&oi->ip_alloc_sem);
|
||||
/* This is the fast path for re-write. */
|
||||
ret = ocfs2_get_block(inode, iblock, bh_result, create);
|
||||
|
||||
up_read(&oi->ip_alloc_sem);
|
||||
up_read(&oi->ip_alloc_sem);
|
||||
|
||||
if (buffer_mapped(bh_result) &&
|
||||
!buffer_new(bh_result) &&
|
||||
ret == 0)
|
||||
goto out;
|
||||
if (buffer_mapped(bh_result) &&
|
||||
!buffer_new(bh_result) &&
|
||||
ret == 0)
|
||||
goto out;
|
||||
|
||||
/* Clear state set by ocfs2_get_block. */
|
||||
bh_result->b_state = 0;
|
||||
/* Clear state set by ocfs2_get_block. */
|
||||
bh_result->b_state = 0;
|
||||
}
|
||||
|
||||
dwc = ocfs2_dio_alloc_write_ctx(bh_result, &first_get_block);
|
||||
if (unlikely(dwc == NULL)) {
|
||||
|
|
Loading…
Reference in a new issue