Unconditionally call gfs2_adjust_reservation in gfs2_alloc_blocks. Move the code for updating rd_free and rd_free_clone from gfs2_alloc_blocks into gfs2_adjust_reservation.
Signed-off-by: Andreas Gruenbacher <agrue...@redhat.com> --- fs/gfs2/rgrp.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index bbcf8b8b2597f..733e21cd4cf25 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -2333,13 +2333,23 @@ static void gfs2_rgrp_error(struct gfs2_rgrpd *rgd) * then it is removed. */ -static void gfs2_adjust_reservation(struct gfs2_inode *ip, - const struct gfs2_rbm *rbm, unsigned len) +static int gfs2_adjust_reservation(struct gfs2_inode *ip, + const struct gfs2_rbm *rbm, unsigned len) { + struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_blkreserv *rs = &ip->i_res; struct gfs2_rgrpd *rgd = rbm->rgd; + int error = 0; spin_lock(&rgd->rd_rsspin); + if (unlikely(rgd->rd_free < len || rgd->rd_free_clone < len)) { + fs_warn(sdp, "rgrp free block accounting error (%u %u %u)\n", + rgd->rd_free, rgd->rd_free_clone, len); + error = -EIO; + goto out; + } + rgd->rd_free -= len; + rgd->rd_free_clone -= len; if (gfs2_rs_active(rs)) { u64 start = gfs2_rbm_to_block(rbm); @@ -2362,6 +2372,7 @@ static void gfs2_adjust_reservation(struct gfs2_inode *ip, } out: spin_unlock(&rgd->rd_rsspin); + return error; } /** @@ -2435,8 +2446,9 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks, gfs2_alloc_extent(&rbm, dinode, nblocks); block = gfs2_rbm_to_block(&rbm); rbm.rgd->rd_last_alloc = block - rbm.rgd->rd_data0; - if (gfs2_rs_active(&ip->i_res)) - gfs2_adjust_reservation(ip, &rbm, *nblocks); + error = gfs2_adjust_reservation(ip, &rbm, *nblocks); + if (error) + goto rgrp_error; ndata = *nblocks; if (dinode) ndata--; @@ -2453,12 +2465,7 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks, brelse(dibh); } } - if (rbm.rgd->rd_free < *nblocks) { - fs_warn(sdp, "nblocks=%u\n", *nblocks); - goto rgrp_error; - } - rbm.rgd->rd_free -= *nblocks; if (dinode) { rbm.rgd->rd_dinodes++; *generation = rbm.rgd->rd_igeneration++; @@ -2475,7 +2482,6 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks, gfs2_quota_change(ip, *nblocks, ip->i_inode.i_uid, ip->i_inode.i_gid); - rbm.rgd->rd_free_clone -= *nblocks; trace_gfs2_block_alloc(ip, rbm.rgd, block, *nblocks, dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED); *bn = block; -- 2.19.1.546.g028f9c799.dirty