dm dust: add interface to list all badblocks
authoryangerkun <yangerkun@huawei.com>
Fri, 19 Jun 2020 21:12:42 +0000 (17:12 -0400)
committerMike Snitzer <snitzer@redhat.com>
Mon, 20 Jul 2020 15:17:41 +0000 (11:17 -0400)
This interface may help anyone who want to know all badblocks without
querying for each block.

[Bryan: DMEMIT message if no blocks are in the bad block list.]

Signed-off-by: yangerkun <yangerkun@huawei.com>
Signed-off-by: Bryan Gurney <bgurney@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Documentation/admin-guide/device-mapper/dm-dust.rst
drivers/md/dm-dust.c

index cf8079e..e35ec8c 100644 (file)
@@ -206,6 +206,22 @@ appear::
 
         dust_clear_badblocks: no badblocks found
 
+Listing the bad block list
+--------------------------
+
+To list all bad blocks in the bad block list (using an example device
+with blocks 1 and 2 in the bad block list), run the following message
+command::
+
+        $ sudo dmsetup message dust1 0 listbadblocks
+        1
+        2
+
+If there are no bad blocks in the bad block list, the command will
+execute with no output::
+
+        $ sudo dmsetup message dust1 0 listbadblocks
+
 Message commands list
 ---------------------
 
@@ -224,6 +240,7 @@ Single argument message commands::
 
         countbadblocks
         clearbadblocks
+        listbadblocks
         disable
         enable
         quiet
index f1f2dd6..072ea91 100644 (file)
@@ -284,6 +284,31 @@ static int dust_clear_badblocks(struct dust_device *dd, char *result, unsigned i
        return 1;
 }
 
+static int dust_list_badblocks(struct dust_device *dd, char *result, unsigned int maxlen,
+                               unsigned int *sz_ptr)
+{
+       unsigned long flags;
+       struct rb_root badblocklist;
+       struct rb_node *node;
+       struct badblock *bblk;
+       unsigned int sz = *sz_ptr;
+       unsigned long long num = 0;
+
+       spin_lock_irqsave(&dd->dust_lock, flags);
+       badblocklist = dd->badblocklist;
+       for (node = rb_first(&badblocklist); node; node = rb_next(node)) {
+               bblk = rb_entry(node, struct badblock, node);
+               DMEMIT("%llu\n", bblk->bb);
+               num++;
+       }
+
+       spin_unlock_irqrestore(&dd->dust_lock, flags);
+       if (!num)
+               DMEMIT("No blocks in badblocklist");
+
+       return 1;
+}
+
 /*
  * Target parameters:
  *
@@ -427,6 +452,8 @@ static int dust_message(struct dm_target *ti, unsigned int argc, char **argv,
                        else
                                dd->quiet_mode = false;
                        r = 0;
+               } else if (!strcasecmp(argv[0], "listbadblocks")) {
+                       r = dust_list_badblocks(dd, result, maxlen, &sz);
                } else {
                        invalid_msg = true;
                }