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);