gfs: Smaller journal reservations in gfs2_iomap_write_alloc

Compute a tighter journal block reservation boundary in
gfs2_iomap_write_alloc() by taking into account that we will not
allocate more than one extent of data blocks in a single transaction.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 513e1ec..896ec9d 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -1392,7 +1392,8 @@ gfs2_iomap_write_alloc(struct inode *inode,
 		blocks += unstuff_block + data_blocks;
 	if (inode == sdp->sd_rindex)
 		blocks += 2 * RES_STATFS;
-	blocks += gfs2_rg_blocks(ip, unstuff_block + data_blocks + ind_blocks);
+	blocks += RES_RG_HDR + RES_RG_BIT * (unstuff_block + ind_blocks +
+		  gfs2_rg_extent(inode, data_blocks));
 
 	revokes = unstuff_block + data_blocks;
 
diff --git a/fs/gfs2/trans.h b/fs/gfs2/trans.h
index 38e4f32..8fc6609 100644
--- a/fs/gfs2/trans.h
+++ b/fs/gfs2/trans.h
@@ -34,6 +34,24 @@ static inline unsigned int gfs2_rg_blocks(const struct gfs2_inode *ip, unsigned
 	return rgd->rd_length;
 }
 
+/*
+ * gfs2_rg_extent - number of bitmap blocks for an extent
+ * @inode: The inode
+ * @blocks: The number of blocks to be allocated
+ *
+ * Compute the maximum number of bitmap blocks that allocating a single
+ * extent in a resource group will touch.
+ */
+static inline unsigned int
+gfs2_rg_extent(struct inode *inode, unsigned int blocks)
+{
+	unsigned int bsize = i_blocksize(inode);
+	unsigned int hdr_bits = (bsize - sizeof(struct gfs2_rgrp)) * GFS2_NBBY;
+	unsigned int bmap_bits = (bsize - sizeof(struct gfs2_meta_header)) * GFS2_NBBY;
+
+	return (blocks + hdr_bits + bmap_bits - 1) / bmap_bits;
+}
+
 int __gfs2_trans_begin(struct gfs2_trans *tr, struct gfs2_sbd *sdp,
 		       unsigned int blocks, unsigned int revokes,
 		       unsigned long ip);