f89330cd10567c0c265987735a3ab8d58ab7899b
[openwrt/staging/wigyori.git] /
1 From 2bba1cdcfcd2907d0696cc0139f1bd078d36ee81 Mon Sep 17 00:00:00 2001
2 From: Daniel Golle <daniel@makrotopia.org>
3 Date: Tue, 19 Dec 2023 02:32:35 +0000
4 Subject: [PATCH 3/8] mtd: ubi: block: use notifier to create ubiblock from
5 parameter
6
7 Use UBI_VOLUME_ADDED notification to create ubiblock device specified
8 on kernel cmdline or module parameter.
9 This makes thing more simple and has the advantage that ubiblock devices
10 on volumes which are not present at the time the ubi module is probed
11 will still be created.
12
13 Suggested-by: Zhihao Cheng <chengzhihao1@huawei.com>
14 Signed-off-by: Daniel Golle <daniel@makrotopia.org>
15 Signed-off-by: Richard Weinberger <richard@nod.at>
16 ---
17 drivers/mtd/ubi/block.c | 136 ++++++++++++++++++++--------------------
18 drivers/mtd/ubi/kapi.c | 54 +++++++++++-----
19 drivers/mtd/ubi/ubi.h | 1 +
20 3 files changed, 106 insertions(+), 85 deletions(-)
21
22 --- a/drivers/mtd/ubi/block.c
23 +++ b/drivers/mtd/ubi/block.c
24 @@ -65,10 +65,10 @@ struct ubiblock_pdu {
25 };
26
27 /* Numbers of elements set in the @ubiblock_param array */
28 -static int ubiblock_devs __initdata;
29 +static int ubiblock_devs;
30
31 /* MTD devices specification parameters */
32 -static struct ubiblock_param ubiblock_param[UBIBLOCK_MAX_DEVICES] __initdata;
33 +static struct ubiblock_param ubiblock_param[UBIBLOCK_MAX_DEVICES];
34
35 struct ubiblock {
36 struct ubi_volume_desc *desc;
37 @@ -532,6 +532,70 @@ static int ubiblock_resize(struct ubi_vo
38 return 0;
39 }
40
41 +static bool
42 +match_volume_desc(struct ubi_volume_info *vi, const char *name, int ubi_num, int vol_id)
43 +{
44 + int err, len, cur_ubi_num, cur_vol_id;
45 +
46 + if (ubi_num == -1) {
47 + /* No ubi num, name must be a vol device path */
48 + err = ubi_get_num_by_path(name, &cur_ubi_num, &cur_vol_id);
49 + if (err || vi->ubi_num != cur_ubi_num || vi->vol_id != cur_vol_id)
50 + return false;
51 +
52 + return true;
53 + }
54 +
55 + if (vol_id == -1) {
56 + /* Got ubi_num, but no vol_id, name must be volume name */
57 + if (vi->ubi_num != ubi_num)
58 + return false;
59 +
60 + len = strnlen(name, UBI_VOL_NAME_MAX + 1);
61 + if (len < 1 || vi->name_len != len)
62 + return false;
63 +
64 + if (strcmp(name, vi->name))
65 + return false;
66 +
67 + return true;
68 + }
69 +
70 + if (vi->ubi_num != ubi_num)
71 + return false;
72 +
73 + if (vi->vol_id != vol_id)
74 + return false;
75 +
76 + return true;
77 +}
78 +
79 +static void
80 +ubiblock_create_from_param(struct ubi_volume_info *vi)
81 +{
82 + int i, ret = 0;
83 + struct ubiblock_param *p;
84 +
85 + /*
86 + * Iterate over ubiblock cmdline parameters. If a parameter matches the
87 + * newly added volume create the ubiblock device for it.
88 + */
89 + for (i = 0; i < ubiblock_devs; i++) {
90 + p = &ubiblock_param[i];
91 +
92 + if (!match_volume_desc(vi, p->name, p->ubi_num, p->vol_id))
93 + continue;
94 +
95 + ret = ubiblock_create(vi);
96 + if (ret) {
97 + pr_err(
98 + "UBI: block: can't add '%s' volume on ubi%d_%d, err=%d\n",
99 + vi->name, p->ubi_num, p->vol_id, ret);
100 + }
101 + break;
102 + }
103 +}
104 +
105 static int ubiblock_notify(struct notifier_block *nb,
106 unsigned long notification_type, void *ns_ptr)
107 {
108 @@ -539,10 +603,7 @@ static int ubiblock_notify(struct notifi
109
110 switch (notification_type) {
111 case UBI_VOLUME_ADDED:
112 - /*
113 - * We want to enforce explicit block device creation for
114 - * volumes, so when a volume is added we do nothing.
115 - */
116 + ubiblock_create_from_param(&nt->vi);
117 break;
118 case UBI_VOLUME_REMOVED:
119 ubiblock_remove(&nt->vi);
120 @@ -568,56 +629,6 @@ static struct notifier_block ubiblock_no
121 .notifier_call = ubiblock_notify,
122 };
123
124 -static struct ubi_volume_desc * __init
125 -open_volume_desc(const char *name, int ubi_num, int vol_id)
126 -{
127 - if (ubi_num == -1)
128 - /* No ubi num, name must be a vol device path */
129 - return ubi_open_volume_path(name, UBI_READONLY);
130 - else if (vol_id == -1)
131 - /* No vol_id, must be vol_name */
132 - return ubi_open_volume_nm(ubi_num, name, UBI_READONLY);
133 - else
134 - return ubi_open_volume(ubi_num, vol_id, UBI_READONLY);
135 -}
136 -
137 -static void __init ubiblock_create_from_param(void)
138 -{
139 - int i, ret = 0;
140 - struct ubiblock_param *p;
141 - struct ubi_volume_desc *desc;
142 - struct ubi_volume_info vi;
143 -
144 - /*
145 - * If there is an error creating one of the ubiblocks, continue on to
146 - * create the following ubiblocks. This helps in a circumstance where
147 - * the kernel command-line specifies multiple block devices and some
148 - * may be broken, but we still want the working ones to come up.
149 - */
150 - for (i = 0; i < ubiblock_devs; i++) {
151 - p = &ubiblock_param[i];
152 -
153 - desc = open_volume_desc(p->name, p->ubi_num, p->vol_id);
154 - if (IS_ERR(desc)) {
155 - pr_err(
156 - "UBI: block: can't open volume on ubi%d_%d, err=%ld\n",
157 - p->ubi_num, p->vol_id, PTR_ERR(desc));
158 - continue;
159 - }
160 -
161 - ubi_get_volume_info(desc, &vi);
162 - ubi_close_volume(desc);
163 -
164 - ret = ubiblock_create(&vi);
165 - if (ret) {
166 - pr_err(
167 - "UBI: block: can't add '%s' volume on ubi%d_%d, err=%d\n",
168 - vi.name, p->ubi_num, p->vol_id, ret);
169 - continue;
170 - }
171 - }
172 -}
173 -
174 static void ubiblock_remove_all(void)
175 {
176 struct ubiblock *next;
177 @@ -643,18 +654,7 @@ int __init ubiblock_init(void)
178 if (ubiblock_major < 0)
179 return ubiblock_major;
180
181 - /*
182 - * Attach block devices from 'block=' module param.
183 - * Even if one block device in the param list fails to come up,
184 - * still allow the module to load and leave any others up.
185 - */
186 - ubiblock_create_from_param();
187 -
188 - /*
189 - * Block devices are only created upon user requests, so we ignore
190 - * existing volumes.
191 - */
192 - ret = ubi_register_volume_notifier(&ubiblock_notifier, 1);
193 + ret = ubi_register_volume_notifier(&ubiblock_notifier, 0);
194 if (ret)
195 goto err_unreg;
196 return 0;
197 --- a/drivers/mtd/ubi/kapi.c
198 +++ b/drivers/mtd/ubi/kapi.c
199 @@ -280,6 +280,41 @@ struct ubi_volume_desc *ubi_open_volume_
200 EXPORT_SYMBOL_GPL(ubi_open_volume_nm);
201
202 /**
203 + * ubi_get_num_by_path - get UBI device and volume number from device path
204 + * @pathname: volume character device node path
205 + * @ubi_num: pointer to UBI device number to be set
206 + * @vol_id: pointer to UBI volume ID to be set
207 + *
208 + * Returns 0 on success and sets ubi_num and vol_id, returns error otherwise.
209 + */
210 +int ubi_get_num_by_path(const char *pathname, int *ubi_num, int *vol_id)
211 +{
212 + int error;
213 + struct path path;
214 + struct kstat stat;
215 +
216 + error = kern_path(pathname, LOOKUP_FOLLOW, &path);
217 + if (error)
218 + return error;
219 +
220 + error = vfs_getattr(&path, &stat, STATX_TYPE, AT_STATX_SYNC_AS_STAT);
221 + path_put(&path);
222 + if (error)
223 + return error;
224 +
225 + if (!S_ISCHR(stat.mode))
226 + return -EINVAL;
227 +
228 + *ubi_num = ubi_major2num(MAJOR(stat.rdev));
229 + *vol_id = MINOR(stat.rdev) - 1;
230 +
231 + if (*vol_id < 0 || *ubi_num < 0)
232 + return -ENODEV;
233 +
234 + return 0;
235 +}
236 +
237 +/**
238 * ubi_open_volume_path - open UBI volume by its character device node path.
239 * @pathname: volume character device node path
240 * @mode: open mode
241 @@ -290,32 +325,17 @@ EXPORT_SYMBOL_GPL(ubi_open_volume_nm);
242 struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode)
243 {
244 int error, ubi_num, vol_id;
245 - struct path path;
246 - struct kstat stat;
247
248 dbg_gen("open volume %s, mode %d", pathname, mode);
249
250 if (!pathname || !*pathname)
251 return ERR_PTR(-EINVAL);
252
253 - error = kern_path(pathname, LOOKUP_FOLLOW, &path);
254 - if (error)
255 - return ERR_PTR(error);
256 -
257 - error = vfs_getattr(&path, &stat, STATX_TYPE, AT_STATX_SYNC_AS_STAT);
258 - path_put(&path);
259 + error = ubi_get_num_by_path(pathname, &ubi_num, &vol_id);
260 if (error)
261 return ERR_PTR(error);
262
263 - if (!S_ISCHR(stat.mode))
264 - return ERR_PTR(-EINVAL);
265 -
266 - ubi_num = ubi_major2num(MAJOR(stat.rdev));
267 - vol_id = MINOR(stat.rdev) - 1;
268 -
269 - if (vol_id >= 0 && ubi_num >= 0)
270 - return ubi_open_volume(ubi_num, vol_id, mode);
271 - return ERR_PTR(-ENODEV);
272 + return ubi_open_volume(ubi_num, vol_id, mode);
273 }
274 EXPORT_SYMBOL_GPL(ubi_open_volume_path);
275
276 --- a/drivers/mtd/ubi/ubi.h
277 +++ b/drivers/mtd/ubi/ubi.h
278 @@ -956,6 +956,7 @@ void ubi_free_internal_volumes(struct ub
279 void ubi_do_get_device_info(struct ubi_device *ubi, struct ubi_device_info *di);
280 void ubi_do_get_volume_info(struct ubi_device *ubi, struct ubi_volume *vol,
281 struct ubi_volume_info *vi);
282 +int ubi_get_num_by_path(const char *pathname, int *ubi_num, int *vol_id);
283 /* scan.c */
284 int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb,
285 int pnum, const struct ubi_vid_hdr *vid_hdr);