mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 18:41:58 +09:00
s390/dcssblk: fix kernel crash with list_add corruption
commitc8f40a0bccupstream. Commitfb08a1908c("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:fb08a1908c("dax: simplify the dax_device <-> gendisk association") Cc: <stable@vger.kernel.org> # 5.17+ 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
8bf567b63c
commit
6489ec0107
@@ -411,6 +411,7 @@ removeseg:
|
|||||||
}
|
}
|
||||||
list_del(&dev_info->lh);
|
list_del(&dev_info->lh);
|
||||||
|
|
||||||
|
dax_remove_host(dev_info->gd);
|
||||||
kill_dax(dev_info->dax_dev);
|
kill_dax(dev_info->dax_dev);
|
||||||
put_dax(dev_info->dax_dev);
|
put_dax(dev_info->dax_dev);
|
||||||
del_gendisk(dev_info->gd);
|
del_gendisk(dev_info->gd);
|
||||||
@@ -706,9 +707,9 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
out_dax_host:
|
out_dax_host:
|
||||||
|
put_device(&dev_info->dev);
|
||||||
dax_remove_host(dev_info->gd);
|
dax_remove_host(dev_info->gd);
|
||||||
out_dax:
|
out_dax:
|
||||||
put_device(&dev_info->dev);
|
|
||||||
kill_dax(dev_info->dax_dev);
|
kill_dax(dev_info->dax_dev);
|
||||||
put_dax(dev_info->dax_dev);
|
put_dax(dev_info->dax_dev);
|
||||||
put_dev:
|
put_dev:
|
||||||
@@ -788,6 +789,7 @@ dcssblk_remove_store(struct device *dev, struct device_attribute *attr, const ch
|
|||||||
}
|
}
|
||||||
|
|
||||||
list_del(&dev_info->lh);
|
list_del(&dev_info->lh);
|
||||||
|
dax_remove_host(dev_info->gd);
|
||||||
kill_dax(dev_info->dax_dev);
|
kill_dax(dev_info->dax_dev);
|
||||||
put_dax(dev_info->dax_dev);
|
put_dax(dev_info->dax_dev);
|
||||||
del_gendisk(dev_info->gd);
|
del_gendisk(dev_info->gd);
|
||||||
|
|||||||
Reference in New Issue
Block a user