[PATCH] mtd: Fix refcounting with MTD_PARTITIONED_MASTER

Usyskin, Alexander alexander.usyskin at intel.com
Mon Jul 31 01:27:44 PDT 2023


> 
> The logic is way too convoluted, let's clean the kref_get/put section to
> clarify what this block does, hopefully solving the refcounting issue
> when using CONFIG_MTD_PARTITIONED_MASTER at the same time:
> - Iterate through all the parent mtd devices
> - Grab a reference over them all but the master
> - Only grab the master whith CONFIG_MTD_PARTITIONED_MASTER
> Same logic must apply in the put path, otherwise it would be broken.
> 
> Cc: Tomas Winkler <tomas.winkler at intel.com>
> Cc: Alexander Usyskin <alexander.usyskin at intel.com>
> Cc: Zhang Xiaoxu <zhangxiaoxu5 at huawei.com>
> Fixes: 19bfa9ebebb5 ("mtd: use refcount to prevent corruption")
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> 
> ---
> 
> Hello,
> 
> Alexander, Zhang, please test this version, it is close to what Zhang
> produced while not strictly identical. This compile-tested only, please
> check on you side whether it fixes the refcounting issue with and
> without PARTITIONED_MASTER, as well as with Kasan.
> 
> Alexander, maybe there is something else to fix, in all cases the logic
> here was broken so let's start by this one and see if we need something
> else on top.
> 
> Thanks,
> Miquèl
> ---
>  drivers/mtd/mtdcore.c | 20 ++++++++++----------
>  1 file changed, 10 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> index 2466ea466466..9b90e1be43e7 100644
> --- a/drivers/mtd/mtdcore.c
> +++ b/drivers/mtd/mtdcore.c
> @@ -1241,14 +1241,15 @@ int __get_mtd_device(struct mtd_info *mtd)
>  		return -ENODEV;
>  	}
> 
> -	kref_get(&mtd->refcnt);
> -
> -	while (mtd->parent) {
> -		if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER) ||
> mtd->parent != master)
> -			kref_get(&mtd->parent->refcnt);
> +	while (mtd) {
> +		if (mtd != master)
> +			kref_get(&mtd->refcnt);
>  		mtd = mtd->parent;
>  	}
> 
> +	if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER))
> +		kref_get(&master->refcnt);
> +
>  	return 0;
>  }
>  EXPORT_SYMBOL_GPL(__get_mtd_device);
> @@ -1332,11 +1333,10 @@ void __put_mtd_device(struct mtd_info *mtd)
>  {
>  	struct mtd_info *master = mtd_get_master(mtd);
> 
> -	while (mtd != master) {
> -		struct mtd_info *parent = mtd->parent;
> -
> -		kref_put(&mtd->refcnt, mtd_device_release);
> -		mtd = parent;
> +	while (mtd) {
> +		if (mtd != master)
> +			kref_put(&mtd->refcnt, mtd_device_release);
kref_put may release mtd here, so the mtd->parent should be stored as in the original patch.

> +		mtd = mtd->parent;
>  	}
> 
>  	if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER))
> --
> 2.34.1


-- 
Thanks,
Sasha





More information about the linux-mtd mailing list