Limit the n_unaligned argument of gfs2_unaligned_extlen to the number of blocks to scan so that the len argument can never underrun.
Slightly simplify the unaligned block logic in gfs2_free_extlen. Signed-off-by: Andreas Gruenbacher <agrue...@redhat.com> --- fs/gfs2/rgrp.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 2ce46e372b020..f06755dae951e 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -335,8 +335,6 @@ static bool gfs2_unaligned_extlen(struct gfs2_rbm *rbm, u32 n_unaligned, u32 *le if (res != GFS2_BLKST_FREE) return true; (*len)--; - if (*len == 0) - return true; if (gfs2_rbm_incr(rbm)) return true; } @@ -362,7 +360,6 @@ static bool gfs2_unaligned_extlen(struct gfs2_rbm *rbm, u32 n_unaligned, u32 *le static u32 gfs2_free_extlen(const struct gfs2_rbm *rrbm, u32 len) { struct gfs2_rbm rbm = *rrbm; - u32 n_unaligned = rbm.offset & 3; u32 size = len; u32 bytes; u32 chunk_size; @@ -370,11 +367,14 @@ static u32 gfs2_free_extlen(const struct gfs2_rbm *rrbm, u32 len) u64 block; struct gfs2_bitmap *bi; - if (n_unaligned && - gfs2_unaligned_extlen(&rbm, 4 - n_unaligned, &len)) - goto out; + /* Deal with unaligned bits at the front */ + if (rbm.offset & 3) { + u32 n_unaligned = min(4 - (rbm.offset & 3), len); + + if (gfs2_unaligned_extlen(&rbm, n_unaligned, &len)) + goto out; + } - n_unaligned = len & 3; /* Start is now byte aligned */ while (len > 3) { bi = rbm_bi(&rbm); @@ -392,20 +392,16 @@ static u32 gfs2_free_extlen(const struct gfs2_rbm *rrbm, u32 len) BUG_ON(len < chunk_size); len -= chunk_size; block = gfs2_rbm_to_block(&rbm); - if (gfs2_rbm_from_block(&rbm, block + chunk_size)) { - n_unaligned = 0; - break; - } - if (ptr) { - n_unaligned = 3; + if (gfs2_rbm_from_block(&rbm, block + chunk_size)) + goto out; + if (ptr) break; - } - n_unaligned = len & 3; } /* Deal with any bits left over at the end */ - if (n_unaligned) - gfs2_unaligned_extlen(&rbm, n_unaligned, &len); + if (len) + gfs2_unaligned_extlen(&rbm, len, &len); + out: return size - len; } -- 2.20.1