[PATCH] mtd: ubi: attach MTD partition from device-tree

Zhihao Cheng chengzhihao1 at huawei.com
Tue May 2 19:26:33 PDT 2023


在 2023/5/2 2:40, Daniel Golle 写道:
> On Tue, Apr 25, 2023 at 11:01:41AM +0800, Zhihao Cheng wrote:
>> 在 2023/4/24 21:06, Daniel Golle 写道:
>>> On Mon, Apr 24, 2023 at 11:26:13AM +0800, Zhihao Cheng wrote:
>>>>> [...]
>>>>> One way to partially resolve this could be to add a boolean parameter to
>>>>> ubiblock_create_from_param which indicates if -ENOENT should be treated
>>>>> as an error, and set that parameter only when calling from
>>>>> late_initcall.
>>>>>
>>>>> Being able to warn users if they added the same ubiblock device more
>>>>> than once **on the cmdline or module parameter** is more tricky and
>>>>> would require tracking why a ubiblock device has previously been
>>>>> created. However, I don't think that emitting a warning in this case
>>>>> is crucial at all, the user definitely wanted the ubiblock device to be
>>>>> created and saying that more than once is unneccesary but yet also
>>>>> doesn't leave room for any interpretation other than just that the user
>>>>> *really* wants the ubiblock to be created.
>>>>
>>>> Emm, I prefer to fix it, it's weird that ubiblock_create_from_param() being
>>>> executed multiple times(Each ubi_notify_add() will call once, late_initcall
>>>> will call it again). User could see many false positive error messages.
>>>
>>> Given my suggestion above (not printing error in case the UBI device or
>>> volume doesn't exist as well as in case in case the ubiblock device has
>>> already been created) there won't be any false positives.
>>> What is still true is that other errors (eg. invalid string format of
>>> the ubiblock parameter) will be printed multiple times.
>>>
>>> Do you think it is worth putting much effort into avoiding that?
>>> If so, any idea how?
>>>
>>
>> Currently, there are two timings to load ubiblock:
>> 1. boot cmdline: One-time loading
>> 2. ioctl UBI_IOCVOLCRBLK: Can be called multiple times at runtime
>> PS: ubiblock cannot be compiled in module, there are only two options: Y and
>> N
> 
> It's true that ubiblock is a boolean option, however, Y or N decides
> whether support for ubiblock will be included with the ubi driver, which
> can well be a kernel module. In that case, ubiblock is loaded and removed
> together with the rest of the ubi driver.

You are right, ubiblock will be loaded in module way if UBI driver is 
compiled in module format, my mistake.

> 
>>
>> How about deleting 'ubiblock_create_from_param' from ubi_notify_add(), we
>> only call ubiblock_create_from_param() once in ubi_init_attach(). This can
>> keep the ubiblock loading timings are unchanged, and ENODEV and EEXIST won't
>> be false positive.
> 
> I also thought that and it works well under the assumption that all
> drivers providing MTD devices are built-in or inserted before the ubi
> driver is inserted. However, this may not always be true. Think of,
> for example, an SPI bus driver which is built as a module and loaded
> during boot (eg. from initramfs). Your suggestion below solves that.
> 
>>
>> If someone later want to loading ubiblock automically, UBI_VOLUME_ADDED case
>> in ubiblock_notify() is suggested to be implemented.
> 
> I've implemented your suggestion and it works fine, to me even looks
> better than the current code which gets/puts the UBI volume just to
> compare if its info matches the cmdline parameter. I will post this as
> a preliminary patch in the series, together with an other fix and an
> updated version of this patch.

