[PATCH] mtd: Fix refcounting with MTD_PARTITIONED_MASTER

Miquel Raynal miquel.raynal at bootlin.com
Mon Jul 31 01:54:50 PDT 2023


Hi Alexander,

alexander.usyskin at intel.com wrote on Mon, 31 Jul 2023 08:27:44 +0000:

> > 
> > 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.

Absolutely. I'll fix this in v2.

Thanks,
Miquèl



More information about the linux-mtd mailing list