From: Miquel Raynal <miquel.raynal@bootlin.com>
To: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
Cc: Alexander Usyskin <alexander.usyskin@intel.com>,
Richard Weinberger <richard@nod.at>,
Vignesh Raghavendra <vigneshr@ti.com>,
"linux-mtd@lists.infradead.org" <linux-mtd@lists.infradead.org>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
Tomas Winkler <tomas.winkler@intel.com>,
Vitaly Lubart <vitaly.lubart@intel.com>,
Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
Geert Uytterhoeven <geert+renesas@glider.be>,
Biju Das <biju.das.jz@bp.renesas.com>,
"linux-renesas-soc@vger.kernel.org"
<linux-renesas-soc@vger.kernel.org>,
Chris Paterson <Chris.Paterson2@renesas.com>
Subject: Re: [PATCH 1/2] mtd: use refcount to prevent corruption
Date: Sat, 15 Jul 2023 17:41:12 +0200 [thread overview]
Message-ID: <20230715174112.3909e43f@xps-13> (raw)
In-Reply-To: <TYWPR01MB87756794A30EB389AB017EB1C234A@TYWPR01MB8775.jpnprd01.prod.outlook.com>
Hi Fabrizio,
fabrizio.castro.jz@renesas.com wrote on Fri, 14 Jul 2023 16:10:45 +0000:
> Dear All,
>
> I am sorry for reopening this topic, but as it turns out (after bisecting
> linux-next/master) this patch is interfering with a use case I am working
> on.
>
> I am using a Renesas RZ/V2M EVK v2.0 platform, I have an SPI NOR memory
> ("micron,mt25ql256a") wired up to a connector on the platform, the SPI
> master is using driver (built as module):
> drivers/spi/spi-rzv2m-csi.c
>
> Although the board device tree in mainline does not reflect the connection
> of CSI4 (which is the SPI master) from the SoC to the "micron,mt25ql256a"
> (SPI slave device), my local device tree comes with the necessary definitions.
>
> Without this patch, when I load up the module, I get the below 3 devices:
> /dev/mtd0
> /dev/mtd0ro
> /dev/mtdblock0
>
> They get cleaned up correctly upon module removal.
> I can reload the same module, and everything works just fine.
>
> With this patch applied, when I load up the module, I get the same 3
> devices:
> /dev/mtd0
> /dev/mtd0ro
> /dev/mtdblock0
>
> Upon removal, the below 2 devices still hang around:
> /dev/mtd0
> /dev/mtd0ro
Looks like the refcounting change is still not even in some cases, can
you investigate and come up with a proper patch? You can either improve
the existing patch or revert it and try your own approach if deemed
better.
Thanks,
Miquèl
> Preventing the module from being (re)loaded correctly:
> rzv2m_csi a4020200.spi: error -EBUSY: register controller failed
> rzv2m_csi: probe of a4020200.spi failed with error -16
>
> Are you guys aware of this sort of side effect?
>
> Thanks,
> Fab
>
> > From: Alexander Usyskin <alexander.usyskin@intel.com>
> > Subject: [PATCH 1/2] mtd: use refcount to prevent corruption
> >
> > From: Tomas Winkler <tomas.winkler@intel.com>
> >
> > When underlying device is removed mtd core will crash
> > in case user space is holding open handle.
> > Need to use proper refcounting so device is release
> > only when has no users.
> >
> > Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
> > Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
> > ---
> > drivers/mtd/mtdcore.c | 72 ++++++++++++++++++++++------------------
> > -
> > drivers/mtd/mtdcore.h | 1 +
> > drivers/mtd/mtdpart.c | 14 ++++----
> > include/linux/mtd/mtd.h | 2 +-
> > 4 files changed, 49 insertions(+), 40 deletions(-)
> >
> > diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> > index abf4cb58a8ab..84bd1878367d 100644
> > --- a/drivers/mtd/mtdcore.c
> > +++ b/drivers/mtd/mtdcore.c
> > @@ -93,10 +93,33 @@ static void mtd_release(struct device *dev)
> > struct mtd_info *mtd = dev_get_drvdata(dev);
> > dev_t index = MTD_DEVT(mtd->index);
> >
> > + if (mtd_is_partition(mtd))
> > + release_mtd_partition(mtd);
> > +
> > /* remove /dev/mtdXro node */
> > device_destroy(&mtd_class, index + 1);
> > }
> >
> > +static void mtd_device_release(struct kref *kref)
> > +{
> > + struct mtd_info *mtd = container_of(kref, struct mtd_info,
> > refcnt);
> > +
> > + debugfs_remove_recursive(mtd->dbg.dfs_dir);
> > +
> > + /* Try to remove the NVMEM provider */
> > + nvmem_unregister(mtd->nvmem);
> > +
> > + device_unregister(&mtd->dev);
> > +
> > + /* Clear dev so mtd can be safely re-registered later if desired
> > */
> > + memset(&mtd->dev, 0, sizeof(mtd->dev));
> > +
> > + idr_remove(&mtd_idr, mtd->index);
> > + of_node_put(mtd_get_of_node(mtd));
> > +
> > + module_put(THIS_MODULE);
> > +}
> > +
> > #define MTD_DEVICE_ATTR_RO(name) \
> > static DEVICE_ATTR(name, 0444, mtd_##name##_show, NULL)
> >
> > @@ -666,7 +689,7 @@ int add_mtd_device(struct mtd_info *mtd)
> > }
> >
> > mtd->index = i;
> > - mtd->usecount = 0;
> > + kref_init(&mtd->refcnt);
> >
> > /* default value if not set by driver */
> > if (mtd->bitflip_threshold == 0)
> > @@ -779,7 +802,6 @@ int del_mtd_device(struct mtd_info *mtd)
> > {
> > int ret;
> > struct mtd_notifier *not;
> > - struct device_node *mtd_of_node;
> >
> > mutex_lock(&mtd_table_mutex);
> >
> > @@ -793,28 +815,8 @@ int del_mtd_device(struct mtd_info *mtd)
> > list_for_each_entry(not, &mtd_notifiers, list)
> > not->remove(mtd);
> >
> > - if (mtd->usecount) {
> > - printk(KERN_NOTICE "Removing MTD device #%d (%s) with use
> > count %d\n",
> > - mtd->index, mtd->name, mtd->usecount);
> > - ret = -EBUSY;
> > - } else {
> > - mtd_of_node = mtd_get_of_node(mtd);
> > - debugfs_remove_recursive(mtd->dbg.dfs_dir);
> > -
> > - /* Try to remove the NVMEM provider */
> > - nvmem_unregister(mtd->nvmem);
> > -
> > - device_unregister(&mtd->dev);
> > -
> > - /* Clear dev so mtd can be safely re-registered later if
> > desired */
> > - memset(&mtd->dev, 0, sizeof(mtd->dev));
> > -
> > - idr_remove(&mtd_idr, mtd->index);
> > - of_node_put(mtd_of_node);
> > -
> > - module_put(THIS_MODULE);
> > - ret = 0;
> > - }
> > + kref_put(&mtd->refcnt, mtd_device_release);
> > + ret = 0;
> >
> > out_error:
> > mutex_unlock(&mtd_table_mutex);
> > @@ -1228,19 +1230,21 @@ int __get_mtd_device(struct mtd_info *mtd)
> > if (!try_module_get(master->owner))
> > return -ENODEV;
> >
> > + kref_get(&mtd->refcnt);
> > +
> > if (master->_get_device) {
> > err = master->_get_device(mtd);
> >
> > if (err) {
> > + kref_put(&mtd->refcnt, mtd_device_release);
> > module_put(master->owner);
> > return err;
> > }
> > }
> >
> > - master->usecount++;
> > -
> > while (mtd->parent) {
> > - mtd->usecount++;
> > + if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER) || mtd-
> > >parent != master)
> > + kref_get(&mtd->parent->refcnt);
> > mtd = mtd->parent;
> > }
> >
> > @@ -1327,18 +1331,20 @@ void __put_mtd_device(struct mtd_info *mtd)
> > {
> > struct mtd_info *master = mtd_get_master(mtd);
> >
> > - while (mtd->parent) {
> > - --mtd->usecount;
> > - BUG_ON(mtd->usecount < 0);
> > - mtd = mtd->parent;
> > - }
> > + while (mtd != master) {
> > + struct mtd_info *parent = mtd->parent;
> >
> > - master->usecount--;
> > + kref_put(&mtd->refcnt, mtd_device_release);
> > + mtd = parent;
> > + }
> >
> > if (master->_put_device)
> > master->_put_device(master);
> >
> > module_put(master->owner);
> > +
> > + if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER))
> > + kref_put(&master->refcnt, mtd_device_release);
> > }
> > EXPORT_SYMBOL_GPL(__put_mtd_device);
> >
> > diff --git a/drivers/mtd/mtdcore.h b/drivers/mtd/mtdcore.h
> > index b5eefeabf310..b014861a06a6 100644
> > --- a/drivers/mtd/mtdcore.h
> > +++ b/drivers/mtd/mtdcore.h
> > @@ -12,6 +12,7 @@ int __must_check add_mtd_device(struct mtd_info
> > *mtd);
> > int del_mtd_device(struct mtd_info *mtd);
> > int add_mtd_partitions(struct mtd_info *, const struct mtd_partition
> > *, int);
> > int del_mtd_partitions(struct mtd_info *);
> > +void release_mtd_partition(struct mtd_info *mtd);
> >
> > struct mtd_partitions;
> >
> > diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
> > index a46affbb037d..23483db8f30c 100644
> > --- a/drivers/mtd/mtdpart.c
> > +++ b/drivers/mtd/mtdpart.c
> > @@ -32,6 +32,12 @@ static inline void free_partition(struct mtd_info
> > *mtd)
> > kfree(mtd);
> > }
> >
> > +void release_mtd_partition(struct mtd_info *mtd)
> > +{
> > + WARN_ON(!list_empty(&mtd->part.node));
> > + free_partition(mtd);
> > +}
> > +
> > static struct mtd_info *allocate_partition(struct mtd_info *parent,
> > const struct mtd_partition *part,
> > int partno, uint64_t cur_offset)
> > @@ -309,13 +315,11 @@ static int __mtd_del_partition(struct mtd_info
> > *mtd)
> >
> > sysfs_remove_files(&mtd->dev.kobj, mtd_partition_attrs);
> >
> > + list_del_init(&mtd->part.node);
> > err = del_mtd_device(mtd);
> > if (err)
> > return err;
> >
> > - list_del(&mtd->part.node);
> > - free_partition(mtd);
> > -
> > return 0;
> > }
> >
> > @@ -333,6 +337,7 @@ static int __del_mtd_partitions(struct mtd_info
> > *mtd)
> > __del_mtd_partitions(child);
> >
> > pr_info("Deleting %s MTD partition\n", child->name);
> > + list_del_init(&child->part.node);
> > ret = del_mtd_device(child);
> > if (ret < 0) {
> > pr_err("Error when deleting partition \"%s\" (%d)\n",
> > @@ -340,9 +345,6 @@ static int __del_mtd_partitions(struct mtd_info
> > *mtd)
> > err = ret;
> > continue;
> > }
> > -
> > - list_del(&child->part.node);
> > - free_partition(child);
> > }
> >
> > return err;
> > diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
> > index 7c58c44662b8..914a9f974baa 100644
> > --- a/include/linux/mtd/mtd.h
> > +++ b/include/linux/mtd/mtd.h
> > @@ -379,7 +379,7 @@ struct mtd_info {
> >
> > struct module *owner;
> > struct device dev;
> > - int usecount;
> > + struct kref refcnt;
> > struct mtd_debug_info dbg;
> > struct nvmem_device *nvmem;
> > struct nvmem_device *otp_user_nvmem;
> > --
> > 2.34.1
>
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
next prev parent reply other threads:[~2023-07-15 15:41 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-20 13:19 [PATCH 0/2] mtd: prepare for dynamically removed devices Alexander Usyskin
2023-06-20 13:19 ` [PATCH 1/2] mtd: use refcount to prevent corruption Alexander Usyskin
2023-07-12 14:14 ` Miquel Raynal
2023-07-14 16:10 ` Fabrizio Castro
2023-07-15 15:41 ` Miquel Raynal [this message]
2023-07-16 6:29 ` Usyskin, Alexander
2023-07-16 13:39 ` Miquel Raynal
2023-07-24 11:43 ` Usyskin, Alexander
2023-07-24 11:51 ` Miquel Raynal
2023-07-24 12:04 ` Usyskin, Alexander
2023-07-25 12:50 ` Usyskin, Alexander
2023-07-27 6:19 ` Miquel Raynal
2023-07-27 6:32 ` Winkler, Tomas
2023-07-27 6:55 ` Miquel Raynal
2023-06-20 13:19 ` [PATCH 2/2] mtd: call external _get and _put in right order Alexander Usyskin
2023-07-12 14:13 ` Miquel Raynal
2023-06-22 8:30 ` [PATCH 0/2] mtd: prepare for dynamically removed devices Miquel Raynal
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230715174112.3909e43f@xps-13 \
--to=miquel.raynal@bootlin.com \
--cc=Chris.Paterson2@renesas.com \
--cc=alexander.usyskin@intel.com \
--cc=andriy.shevchenko@linux.intel.com \
--cc=biju.das.jz@bp.renesas.com \
--cc=fabrizio.castro.jz@renesas.com \
--cc=geert+renesas@glider.be \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mtd@lists.infradead.org \
--cc=linux-renesas-soc@vger.kernel.org \
--cc=richard@nod.at \
--cc=tomas.winkler@intel.com \
--cc=vigneshr@ti.com \
--cc=vitaly.lubart@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox