Skip to content

Commit 79c4a56

Browse files
ausyskinmiquelraynal
authored andcommitted
mtd: call external _get and _put in right order
MTD provider provides mtd_info object to mtd subsystem. With kref patch the mtd_info object can be alive after provider released mtd device. Fix calling order in _get and _put functions to allow mtd provider to safely alloc and release mtd object. Execute: 1) call external _get 2) get_module 3) add internal kref in the get function and opposite order in the put one. The _put_device callback should be the last in put as the master struct memory may be freed in this callback. Signed-off-by: Alexander Usyskin <[email protected]> Signed-off-by: Miquel Raynal <[email protected]> Link: https://lore.kernel.org/linux-mtd/[email protected]
1 parent 19bfa9e commit 79c4a56

File tree

1 file changed

+14
-14
lines changed

1 file changed

+14
-14
lines changed

drivers/mtd/mtdcore.c

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,21 +1229,20 @@ int __get_mtd_device(struct mtd_info *mtd)
12291229
struct mtd_info *master = mtd_get_master(mtd);
12301230
int err;
12311231

1232-
if (!try_module_get(master->owner))
1233-
return -ENODEV;
1234-
1235-
kref_get(&mtd->refcnt);
1236-
12371232
if (master->_get_device) {
12381233
err = master->_get_device(mtd);
1239-
1240-
if (err) {
1241-
kref_put(&mtd->refcnt, mtd_device_release);
1242-
module_put(master->owner);
1234+
if (err)
12431235
return err;
1244-
}
12451236
}
12461237

1238+
if (!try_module_get(master->owner)) {
1239+
if (master->_put_device)
1240+
master->_put_device(master);
1241+
return -ENODEV;
1242+
}
1243+
1244+
kref_get(&mtd->refcnt);
1245+
12471246
while (mtd->parent) {
12481247
if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER) || mtd->parent != master)
12491248
kref_get(&mtd->parent->refcnt);
@@ -1340,13 +1339,14 @@ void __put_mtd_device(struct mtd_info *mtd)
13401339
mtd = parent;
13411340
}
13421341

1343-
if (master->_put_device)
1344-
master->_put_device(master);
1342+
if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER))
1343+
kref_put(&master->refcnt, mtd_device_release);
13451344

13461345
module_put(master->owner);
13471346

1348-
if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER))
1349-
kref_put(&master->refcnt, mtd_device_release);
1347+
/* must be the last as master can be freed in the _put_device */
1348+
if (master->_put_device)
1349+
master->_put_device(master);
13501350
}
13511351
EXPORT_SYMBOL_GPL(__put_mtd_device);
13521352

0 commit comments

Comments
 (0)