diff options
author | Andreas Gruenbacher <agruenba@redhat.com> | 2018-03-29 06:50:32 -0700 |
---|---|---|
committer | Bob Peterson <rpeterso@redhat.com> | 2018-03-29 06:50:32 -0700 |
commit | fffb64127adc3eea6a19ceefdc88d171f68b9d34 (patch) | |
tree | 0e0f6d63493ff268d7472322af53f24fc0ac4a34 /fs/gfs2/file.c | |
parent | bb491ce67aa7c1635e5ae4f2f304a7d13d3dbe71 (diff) | |
download | op-kernel-dev-fffb64127adc3eea6a19ceefdc88d171f68b9d34.zip op-kernel-dev-fffb64127adc3eea6a19ceefdc88d171f68b9d34.tar.gz |
gfs2: Zero out fallocated blocks in fallocate_chunk
Instead of zeroing out fallocated blocks in gfs2_iomap_alloc, zero them
out in fallocate_chunk, much higher up the call stack. This gets rid of
gfs2's abuse of the IOMAP_ZERO flag as well as the gfs2 specific zeronew
buffer flag. I can't think of a reason why zeroing out the blocks in
gfs2_iomap_alloc would have any benefits: there is no additional locking
at that level that would add protection to the newly allocated blocks.
While at it, change fallocate over from gs2_block_map to gfs2_iomap_begin.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
Acked-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs/gfs2/file.c')
-rw-r--r-- | fs/gfs2/file.c | 29 |
1 files changed, 14 insertions, 15 deletions
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 2edd3a9..4b71f021 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -729,11 +729,12 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from) static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len, int mode) { + struct super_block *sb = inode->i_sb; struct gfs2_inode *ip = GFS2_I(inode); + loff_t end = offset + len; struct buffer_head *dibh; + struct iomap iomap; int error; - unsigned int nr_blks; - sector_t lblock = offset >> inode->i_blkbits; error = gfs2_meta_inode_buffer(ip, &dibh); if (unlikely(error)) @@ -747,21 +748,19 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len, goto out; } - while (len) { - struct buffer_head bh_map = { .b_state = 0, .b_blocknr = 0 }; - bh_map.b_size = len; - set_buffer_zeronew(&bh_map); - - error = gfs2_block_map(inode, lblock, &bh_map, 1); - if (unlikely(error)) + while (offset < end) { + error = gfs2_iomap_begin(inode, offset, end - offset, + IOMAP_WRITE, &iomap); + if (error) goto out; - len -= bh_map.b_size; - nr_blks = bh_map.b_size >> inode->i_blkbits; - lblock += nr_blks; - if (!buffer_new(&bh_map)) + offset = iomap.offset + iomap.length; + if (iomap.type != IOMAP_HOLE) continue; - if (unlikely(!buffer_zeronew(&bh_map))) { - error = -EIO; + error = sb_issue_zeroout(sb, iomap.addr >> inode->i_blkbits, + iomap.length >> inode->i_blkbits, + GFP_NOFS); + if (error) { + fs_err(GFS2_SB(inode), "Failed to zero data buffers\n"); goto out; } } |