summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryangerkun <yangerkun@huawei.com>2020-06-19 17:12:42 -0400
committerMike Snitzer <snitzer@redhat.com>2020-07-20 11:17:41 -0400
commit0c248ea27fc88cf8a3035ba0ed75b210be9abf80 (patch)
tree71b4b586f35944e129f8db51e660b0ff922bf48c
parent4f7f590b152444c1403ece9eeeddd1e8b22ba04e (diff)
downloadlinux-0c248ea27fc88cf8a3035ba0ed75b210be9abf80.tar.bz2
dm dust: add interface to list all badblocks
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>
-rw-r--r--Documentation/admin-guide/device-mapper/dm-dust.rst17
-rw-r--r--drivers/md/dm-dust.c27
2 files changed, 44 insertions, 0 deletions
diff --git a/Documentation/admin-guide/device-mapper/dm-dust.rst b/Documentation/admin-guide/device-mapper/dm-dust.rst
index cf8079e368de..e35ec8cd2f88 100644
--- a/Documentation/admin-guide/device-mapper/dm-dust.rst
+++ b/Documentation/admin-guide/device-mapper/dm-dust.rst
@@ -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
diff --git a/drivers/md/dm-dust.c b/drivers/md/dm-dust.c
index f1f2dd6a4e84..072ea913cebc 100644
--- a/drivers/md/dm-dust.c
+++ b/drivers/md/dm-dust.c
@@ -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;
}