diff options
author | Andreas Gruenbacher <agruenba@redhat.com> | 2022-04-14 17:52:39 +0200 |
---|---|---|
committer | Andreas Gruenbacher <agruenba@redhat.com> | 2022-05-13 21:59:18 +0200 |
commit | d031a8866e709c9d1ee5537a321b6192b4d2dc5b (patch) | |
tree | ccd7942b2ac3df85369219f0352b2b3edff4d524 /fs/gfs2 | |
parent | 4a2316a1eda4ef3ced18c7f08f7cb3726bcae44b (diff) | |
download | linux-stable-d031a8866e709c9d1ee5537a321b6192b4d2dc5b.tar.gz linux-stable-d031a8866e709c9d1ee5537a321b6192b4d2dc5b.tar.bz2 linux-stable-d031a8866e709c9d1ee5537a321b6192b4d2dc5b.zip |
gfs2: Fix filesystem block deallocation for short writes
When a write cannot be carried out in full, gfs2_iomap_end() releases
blocks that have been allocated for this write but haven't been used.
To compute the end of the allocation, gfs2_iomap_end() incorrectly
rounded the end of the attempted write down to the next block boundary
to arrive at the end of the allocation. It would have to round up, but
the end of the allocation is also available as iomap->offset +
iomap->length, so just use that instead.
In addition, use round_up() for computing the start of the unused range.
Fixes: 64bc06bb32ee ("gfs2: iomap buffered write support")
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Diffstat (limited to 'fs/gfs2')
-rw-r--r-- | fs/gfs2/bmap.c | 11 |
1 files changed, 5 insertions, 6 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 39080b2d6cf8..b6697333bb2b 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -1153,13 +1153,12 @@ static int gfs2_iomap_end(struct inode *inode, loff_t pos, loff_t length, if (length != written && (iomap->flags & IOMAP_F_NEW)) { /* Deallocate blocks that were just allocated. */ - loff_t blockmask = i_blocksize(inode) - 1; - loff_t end = (pos + length) & ~blockmask; + loff_t hstart = round_up(pos + written, i_blocksize(inode)); + loff_t hend = iomap->offset + iomap->length; - pos = (pos + written + blockmask) & ~blockmask; - if (pos < end) { - truncate_pagecache_range(inode, pos, end - 1); - punch_hole(ip, pos, end - pos); + if (hstart < hend) { + truncate_pagecache_range(inode, hstart, hend - 1); + punch_hole(ip, hstart, hend - hstart); } } |