I'll take a look at this series.
> 
>>
>>>>
>>>>>
>>>>>>
>>>>>>> +				pr_err(
>>>>>>> +				       "UBI: block: can't add '%s' volume on ubi%d_%d, err=%d\n",
>>>>>>> +				       vi.name, p->ubi_num, p->vol_id, ret);
>>>>>>>      			continue;
>>>>>>>      		}
>>>>>>>      	}
>>>>>>> @@ -644,13 +645,6 @@ int __init ubiblock_init(void)
>>>>>>>      	if (ubiblock_major < 0)
>>>>>>>      		return ubiblock_major;
>>>>>>> -	/*
>>>>>>> -	 * Attach block devices from 'block=' module param.
>>>>>>> -	 * Even if one block device in the param list fails to come up,
>>>>>>> -	 * still allow the module to load and leave any others up.
>>>>>>> -	 */
>>>>>>> -	ubiblock_create_from_param();
>>>>>>> -
>>>>>>>      	/*
>>>>>>>      	 * Block devices are only created upon user requests, so we ignore
>>>>>>>      	 * existing volumes.
>>>>>>> diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
>>>>>>> index 9cd565daad368..a764f97eee791 100644
>>>>>>> --- a/drivers/mtd/ubi/build.c
>>>>>>> +++ b/drivers/mtd/ubi/build.c
>>>>>>> @@ -27,6 +27,7 @@
>>>>>>>      #include <linux/log2.h>
>>>>>>>      #include <linux/kthread.h>
>>>>>>>      #include <linux/kernel.h>
>>>>>>> +#include <linux/of.h>
>>>>>>>      #include <linux/slab.h>
>>>>>>>      #include <linux/major.h>
>>>>>>>      #include "ubi.h"
>>>>>>> @@ -1065,6 +1066,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
>>>>>>>       * ubi_detach_mtd_dev - detach an MTD device.
>>>>>>>       * @ubi_num: UBI device number to detach from
>>>>>>>       * @anyway: detach MTD even if device reference count is not zero
>>>>>>> + * @have_lock: called by MTD notifier holding mtd_table_mutex
>>>>>>>       *
>>>>>>>       * This function destroys an UBI device number @ubi_num and detaches the
>>>>>>>       * underlying MTD device. Returns zero in case of success and %-EBUSY if the
>>>>>>> @@ -1074,7 +1076,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
>>>>>>>       * Note, the invocations of this function has to be serialized by the
>>>>>>>       * @ubi_devices_mutex.
>>>>>>>       */
>>>>>>> -int ubi_detach_mtd_dev(int ubi_num, int anyway)
>>>>>>> +int ubi_detach_mtd_dev(int ubi_num, int anyway, bool have_lock)
>>>>>>>      {
>>>>>>>      	struct ubi_device *ubi;
>>>>>>> @@ -1108,7 +1110,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
>>>>>>>      	 * EC updates that have been made since the last written fastmap.
>>>>>>>      	 * In case of fastmap debugging we omit the update to simulate an
>>>>>>>      	 * unclean shutdown. */
>>>>>>> -	if (!ubi_dbg_chk_fastmap(ubi))
>>>>>>> +	if (!have_lock && !ubi_dbg_chk_fastmap(ubi))
>>>>>>>      		ubi_update_fastmap(ubi);
>>>>>>
>>>>>> Why do you skip updating fastmap if ubi is detached in mtd notification way?
>>>>>
>>>>> The reason here is simple: Once we receive a notification about the MTD
>>>>> device being removed it is too late to update fastmap. The device is
>>>>> gone, nothing we can do about that any more. Just like removing a
>>>>> device holding a filesystem without having priorly unmounted it, e.g.
>>>>> if you 'rmmod usb-storage' (just that block devices unfortunately still
>>>>> lack notifications about removal or size changes...)
>>>>>
>>>>
>>>> Another path still operate mtd device:
>>>> ubi_detach_mtd_dev -> ubi_wl_close -> shutdown_work -> wrk->func ->
>>>> erase_worker -> sync_erase -> ubi_io_sync_erase/ubi_io_write_ec_hdr.
>>>
>>> True, but I didn't see this being a problem, at least in the sense
>>> that I didn't see a kernel panic. We could try to make
>>> ubi_update_fastmap more robust to gracefully return in case the device
>>> is already gone.
>>>
>>
>> You mean ubi_update_fastmap() could trigger panic in ubi_notify_remove()
>> when you remove the SPI bus dirver? May I have the error message?
> 
> I spent a day stairing at the kernel Oops and found that it was unrelated
> to UBI, but rather a bug in the SPI driver. I've posted the fix:
> 
> https://patchwork.kernel.org/project/spi-devel-general/patch/ZFAF6pJxMu1z6k4w@makrotopia.org/
> 
>> I thought both ubi_update_fastmap() and ubi_wl_close() could operate the
>> removed mtd device, it will be better to notify user error messages of
>> ubi_update_fastmap() casued by removing under layer device.
> 
> You were right, there is no problem there and we don't need to skip
> ubi_update_fastmap() now that the SPI driver makes sure to complete
> any ongoing operation before unloading (see above).
> 

Great.

>>
>>>>
>>>> Besides, can we remove any mtd specific driver(eg. phram/nandsim) by rmmod?
>>>
>>> My test-case was to remove the SPI bus driver on which the SPI-NAND chip
>>> is connected to. Afaik there is also no way to prevent this at this
>>> point, we'd have to propagate the usecount of the MTD device down to
>>> the SPI bus hosting it.
>>>
>>>> I notice that get_mtd_device(called before ubi attaching) will increase
>>>> specific mtd driver's module refcnt.
>>>> If we physically remove the mtd device, will it trigger del_mtd_device()?
>>>
>>> Yes, in case what you mean is an SPI-NAND flash connected to an SPI-USB
>>> adapter, and then pulling the USB device.
>>>
>>>> For example, when is phram_remove() called?
>>>
>>>>  From what I can see:
>>> phram_remove -> mtd_device_unregister -> del_mtd_device -> [for all
>>> elements of list mtd_notifiers call their 'remove' function]
>>>
>>> After this we should always end up with mtd->usecount == 0 and hence
>>> proceed. If usecount != 0 at this point there is currently no meaningful
>>> error handling in mtdcore.c as far as my interpretation goes.
> 
> I've found a similar issue with "fake error handling" on removal which
> should rather be skipped in drivers/mtd/ubi/block.c. I will post the
> fix also in the upcoming series which I'm preparing right now.
> 
> .
> 




More information about the linux-mtd mailing list