Skip to content

Commit 789dd8c

Browse files
gerald-schaeferhcahca
authored andcommitted
s390/dcssblk: fix lockdep warning
dcssblk_remove_store() holds the dcssblk_devices_sem semaphore while calling del_gendisk(dev_info->gd), which in turn tries to acquire disk->open_mutex. Then there is dcssblk_release(), which is called with disk->open_mutex held, and tries to acquire dcssblk_devices_sem. Lockdep reports this as possible circular locking dependency (CPU0 = dcssblk_remove_store, CPU1 = dcssblk_release): [ 44.948865] Possible unsafe locking scenario: [ 44.948866] CPU0 CPU1 [ 44.948867] ---- ---- [ 44.948868] lock(&dcssblk_devices_sem); [ 44.948870] lock(&disk->open_mutex); [ 44.948872] lock(&dcssblk_devices_sem); [ 44.948874] lock(&disk->open_mutex); [ 44.948876] *** DEADLOCK *** In practice, this deadlock should not happen, since dcssblk_remove_store() checks for dev_info->use_count != 0 after acquiring dcssblk_devices_sem, and breaks out before calling del_gendisk(). dev_info->use_count will be decremented in dcssblk_release(), protected by dcssblk_devices_sem. Still there is no need for dcssblk_remove_store() to hold the dcssblk_devices_sem until after calling del_gendisk(), as this only protects dcssblk internal data. So fix the lockdep warning by releasing dcssblk_devices_sem earlier. Also move the segment_unload() loop up, similar to dcssblk_shared_store() error path, no need to do that after calling del_gendisk(). Also change dcssblk_shared_store() error path, where dcssblk_devices_sem was also released only after calling del_gendisk(), and a similar lockdep warning could be triggered (but also deadlock prevented by check for dev_info->use_count). Acked-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Gerald Schaefer <gerald.schaefer@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
1 parent 67ce50c commit 789dd8c

File tree

1 file changed

+6
-7
lines changed

1 file changed

+6
-7
lines changed

drivers/s390/block/dcssblk.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -411,13 +411,13 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch
411411
segment_unload(entry->segment_name);
412412
}
413413
list_del(&dev_info->lh);
414+
up_write(&dcssblk_devices_sem);
414415

415416
dax_remove_host(dev_info->gd);
416417
kill_dax(dev_info->dax_dev);
417418
put_dax(dev_info->dax_dev);
418419
del_gendisk(dev_info->gd);
419420
put_disk(dev_info->gd);
420-
up_write(&dcssblk_devices_sem);
421421

422422
if (device_remove_file_self(dev, attr)) {
423423
device_unregister(dev);
@@ -790,18 +790,17 @@ dcssblk_remove_store(struct device *dev, struct device_attribute *attr, const ch
790790
}
791791

792792
list_del(&dev_info->lh);
793+
/* unload all related segments */
794+
list_for_each_entry(entry, &dev_info->seg_list, lh)
795+
segment_unload(entry->segment_name);
796+
up_write(&dcssblk_devices_sem);
797+
793798
dax_remove_host(dev_info->gd);
794799
kill_dax(dev_info->dax_dev);
795800
put_dax(dev_info->dax_dev);
796801
del_gendisk(dev_info->gd);
797802
put_disk(dev_info->gd);
798803

799-
/* unload all related segments */
800-
list_for_each_entry(entry, &dev_info->seg_list, lh)
801-
segment_unload(entry->segment_name);
802-
803-
up_write(&dcssblk_devices_sem);
804-
805804
device_unregister(&dev_info->dev);
806805
put_device(&dev_info->dev);
807806

0 commit comments

Comments
 (0)