Skip to content

Commit c8f40a0

Browse files
gerald-schaeferhcahca
authored andcommitted
s390/dcssblk: fix kernel crash with list_add corruption
Commit fb08a19 ("dax: simplify the dax_device <-> gendisk association") introduced new logic for gendisk association, requiring drivers to explicitly call dax_add_host() and dax_remove_host(). For dcssblk driver, some dax_remove_host() calls were missing, e.g. in device remove path. The commit also broke error handling for out_dax case in device add path, resulting in an extra put_device() w/o the previous get_device() in that case. This lead to stale xarray entries after device add / remove cycles. In the case when a previously used struct gendisk pointer (xarray index) would be used again, because blk_alloc_disk() happened to return such a pointer, the xa_insert() in dax_add_host() would fail and go to out_dax, doing the extra put_device() in the error path. In combination with an already flawed error handling in dcssblk (device_register() cleanup), which needs to be addressed in a separate patch, this resulted in a missing device_del() / klist_del(), and eventually in the kernel crash with list_add corruption on a subsequent device_add() / klist_add(). Fix this by adding the missing dax_remove_host() calls, and also move the put_device() in the error path to restore the previous logic. Fixes: fb08a19 ("dax: simplify the dax_device <-> gendisk association") Cc: <[email protected]> # 5.17+ Acked-by: Heiko Carstens <[email protected]> Signed-off-by: Gerald Schaefer <[email protected]> Signed-off-by: Heiko Carstens <[email protected]>
1 parent 2d1494f commit c8f40a0

File tree

1 file changed

+3
-1
lines changed

1 file changed

+3
-1
lines changed

drivers/s390/block/dcssblk.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch
412412
}
413413
list_del(&dev_info->lh);
414414

415+
dax_remove_host(dev_info->gd);
415416
kill_dax(dev_info->dax_dev);
416417
put_dax(dev_info->dax_dev);
417418
del_gendisk(dev_info->gd);
@@ -707,9 +708,9 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
707708
goto out;
708709

709710
out_dax_host:
711+
put_device(&dev_info->dev);
710712
dax_remove_host(dev_info->gd);
711713
out_dax:
712-
put_device(&dev_info->dev);
713714
kill_dax(dev_info->dax_dev);
714715
put_dax(dev_info->dax_dev);
715716
put_dev:
@@ -789,6 +790,7 @@ dcssblk_remove_store(struct device *dev, struct device_attribute *attr, const ch
789790
}
790791

791792
list_del(&dev_info->lh);
793+
dax_remove_host(dev_info->gd);
792794
kill_dax(dev_info->dax_dev);
793795
put_dax(dev_info->dax_dev);
794796
del_gendisk(dev_info->gd);

0 commit comments

Comments
 (0)