summaryrefslogtreecommitdiff
path: root/fs/gfs2/file.c
diff options
context:
space:
mode:
authorAndrew Price <anprice@redhat.com>2014-11-12 17:24:04 +0000
committerSteven Whitehouse <swhiteho@redhat.com>2014-11-14 14:15:04 +0000
commit1885867b84d58e3704ed175e0abac2f38889f34d (patch)
treed4b37a4e65553290d4c2323f14f10f8d9a621e5e /fs/gfs2/file.c
parent9c9f1159a54c6163dd0b9d2085985d3c98dad11f (diff)
GFS2: Update i_size properly on fallocate
This addresses an issue caught by fsx where the inode size was not being updated to the expected value after fallocate(2) with mode 0. The problem was caused by the offset and len parameters being converted to multiples of the file system's block size, so i_size would be rounded up to the nearest block size multiple instead of the requested size. This replaces the per-chunk i_size updates with a single i_size_write on successful completion of the operation. With this patch gfs2 gets through a complete run of fsx. For clarity, the check for (error == 0) following the loop is removed as all failures before that point jump to out_* labels or return. Signed-off-by: Andrew Price <anprice@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/file.c')
-rw-r--r--fs/gfs2/file.c15
1 files changed, 6 insertions, 9 deletions
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index 3786579dd348..118216419cef 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -729,7 +729,6 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
struct gfs2_inode *ip = GFS2_I(inode);
struct buffer_head *dibh;
int error;
- loff_t size = len;
unsigned int nr_blks;
sector_t lblock = offset >> inode->i_blkbits;
@@ -763,11 +762,6 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
goto out;
}
}
- if (offset + size > inode->i_size && !(mode & FALLOC_FL_KEEP_SIZE))
- i_size_write(inode, offset + size);
-
- mark_inode_dirty(inode);
-
out:
brelse(dibh);
return error;
@@ -878,9 +872,12 @@ retry:
gfs2_quota_unlock(ip);
}
- if (error == 0)
- error = generic_write_sync(file, pos, count);
- return error;
+ if (!(mode & FALLOC_FL_KEEP_SIZE) && (pos + count) > inode->i_size) {
+ i_size_write(inode, pos + count);
+ mark_inode_dirty(inode);
+ }
+
+ return generic_write_sync(file, pos, count);
out_trans_fail:
gfs2_inplace_release(ip);