Skip to content

Commit 6f6544f

Browse files
stellarhopperakpm00
authored andcommitted
dax/bus.c: fix locking for unregister_dax_dev / unregister_dax_mapping paths
Commit c05ae9d ("dax/bus.c: replace driver-core lock usage by a local rwsem") aimed to undo device_lock() abuses for protecting changes to dax-driver internal data-structures like the dax_region resource tree to device-dax-instance range structures. However, the device_lock() was legitimately enforcing that devices to be deleted were not current actively attached to any driver nor assigned any capacity from the region. As a result of the device_lock restoration in delete_store(), the conditional locking in unregister_dev_dax() and unregister_dax_mapping() can be removed. Link: https://lkml.kernel.org/r/[email protected] Fixes: c05ae9d ("dax/bus.c: replace driver-core lock usage by a local rwsem") Signed-off-by: Vishal Verma <[email protected]> Reported-by: Dan Williams <[email protected]> Reviewed-by: Dan Williams <[email protected]> Cc: Alison Schofield <[email protected]> Cc: Dave Jiang <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent c14c647 commit 6f6544f

File tree

1 file changed

+8
-34
lines changed

1 file changed

+8
-34
lines changed

drivers/dax/bus.c

Lines changed: 8 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -465,26 +465,17 @@ static void free_dev_dax_ranges(struct dev_dax *dev_dax)
465465
trim_dev_dax_range(dev_dax);
466466
}
467467

468-
static void __unregister_dev_dax(void *dev)
468+
static void unregister_dev_dax(void *dev)
469469
{
470470
struct dev_dax *dev_dax = to_dev_dax(dev);
471471

472472
dev_dbg(dev, "%s\n", __func__);
473473

474+
down_write(&dax_region_rwsem);
474475
kill_dev_dax(dev_dax);
475476
device_del(dev);
476477
free_dev_dax_ranges(dev_dax);
477478
put_device(dev);
478-
}
479-
480-
static void unregister_dev_dax(void *dev)
481-
{
482-
if (rwsem_is_locked(&dax_region_rwsem))
483-
return __unregister_dev_dax(dev);
484-
485-
if (WARN_ON_ONCE(down_write_killable(&dax_region_rwsem) != 0))
486-
return;
487-
__unregister_dev_dax(dev);
488479
up_write(&dax_region_rwsem);
489480
}
490481

@@ -560,15 +551,10 @@ static ssize_t delete_store(struct device *dev, struct device_attribute *attr,
560551
if (!victim)
561552
return -ENXIO;
562553

563-
rc = down_write_killable(&dax_region_rwsem);
564-
if (rc)
565-
return rc;
566-
rc = down_write_killable(&dax_dev_rwsem);
567-
if (rc) {
568-
up_write(&dax_region_rwsem);
569-
return rc;
570-
}
554+
device_lock(dev);
555+
device_lock(victim);
571556
dev_dax = to_dev_dax(victim);
557+
down_write(&dax_dev_rwsem);
572558
if (victim->driver || dev_dax_size(dev_dax))
573559
rc = -EBUSY;
574560
else {
@@ -589,11 +575,12 @@ static ssize_t delete_store(struct device *dev, struct device_attribute *attr,
589575
rc = -EBUSY;
590576
}
591577
up_write(&dax_dev_rwsem);
578+
device_unlock(victim);
592579

593580
/* won the race to invalidate the device, clean it up */
594581
if (do_del)
595582
devm_release_action(dev, unregister_dev_dax, victim);
596-
up_write(&dax_region_rwsem);
583+
device_unlock(dev);
597584
put_device(victim);
598585

599586
return rc;
@@ -705,33 +692,20 @@ static void dax_mapping_release(struct device *dev)
705692
put_device(parent);
706693
}
707694

708-
static void __unregister_dax_mapping(void *data)
695+
static void unregister_dax_mapping(void *data)
709696
{
710697
struct device *dev = data;
711698
struct dax_mapping *mapping = to_dax_mapping(dev);
712699
struct dev_dax *dev_dax = to_dev_dax(dev->parent);
713700

714701
dev_dbg(dev, "%s\n", __func__);
715702

716-
lockdep_assert_held_write(&dax_region_rwsem);
717-
718703
dev_dax->ranges[mapping->range_id].mapping = NULL;
719704
mapping->range_id = -1;
720705

721706
device_unregister(dev);
722707
}
723708

724-
static void unregister_dax_mapping(void *data)
725-
{
726-
if (rwsem_is_locked(&dax_region_rwsem))
727-
return __unregister_dax_mapping(data);
728-
729-
if (WARN_ON_ONCE(down_write_killable(&dax_region_rwsem) != 0))
730-
return;
731-
__unregister_dax_mapping(data);
732-
up_write(&dax_region_rwsem);
733-
}
734-
735709
static struct dev_dax_range *get_dax_range(struct device *dev)
736710
{
737711
struct dax_mapping *mapping = to_dax_mapping(dev);

0 commit comments

Comments
 (0)