badblocks: badblocks_set/clear update unacked_exist
authorShaohua Li <shli@fb.com>
Thu, 20 Oct 2016 21:40:06 +0000 (14:40 -0700)
committerJens Axboe <axboe@fb.com>
Fri, 21 Oct 2016 21:45:47 +0000 (15:45 -0600)
When bandblocks_set acknowledges a range or badblocks_clear a range,
it's possible all badblocks are acknowledged. We should update
unacked_exist if this occurs.

Signed-off-by: Shaohua Li <shli@fb.com>
Reviewed-by: Tomasz Majchrzak <tomasz.majchrzak@intel.com>
Tested-by: Tomasz Majchrzak <tomasz.majchrzak@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
block/badblocks.c

index 6610e282a03e0a58363151426956dc5e9e0dff7f..6ebcef28231486ae2b9dcefadfe61412b2112f11 100644 (file)
@@ -133,6 +133,26 @@ retry:
 }
 EXPORT_SYMBOL_GPL(badblocks_check);
 
+static void badblocks_update_acked(struct badblocks *bb)
+{
+       u64 *p = bb->page;
+       int i;
+       bool unacked = false;
+
+       if (!bb->unacked_exist)
+               return;
+
+       for (i = 0; i < bb->count ; i++) {
+               if (!BB_ACK(p[i])) {
+                       unacked = true;
+                       break;
+               }
+       }
+
+       if (!unacked)
+               bb->unacked_exist = 0;
+}
+
 /**
  * badblocks_set() - Add a range of bad blocks to the table.
  * @bb:                the badblocks structure that holds all badblock information
@@ -294,6 +314,8 @@ int badblocks_set(struct badblocks *bb, sector_t s, int sectors,
        bb->changed = 1;
        if (!acknowledged)
                bb->unacked_exist = 1;
+       else
+               badblocks_update_acked(bb);
        write_sequnlock_irqrestore(&bb->lock, flags);
 
        return rv;
@@ -401,6 +423,7 @@ int badblocks_clear(struct badblocks *bb, sector_t s, int sectors)
                }
        }
 
+       badblocks_update_acked(bb);
        bb->changed = 1;
 out:
        write_sequnlock_irq(&bb->lock);