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

Reply via email to