gfs2: Zero out fallocated blocks in fallocate_chunk
authorAndreas Gruenbacher <agruenba@redhat.com>
Thu, 29 Mar 2018 13:50:32 +0000 (06:50 -0700)
committerBob Peterson <rpeterso@redhat.com>
Thu, 29 Mar 2018 13:50:32 +0000 (06:50 -0700)
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>
fs/gfs2/bmap.c
fs/gfs2/file.c
fs/gfs2/incore.h

index ce4a978e0c18fc98c573459fbcb59aae05d134d6..685c305cbeb6f7bcc6ad097ce20acfd1859ebdf3 100644 (file)
@@ -491,14 +491,12 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
 {
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_sbd *sdp = GFS2_SB(inode);
-       struct super_block *sb = sdp->sd_vfs;
        struct buffer_head *dibh = mp->mp_bh[0];
        u64 bn;
        unsigned n, i, blks, alloced = 0, iblks = 0, branch_start = 0;
        unsigned dblks = 0;
        unsigned ptrs_per_blk;
        const unsigned end_of_metadata = mp->mp_fheight - 1;
-       int ret;
        enum alloc_state state;
        __be64 *ptr;
        __be64 zero_bn = 0;
@@ -607,15 +605,6 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
                        iomap->flags |= IOMAP_F_NEW;
                        while (n-- > 0)
                                *ptr++ = cpu_to_be64(bn++);
-                       if (flags & IOMAP_ZERO) {
-                               ret = sb_issue_zeroout(sb, iomap->addr >> inode->i_blkbits,
-                                                      dblks, GFP_NOFS);
-                               if (ret) {
-                                       fs_err(sdp,
-                                              "Failed to zero data buffers\n");
-                                       flags &= ~IOMAP_ZERO;
-                               }
-                       }
                        break;
                }
        } while (iomap->addr == IOMAP_NULL_ADDR);
@@ -846,8 +835,6 @@ int gfs2_block_map(struct inode *inode, sector_t lblock,
 
        if (create)
                flags |= IOMAP_WRITE;
-       if (buffer_zeronew(bh_map))
-               flags |= IOMAP_ZERO;
        ret = gfs2_iomap_begin(inode, (loff_t)lblock << inode->i_blkbits,
                               bh_map->b_size, flags, &iomap);
        if (ret) {
index 2edd3a9a7b79aa0cdcabb2e966a3d4e1e55e6d0b..4b71f021a9e29828c472c56ebe59f3562bf956be 100644 (file)
@@ -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;
                }
        }
index e0557b8a590af06fa9e2b5084d9f1b5f32a99f3a..1b6b1e3f5cafbd863edc47e3dc61ffe4d6eafad3 100644 (file)
@@ -130,15 +130,12 @@ static inline bool gfs2_rbm_eq(const struct gfs2_rbm *rbm1,
 enum gfs2_state_bits {
        BH_Pinned = BH_PrivateStart,
        BH_Escaped = BH_PrivateStart + 1,
-       BH_Zeronew = BH_PrivateStart + 2,
 };
 
 BUFFER_FNS(Pinned, pinned)
 TAS_BUFFER_FNS(Pinned, pinned)
 BUFFER_FNS(Escaped, escaped)
 TAS_BUFFER_FNS(Escaped, escaped)
-BUFFER_FNS(Zeronew, zeronew)
-TAS_BUFFER_FNS(Zeronew, zeronew)
 
 struct gfs2_bufdata {
        struct buffer_head *bd_bh;