123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- From e5cf19bd8204925f3bd2067df9e867313eac388b Mon Sep 17 00:00:00 2001
- From: Daniel Golle <[email protected]>
- Date: Mon, 1 May 2023 11:57:51 +0100
- Subject: [PATCH 03/15] mtd: ubi: block: use notifier to create ubiblock from
- parameter
- Use UBI_VOLUME_ADDED notification to create ubiblock device specified
- on kernel cmdline or module parameter.
- This makes thing more simple and has the advantage that ubiblock devices
- on volumes which are not present at the time the ubi module is probed
- will still be created.
- Suggested-by: Zhihao Cheng <[email protected]>
- Signed-off-by: Daniel Golle <[email protected]>
- ---
- drivers/mtd/ubi/block.c | 154 ++++++++++++++++++++++------------------
- 1 file changed, 85 insertions(+), 69 deletions(-)
- --- a/drivers/mtd/ubi/block.c
- +++ b/drivers/mtd/ubi/block.c
- @@ -33,6 +33,7 @@
- #include <linux/kernel.h>
- #include <linux/list.h>
- #include <linux/mutex.h>
- +#include <linux/namei.h>
- #include <linux/slab.h>
- #include <linux/mtd/ubi.h>
- #include <linux/blkdev.h>
- @@ -65,10 +66,10 @@ struct ubiblock_pdu {
- };
-
- /* Numbers of elements set in the @ubiblock_param array */
- -static int ubiblock_devs __initdata;
- +static int ubiblock_devs;
-
- /* MTD devices specification parameters */
- -static struct ubiblock_param ubiblock_param[UBIBLOCK_MAX_DEVICES] __initdata;
- +static struct ubiblock_param ubiblock_param[UBIBLOCK_MAX_DEVICES];
-
- struct ubiblock {
- struct ubi_volume_desc *desc;
- @@ -469,7 +470,7 @@ int ubiblock_remove(struct ubi_volume_in
- }
-
- /* Found a device, let's lock it so we can check if it's busy */
- - mutex_lock(&dev->dev_mutex);
- + mutex_lock_nested(&dev->dev_mutex, SINGLE_DEPTH_NESTING);
- if (dev->refcnt > 0) {
- ret = -EBUSY;
- goto out_unlock_dev;
- @@ -532,6 +533,85 @@ static int ubiblock_resize(struct ubi_vo
- return 0;
- }
-
- +static bool
- +match_volume_desc(struct ubi_volume_info *vi, const char *name, int ubi_num, int vol_id)
- +{
- + int err, len;
- + struct path path;
- + struct kstat stat;
- +
- + if (ubi_num == -1) {
- + /* No ubi num, name must be a vol device path */
- + err = kern_path(name, LOOKUP_FOLLOW, &path);
- + if (err)
- + return false;
- +
- + err = vfs_getattr(&path, &stat, STATX_TYPE, AT_STATX_SYNC_AS_STAT);
- + path_put(&path);
- + if (err)
- + return false;
- +
- + if (!S_ISCHR(stat.mode))
- + return false;
- +
- + if (vi->ubi_num != ubi_major2num(MAJOR(stat.rdev)))
- + return false;
- +
- + if (vi->vol_id != MINOR(stat.rdev) - 1)
- + return false;
- +
- + return true;
- + }
- +
- + if (vol_id == -1) {
- + if (vi->ubi_num != ubi_num)
- + return false;
- +
- + len = strnlen(name, UBI_VOL_NAME_MAX + 1);
- + if (len < 1 || vi->name_len != len)
- + return false;
- +
- + if (strcmp(name, vi->name))
- + return false;
- +
- + return true;
- + }
- +
- + if (vi->ubi_num != ubi_num)
- + return false;
- +
- + if (vi->vol_id != vol_id)
- + return false;
- +
- + return true;
- +}
- +
- +static void
- +ubiblock_create_from_param(struct ubi_volume_info *vi)
- +{
- + int i, ret = 0;
- + struct ubiblock_param *p;
- +
- + /*
- + * Iterate over ubiblock cmdline parameters. If a parameter matches the
- + * newly added volume create the ubiblock device for it.
- + */
- + for (i = 0; i < ubiblock_devs; i++) {
- + p = &ubiblock_param[i];
- +
- + if (!match_volume_desc(vi, p->name, p->ubi_num, p->vol_id))
- + continue;
- +
- + ret = ubiblock_create(vi);
- + if (ret) {
- + 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);
- + }
- + break;
- + }
- +}
- +
- static int ubiblock_notify(struct notifier_block *nb,
- unsigned long notification_type, void *ns_ptr)
- {
- @@ -539,10 +619,7 @@ static int ubiblock_notify(struct notifi
-
- switch (notification_type) {
- case UBI_VOLUME_ADDED:
- - /*
- - * We want to enforce explicit block device creation for
- - * volumes, so when a volume is added we do nothing.
- - */
- + ubiblock_create_from_param(&nt->vi);
- break;
- case UBI_VOLUME_REMOVED:
- ubiblock_remove(&nt->vi);
- @@ -568,56 +645,6 @@ static struct notifier_block ubiblock_no
- .notifier_call = ubiblock_notify,
- };
-
- -static struct ubi_volume_desc * __init
- -open_volume_desc(const char *name, int ubi_num, int vol_id)
- -{
- - if (ubi_num == -1)
- - /* No ubi num, name must be a vol device path */
- - return ubi_open_volume_path(name, UBI_READONLY);
- - else if (vol_id == -1)
- - /* No vol_id, must be vol_name */
- - return ubi_open_volume_nm(ubi_num, name, UBI_READONLY);
- - else
- - return ubi_open_volume(ubi_num, vol_id, UBI_READONLY);
- -}
- -
- -static void __init ubiblock_create_from_param(void)
- -{
- - int i, ret = 0;
- - struct ubiblock_param *p;
- - struct ubi_volume_desc *desc;
- - struct ubi_volume_info vi;
- -
- - /*
- - * If there is an error creating one of the ubiblocks, continue on to
- - * create the following ubiblocks. This helps in a circumstance where
- - * the kernel command-line specifies multiple block devices and some
- - * may be broken, but we still want the working ones to come up.
- - */
- - for (i = 0; i < ubiblock_devs; i++) {
- - p = &ubiblock_param[i];
- -
- - desc = open_volume_desc(p->name, p->ubi_num, p->vol_id);
- - if (IS_ERR(desc)) {
- - pr_err(
- - "UBI: block: can't open volume on ubi%d_%d, err=%ld\n",
- - p->ubi_num, p->vol_id, PTR_ERR(desc));
- - continue;
- - }
- -
- - ubi_get_volume_info(desc, &vi);
- - ubi_close_volume(desc);
- -
- - ret = ubiblock_create(&vi);
- - if (ret) {
- - 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;
- - }
- - }
- -}
- -
- static void ubiblock_remove_all(void)
- {
- struct ubiblock *next;
- @@ -643,18 +670,7 @@ 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.
- - */
- - ret = ubi_register_volume_notifier(&ubiblock_notifier, 1);
- + ret = ubi_register_volume_notifier(&ubiblock_notifier, 0);
- if (ret)
- goto err_unreg;
- return 0;
|