Since the dm-dust calls that need locking do not occur from an
interrupt context, switch to a mutex lock.

Additionally, move some DMERR() calls to be after the unlock, and
in dust_add_block(), move a "bblock->bb" assignment before the lock.

Suggested-by: Heinz Mauelshagen <[email protected]>
Signed-off-by: Bryan Gurney <[email protected]>
---
 drivers/md/dm-dust.c | 44 ++++++++++++++++++--------------------------
 1 file changed, 18 insertions(+), 26 deletions(-)

diff --git a/drivers/md/dm-dust.c b/drivers/md/dm-dust.c
index 8288887b7f94..9a6c041cc711 100644
--- a/drivers/md/dm-dust.c
+++ b/drivers/md/dm-dust.c
@@ -23,7 +23,7 @@ struct dust_device {
        struct dm_dev *dev;
        struct rb_root badblocklist;
        unsigned long long badblock_count;
-       spinlock_t dust_lock;
+       struct mutex dust_lock;
        unsigned int blksz;
        int sect_per_block_shift;
        unsigned int sect_per_block;
@@ -77,26 +77,25 @@ static bool dust_rb_insert(struct rb_root *root, struct 
badblock *new)
 static int dust_remove_block(struct dust_device *dd, unsigned long long block)
 {
        struct badblock *bblock;
-       unsigned long flags;
 
-       spin_lock_irqsave(&dd->dust_lock, flags);
+       mutex_lock(&dd->dust_lock);
        bblock = dust_rb_search(&dd->badblocklist, block);
 
        if (bblock == NULL) {
+               mutex_unlock(&dd->dust_lock);
                if (!dd->quiet_mode) {
                        DMERR("%s: block %llu not found in badblocklist",
                              __func__, block);
                }
-               spin_unlock_irqrestore(&dd->dust_lock, flags);
                return -EINVAL;
        }
 
        rb_erase(&bblock->node, &dd->badblocklist);
        dd->badblock_count--;
+       mutex_unlock(&dd->dust_lock);
        if (!dd->quiet_mode)
                DMINFO("%s: badblock removed at block %llu", __func__, block);
        kfree(bblock);
-       spin_unlock_irqrestore(&dd->dust_lock, flags);
 
        return 0;
 }
@@ -104,7 +103,6 @@ static int dust_remove_block(struct dust_device *dd, 
unsigned long long block)
 static int dust_add_block(struct dust_device *dd, unsigned long long block)
 {
        struct badblock *bblock;
-       unsigned long flags;
 
        bblock = kmalloc(sizeof(*bblock), GFP_KERNEL);
        if (bblock == NULL) {
@@ -113,22 +111,22 @@ static int dust_add_block(struct dust_device *dd, 
unsigned long long block)
                return -ENOMEM;
        }
 
-       spin_lock_irqsave(&dd->dust_lock, flags);
        bblock->bb = block;
+       mutex_lock(&dd->dust_lock);
        if (!dust_rb_insert(&dd->badblocklist, bblock)) {
+               mutex_unlock(&dd->dust_lock);
                if (!dd->quiet_mode) {
                        DMERR("%s: block %llu already in badblocklist",
                              __func__, block);
                }
-               spin_unlock_irqrestore(&dd->dust_lock, flags);
                kfree(bblock);
                return -EINVAL;
        }
 
        dd->badblock_count++;
+       mutex_unlock(&dd->dust_lock);
        if (!dd->quiet_mode)
                DMINFO("%s: badblock added at block %llu", __func__, block);
-       spin_unlock_irqrestore(&dd->dust_lock, flags);
 
        return 0;
 }
@@ -136,15 +134,14 @@ static int dust_add_block(struct dust_device *dd, 
unsigned long long block)
 static int dust_query_block(struct dust_device *dd, unsigned long long block)
 {
        struct badblock *bblock;
-       unsigned long flags;
 
-       spin_lock_irqsave(&dd->dust_lock, flags);
+       mutex_lock(&dd->dust_lock);
        bblock = dust_rb_search(&dd->badblocklist, block);
        if (bblock != NULL)
                DMINFO("%s: block %llu found in badblocklist", __func__, block);
        else
                DMINFO("%s: block %llu not found in badblocklist", __func__, 
block);
-       spin_unlock_irqrestore(&dd->dust_lock, flags);
+       mutex_unlock(&dd->dust_lock);
 
        return 0;
 }
@@ -162,14 +159,13 @@ static int __dust_map_read(struct dust_device *dd, 
sector_t thisblock)
 static int dust_map_read(struct dust_device *dd, sector_t thisblock,
                         bool fail_read_on_bb)
 {
-       unsigned long flags;
        int ret = DM_MAPIO_REMAPPED;
 
        if (fail_read_on_bb) {
                thisblock >>= dd->sect_per_block_shift;
-               spin_lock_irqsave(&dd->dust_lock, flags);
+               mutex_lock(&dd->dust_lock);
                ret = __dust_map_read(dd, thisblock);
-               spin_unlock_irqrestore(&dd->dust_lock, flags);
+               mutex_unlock(&dd->dust_lock);
        }
 
        return ret;
@@ -194,13 +190,11 @@ static void __dust_map_write(struct dust_device *dd, 
sector_t thisblock)
 static int dust_map_write(struct dust_device *dd, sector_t thisblock,
                          bool fail_read_on_bb)
 {
-       unsigned long flags;
-
        if (fail_read_on_bb) {
                thisblock >>= dd->sect_per_block_shift;
-               spin_lock_irqsave(&dd->dust_lock, flags);
+               mutex_lock(&dd->dust_lock);
                __dust_map_write(dd, thisblock);
-               spin_unlock_irqrestore(&dd->dust_lock, flags);
+               mutex_unlock(&dd->dust_lock);
        }
 
        return DM_MAPIO_REMAPPED;
@@ -248,16 +242,15 @@ static bool __dust_clear_badblocks(struct rb_root *tree,
 
 static int dust_clear_badblocks(struct dust_device *dd)
 {
-       unsigned long flags;
        struct rb_root badblocklist;
        unsigned long long badblock_count;
 
-       spin_lock_irqsave(&dd->dust_lock, flags);
+       mutex_lock(&dd->dust_lock);
        badblocklist = dd->badblocklist;
        badblock_count = dd->badblock_count;
        dd->badblocklist = RB_ROOT;
        dd->badblock_count = 0;
-       spin_unlock_irqrestore(&dd->dust_lock, flags);
+       mutex_unlock(&dd->dust_lock);
 
        if (!__dust_clear_badblocks(&badblocklist, badblock_count))
                DMINFO("%s: no badblocks found", __func__);
@@ -347,7 +340,7 @@ static int dust_ctr(struct dm_target *ti, unsigned int 
argc, char **argv)
         */
        dd->badblocklist = RB_ROOT;
        dd->badblock_count = 0;
-       spin_lock_init(&dd->dust_lock);
+       mutex_init(&dd->dust_lock);
 
        dd->quiet_mode = false;
 
@@ -377,7 +370,6 @@ static int dust_message(struct dm_target *ti, unsigned int 
argc, char **argv,
        bool invalid_msg = false;
        int result = -EINVAL;
        unsigned long long tmp, block;
-       unsigned long flags;
        char dummy;
 
        if (argc == 1) {
@@ -394,10 +386,10 @@ static int dust_message(struct dm_target *ti, unsigned 
int argc, char **argv,
                        dd->fail_read_on_bb = true;
                        result = 0;
                } else if (!strcasecmp(argv[0], "countbadblocks")) {
-                       spin_lock_irqsave(&dd->dust_lock, flags);
+                       mutex_lock(&dd->dust_lock);
                        DMINFO("countbadblocks: %llu badblock(s) found",
                               dd->badblock_count);
-                       spin_unlock_irqrestore(&dd->dust_lock, flags);
+                       mutex_unlock(&dd->dust_lock);
                        result = 0;
                } else if (!strcasecmp(argv[0], "clearbadblocks")) {
                        result = dust_clear_badblocks(dd);
-- 
2.21.0

--
dm-devel mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/dm-devel

Reply via email to