Several gfs2 functions failed to reserve enough revoke entries for their
transactions in the journal. Function gfs2_trans_remove_revoke unconditionally
decrements tr->tr_num_revoke, and if not enough revokes are reserved, the
value goes from 0 to  4294967295 (-1, but it's an unsigned int). This is later
re-added to the system-wide revoke numbers, thereby decrementing the value
(sd_log_commited_revoke) "properly," but by accident. This worked properly
most of the time because one transaction would reserve space for revokes,
then it would be merged with the system transaction (sdp->sd_log_tr) and it
usually did not run out, because you can hold a lot of revoke entries
per log descriptor block. Some of the code, such as gfs2_write_revokes, would
work around this and somehow got it right most of the time. However, some
jdata tests with xfstests generic/269 encountered problems when it actually
ran out.

This patch is part of a series that tries to do proper accounting of revokes.

This patch adds the needed revoke entries to function gfs2_iomap_begin_write.

Signed-off-by: Bob Peterson <[email protected]>
---
 fs/gfs2/bmap.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 08f6fbb3655e..403d5ada2f52 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -1074,7 +1074,7 @@ static int gfs2_iomap_begin_write(struct inode *inode, 
loff_t pos,
        if (unstuff || iomap->type == IOMAP_HOLE) {
                unsigned int data_blocks, ind_blocks;
                struct gfs2_alloc_parms ap = {};
-               unsigned int rblocks;
+               unsigned int rblocks, new_blocks = 0;
                struct gfs2_trans *tr;
 
                gfs2_write_calc_reserv(ip, iomap->length, &data_blocks,
@@ -1095,10 +1095,10 @@ static int gfs2_iomap_begin_write(struct inode *inode, 
loff_t pos,
                        rblocks += RES_STATFS + RES_QUOTA;
                if (inode == sdp->sd_rindex)
                        rblocks += 2 * RES_STATFS;
-               rblocks += gfs2_rg_blocks(ip, data_blocks + ind_blocks);
+               new_blocks += gfs2_rg_blocks(ip, data_blocks + ind_blocks);
+               rblocks += new_blocks;
 
-               ret = gfs2_trans_begin(sdp, rblocks,
-                                      iomap->length >> inode->i_blkbits);
+               ret = gfs2_trans_begin(sdp, rblocks, new_blocks);
                if (ret)
                        goto out_trans_fail;
 
-- 
2.24.1

Reply via email to