1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright (c) International Business Machines Corp., 2006 |
4 | * |
5 | * Author: Artem Bityutskiy (Битюцкий Артём) |
6 | */ |
7 | |
8 | /* |
9 | * This file contains implementation of volume creation, deletion, updating and |
10 | * resizing. |
11 | */ |
12 | |
13 | #include <linux/err.h> |
14 | #include <linux/math64.h> |
15 | #include <linux/slab.h> |
16 | #include <linux/export.h> |
17 | #include "ubi.h" |
18 | |
19 | static int self_check_volumes(struct ubi_device *ubi); |
20 | |
21 | static ssize_t vol_attribute_show(struct device *dev, |
22 | struct device_attribute *attr, char *buf); |
23 | |
24 | /* Device attributes corresponding to files in '/<sysfs>/class/ubi/ubiX_Y' */ |
25 | static struct device_attribute attr_vol_reserved_ebs = |
26 | __ATTR(reserved_ebs, S_IRUGO, vol_attribute_show, NULL); |
27 | static struct device_attribute attr_vol_type = |
28 | __ATTR(type, S_IRUGO, vol_attribute_show, NULL); |
29 | static struct device_attribute attr_vol_name = |
30 | __ATTR(name, S_IRUGO, vol_attribute_show, NULL); |
31 | static struct device_attribute attr_vol_corrupted = |
32 | __ATTR(corrupted, S_IRUGO, vol_attribute_show, NULL); |
33 | static struct device_attribute attr_vol_alignment = |
34 | __ATTR(alignment, S_IRUGO, vol_attribute_show, NULL); |
35 | static struct device_attribute attr_vol_usable_eb_size = |
36 | __ATTR(usable_eb_size, S_IRUGO, vol_attribute_show, NULL); |
37 | static struct device_attribute attr_vol_data_bytes = |
38 | __ATTR(data_bytes, S_IRUGO, vol_attribute_show, NULL); |
39 | static struct device_attribute attr_vol_upd_marker = |
40 | __ATTR(upd_marker, S_IRUGO, vol_attribute_show, NULL); |
41 | |
42 | /* |
43 | * "Show" method for files in '/<sysfs>/class/ubi/ubiX_Y/'. |
44 | * |
45 | * Consider a situation: |
46 | * A. process 1 opens a sysfs file related to volume Y, say |
47 | * /<sysfs>/class/ubi/ubiX_Y/reserved_ebs; |
48 | * B. process 2 removes volume Y; |
49 | * C. process 1 starts reading the /<sysfs>/class/ubi/ubiX_Y/reserved_ebs file; |
50 | * |
51 | * In this situation, this function will return %-ENODEV because it will find |
52 | * out that the volume was removed from the @ubi->volumes array. |
53 | */ |
54 | static ssize_t vol_attribute_show(struct device *dev, |
55 | struct device_attribute *attr, char *buf) |
56 | { |
57 | int ret; |
58 | struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); |
59 | struct ubi_device *ubi = vol->ubi; |
60 | |
61 | spin_lock(lock: &ubi->volumes_lock); |
62 | if (!ubi->volumes[vol->vol_id] || ubi->volumes[vol->vol_id]->is_dead) { |
63 | spin_unlock(lock: &ubi->volumes_lock); |
64 | return -ENODEV; |
65 | } |
66 | /* Take a reference to prevent volume removal */ |
67 | vol->ref_count += 1; |
68 | spin_unlock(lock: &ubi->volumes_lock); |
69 | |
70 | if (attr == &attr_vol_reserved_ebs) |
71 | ret = sprintf(buf, fmt: "%d\n" , vol->reserved_pebs); |
72 | else if (attr == &attr_vol_type) { |
73 | const char *tp; |
74 | |
75 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) |
76 | tp = "dynamic" ; |
77 | else |
78 | tp = "static" ; |
79 | ret = sprintf(buf, fmt: "%s\n" , tp); |
80 | } else if (attr == &attr_vol_name) |
81 | ret = sprintf(buf, fmt: "%s\n" , vol->name); |
82 | else if (attr == &attr_vol_corrupted) |
83 | ret = sprintf(buf, fmt: "%d\n" , vol->corrupted); |
84 | else if (attr == &attr_vol_alignment) |
85 | ret = sprintf(buf, fmt: "%d\n" , vol->alignment); |
86 | else if (attr == &attr_vol_usable_eb_size) |
87 | ret = sprintf(buf, fmt: "%d\n" , vol->usable_leb_size); |
88 | else if (attr == &attr_vol_data_bytes) |
89 | ret = sprintf(buf, fmt: "%lld\n" , vol->used_bytes); |
90 | else if (attr == &attr_vol_upd_marker) |
91 | ret = sprintf(buf, fmt: "%d\n" , vol->upd_marker); |
92 | else |
93 | /* This must be a bug */ |
94 | ret = -EINVAL; |
95 | |
96 | /* We've done the operation, drop volume and UBI device references */ |
97 | spin_lock(lock: &ubi->volumes_lock); |
98 | vol->ref_count -= 1; |
99 | ubi_assert(vol->ref_count >= 0); |
100 | spin_unlock(lock: &ubi->volumes_lock); |
101 | return ret; |
102 | } |
103 | |
104 | static struct attribute *volume_dev_attrs[] = { |
105 | &attr_vol_reserved_ebs.attr, |
106 | &attr_vol_type.attr, |
107 | &attr_vol_name.attr, |
108 | &attr_vol_corrupted.attr, |
109 | &attr_vol_alignment.attr, |
110 | &attr_vol_usable_eb_size.attr, |
111 | &attr_vol_data_bytes.attr, |
112 | &attr_vol_upd_marker.attr, |
113 | NULL |
114 | }; |
115 | ATTRIBUTE_GROUPS(volume_dev); |
116 | |
117 | /* Release method for volume devices */ |
118 | static void vol_release(struct device *dev) |
119 | { |
120 | struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); |
121 | |
122 | ubi_eba_replace_table(vol, NULL); |
123 | ubi_fastmap_destroy_checkmap(vol); |
124 | kfree(objp: vol); |
125 | } |
126 | |
127 | static struct fwnode_handle *find_volume_fwnode(struct ubi_volume *vol) |
128 | { |
129 | struct fwnode_handle *fw_vols, *fw_vol; |
130 | const char *volname; |
131 | u32 volid; |
132 | |
133 | fw_vols = device_get_named_child_node(dev: vol->dev.parent->parent, childname: "volumes" ); |
134 | if (!fw_vols) |
135 | return NULL; |
136 | |
137 | fwnode_for_each_child_node(fw_vols, fw_vol) { |
138 | if (!fwnode_property_read_string(fwnode: fw_vol, propname: "volname" , val: &volname) && |
139 | strncmp(volname, vol->name, vol->name_len)) |
140 | continue; |
141 | |
142 | if (!fwnode_property_read_u32(fwnode: fw_vol, propname: "volid" , val: &volid) && |
143 | vol->vol_id != volid) |
144 | continue; |
145 | |
146 | return fw_vol; |
147 | } |
148 | |
149 | return NULL; |
150 | } |
151 | |
152 | /** |
153 | * ubi_create_volume - create volume. |
154 | * @ubi: UBI device description object |
155 | * @req: volume creation request |
156 | * |
157 | * This function creates volume described by @req. If @req->vol_id id |
158 | * %UBI_VOL_NUM_AUTO, this function automatically assign ID to the new volume |
159 | * and saves it in @req->vol_id. Returns zero in case of success and a negative |
160 | * error code in case of failure. Note, the caller has to have the |
161 | * @ubi->device_mutex locked. |
162 | */ |
163 | int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) |
164 | { |
165 | int i, err, vol_id = req->vol_id; |
166 | struct ubi_volume *vol; |
167 | struct ubi_vtbl_record vtbl_rec; |
168 | struct ubi_eba_table *eba_tbl = NULL; |
169 | |
170 | if (ubi->ro_mode) |
171 | return -EROFS; |
172 | |
173 | vol = kzalloc(size: sizeof(struct ubi_volume), GFP_KERNEL); |
174 | if (!vol) |
175 | return -ENOMEM; |
176 | |
177 | device_initialize(dev: &vol->dev); |
178 | vol->dev.release = vol_release; |
179 | vol->dev.parent = &ubi->dev; |
180 | vol->dev.class = &ubi_class; |
181 | vol->dev.groups = volume_dev_groups; |
182 | |
183 | if (req->flags & UBI_VOL_SKIP_CRC_CHECK_FLG) |
184 | vol->skip_check = 1; |
185 | |
186 | spin_lock(lock: &ubi->volumes_lock); |
187 | if (vol_id == UBI_VOL_NUM_AUTO) { |
188 | /* Find unused volume ID */ |
189 | dbg_gen("search for vacant volume ID" ); |
190 | for (i = 0; i < ubi->vtbl_slots; i++) |
191 | if (!ubi->volumes[i]) { |
192 | vol_id = i; |
193 | break; |
194 | } |
195 | |
196 | if (vol_id == UBI_VOL_NUM_AUTO) { |
197 | ubi_err(ubi, fmt: "out of volume IDs" ); |
198 | err = -ENFILE; |
199 | goto out_unlock; |
200 | } |
201 | req->vol_id = vol_id; |
202 | } |
203 | |
204 | dbg_gen("create device %d, volume %d, %llu bytes, type %d, name %s" , |
205 | ubi->ubi_num, vol_id, (unsigned long long)req->bytes, |
206 | (int)req->vol_type, req->name); |
207 | |
208 | /* Ensure that this volume does not exist */ |
209 | err = -EEXIST; |
210 | if (ubi->volumes[vol_id]) { |
211 | ubi_err(ubi, fmt: "volume %d already exists" , vol_id); |
212 | goto out_unlock; |
213 | } |
214 | |
215 | /* Ensure that the name is unique */ |
216 | for (i = 0; i < ubi->vtbl_slots; i++) |
217 | if (ubi->volumes[i] && !ubi->volumes[i]->is_dead && |
218 | ubi->volumes[i]->name_len == req->name_len && |
219 | !strcmp(ubi->volumes[i]->name, req->name)) { |
220 | ubi_err(ubi, fmt: "volume \"%s\" exists (ID %d)" , |
221 | req->name, i); |
222 | goto out_unlock; |
223 | } |
224 | |
225 | /* Calculate how many eraseblocks are requested */ |
226 | vol->usable_leb_size = ubi->leb_size - ubi->leb_size % req->alignment; |
227 | vol->reserved_pebs = div_u64(dividend: req->bytes + vol->usable_leb_size - 1, |
228 | divisor: vol->usable_leb_size); |
229 | |
230 | /* Reserve physical eraseblocks */ |
231 | if (vol->reserved_pebs > ubi->avail_pebs) { |
232 | ubi_err(ubi, fmt: "not enough PEBs, only %d available" , |
233 | ubi->avail_pebs); |
234 | if (ubi->corr_peb_count) |
235 | ubi_err(ubi, fmt: "%d PEBs are corrupted and not used" , |
236 | ubi->corr_peb_count); |
237 | err = -ENOSPC; |
238 | goto out_unlock; |
239 | } |
240 | ubi->avail_pebs -= vol->reserved_pebs; |
241 | ubi->rsvd_pebs += vol->reserved_pebs; |
242 | spin_unlock(lock: &ubi->volumes_lock); |
243 | |
244 | vol->vol_id = vol_id; |
245 | vol->alignment = req->alignment; |
246 | vol->data_pad = ubi->leb_size % vol->alignment; |
247 | vol->vol_type = req->vol_type; |
248 | vol->name_len = req->name_len; |
249 | memcpy(vol->name, req->name, vol->name_len); |
250 | vol->ubi = ubi; |
251 | device_set_node(dev: &vol->dev, fwnode: find_volume_fwnode(vol)); |
252 | |
253 | /* |
254 | * Finish all pending erases because there may be some LEBs belonging |
255 | * to the same volume ID. |
256 | */ |
257 | err = ubi_wl_flush(ubi, vol_id, UBI_ALL); |
258 | if (err) |
259 | goto out_acc; |
260 | |
261 | eba_tbl = ubi_eba_create_table(vol, nentries: vol->reserved_pebs); |
262 | if (IS_ERR(ptr: eba_tbl)) { |
263 | err = PTR_ERR(ptr: eba_tbl); |
264 | goto out_acc; |
265 | } |
266 | |
267 | ubi_eba_replace_table(vol, tbl: eba_tbl); |
268 | |
269 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) { |
270 | vol->used_ebs = vol->reserved_pebs; |
271 | vol->last_eb_bytes = vol->usable_leb_size; |
272 | vol->used_bytes = |
273 | (long long)vol->used_ebs * vol->usable_leb_size; |
274 | } else { |
275 | vol->used_ebs = div_u64_rem(dividend: vol->used_bytes, |
276 | divisor: vol->usable_leb_size, |
277 | remainder: &vol->last_eb_bytes); |
278 | if (vol->last_eb_bytes != 0) |
279 | vol->used_ebs += 1; |
280 | else |
281 | vol->last_eb_bytes = vol->usable_leb_size; |
282 | } |
283 | |
284 | /* Make volume "available" before it becomes accessible via sysfs */ |
285 | spin_lock(lock: &ubi->volumes_lock); |
286 | ubi->volumes[vol_id] = vol; |
287 | ubi->vol_count += 1; |
288 | spin_unlock(lock: &ubi->volumes_lock); |
289 | |
290 | /* Register character device for the volume */ |
291 | cdev_init(&vol->cdev, &ubi_vol_cdev_operations); |
292 | vol->cdev.owner = THIS_MODULE; |
293 | |
294 | vol->dev.devt = MKDEV(MAJOR(ubi->cdev.dev), vol_id + 1); |
295 | dev_set_name(dev: &vol->dev, name: "%s_%d" , ubi->ubi_name, vol->vol_id); |
296 | err = cdev_device_add(cdev: &vol->cdev, dev: &vol->dev); |
297 | if (err) { |
298 | ubi_err(ubi, fmt: "cannot add device" ); |
299 | goto out_mapping; |
300 | } |
301 | |
302 | /* Fill volume table record */ |
303 | memset(&vtbl_rec, 0, sizeof(struct ubi_vtbl_record)); |
304 | vtbl_rec.reserved_pebs = cpu_to_be32(vol->reserved_pebs); |
305 | vtbl_rec.alignment = cpu_to_be32(vol->alignment); |
306 | vtbl_rec.data_pad = cpu_to_be32(vol->data_pad); |
307 | vtbl_rec.name_len = cpu_to_be16(vol->name_len); |
308 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) |
309 | vtbl_rec.vol_type = UBI_VID_DYNAMIC; |
310 | else |
311 | vtbl_rec.vol_type = UBI_VID_STATIC; |
312 | |
313 | if (vol->skip_check) |
314 | vtbl_rec.flags |= UBI_VTBL_SKIP_CRC_CHECK_FLG; |
315 | |
316 | memcpy(vtbl_rec.name, vol->name, vol->name_len); |
317 | |
318 | err = ubi_change_vtbl_record(ubi, idx: vol_id, vtbl_rec: &vtbl_rec); |
319 | if (err) |
320 | goto out_sysfs; |
321 | |
322 | ubi_volume_notify(ubi, vol, ntype: UBI_VOLUME_ADDED); |
323 | self_check_volumes(ubi); |
324 | return err; |
325 | |
326 | out_sysfs: |
327 | /* |
328 | * We have registered our device, we should not free the volume |
329 | * description object in this function in case of an error - it is |
330 | * freed by the release function. |
331 | */ |
332 | cdev_device_del(cdev: &vol->cdev, dev: &vol->dev); |
333 | out_mapping: |
334 | spin_lock(lock: &ubi->volumes_lock); |
335 | ubi->volumes[vol_id] = NULL; |
336 | ubi->vol_count -= 1; |
337 | spin_unlock(lock: &ubi->volumes_lock); |
338 | out_acc: |
339 | spin_lock(lock: &ubi->volumes_lock); |
340 | ubi->rsvd_pebs -= vol->reserved_pebs; |
341 | ubi->avail_pebs += vol->reserved_pebs; |
342 | out_unlock: |
343 | spin_unlock(lock: &ubi->volumes_lock); |
344 | put_device(dev: &vol->dev); |
345 | ubi_err(ubi, fmt: "cannot create volume %d, error %d" , vol_id, err); |
346 | return err; |
347 | } |
348 | |
349 | /** |
350 | * ubi_remove_volume - remove volume. |
351 | * @desc: volume descriptor |
352 | * @no_vtbl: do not change volume table if not zero |
353 | * |
354 | * This function removes volume described by @desc. The volume has to be opened |
355 | * in "exclusive" mode. Returns zero in case of success and a negative error |
356 | * code in case of failure. The caller has to have the @ubi->device_mutex |
357 | * locked. |
358 | */ |
359 | int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl) |
360 | { |
361 | struct ubi_volume *vol = desc->vol; |
362 | struct ubi_device *ubi = vol->ubi; |
363 | int i, err, vol_id = vol->vol_id, reserved_pebs = vol->reserved_pebs; |
364 | |
365 | dbg_gen("remove device %d, volume %d" , ubi->ubi_num, vol_id); |
366 | ubi_assert(desc->mode == UBI_EXCLUSIVE); |
367 | ubi_assert(vol == ubi->volumes[vol_id]); |
368 | |
369 | if (ubi->ro_mode) |
370 | return -EROFS; |
371 | |
372 | spin_lock(lock: &ubi->volumes_lock); |
373 | if (vol->ref_count > 1) { |
374 | /* |
375 | * The volume is busy, probably someone is reading one of its |
376 | * sysfs files. |
377 | */ |
378 | err = -EBUSY; |
379 | goto out_unlock; |
380 | } |
381 | |
382 | /* |
383 | * Mark volume as dead at this point to prevent that anyone |
384 | * can take a reference to the volume from now on. |
385 | * This is necessary as we have to release the spinlock before |
386 | * calling ubi_volume_notify. |
387 | */ |
388 | vol->is_dead = true; |
389 | spin_unlock(lock: &ubi->volumes_lock); |
390 | |
391 | ubi_volume_notify(ubi, vol, ntype: UBI_VOLUME_SHUTDOWN); |
392 | |
393 | spin_lock(lock: &ubi->volumes_lock); |
394 | ubi->volumes[vol_id] = NULL; |
395 | spin_unlock(lock: &ubi->volumes_lock); |
396 | |
397 | if (!no_vtbl) { |
398 | err = ubi_change_vtbl_record(ubi, idx: vol_id, NULL); |
399 | if (err) |
400 | goto out_err; |
401 | } |
402 | |
403 | for (i = 0; i < vol->reserved_pebs; i++) { |
404 | err = ubi_eba_unmap_leb(ubi, vol, lnum: i); |
405 | if (err) |
406 | goto out_err; |
407 | } |
408 | |
409 | cdev_device_del(cdev: &vol->cdev, dev: &vol->dev); |
410 | put_device(dev: &vol->dev); |
411 | |
412 | spin_lock(lock: &ubi->volumes_lock); |
413 | ubi->rsvd_pebs -= reserved_pebs; |
414 | ubi->avail_pebs += reserved_pebs; |
415 | ubi_update_reserved(ubi); |
416 | ubi->vol_count -= 1; |
417 | spin_unlock(lock: &ubi->volumes_lock); |
418 | |
419 | ubi_volume_notify(ubi, vol, ntype: UBI_VOLUME_REMOVED); |
420 | if (!no_vtbl) |
421 | self_check_volumes(ubi); |
422 | |
423 | return 0; |
424 | |
425 | out_err: |
426 | ubi_err(ubi, fmt: "cannot remove volume %d, error %d" , vol_id, err); |
427 | spin_lock(lock: &ubi->volumes_lock); |
428 | ubi->volumes[vol_id] = vol; |
429 | out_unlock: |
430 | spin_unlock(lock: &ubi->volumes_lock); |
431 | return err; |
432 | } |
433 | |
434 | /** |
435 | * ubi_resize_volume - re-size volume. |
436 | * @desc: volume descriptor |
437 | * @reserved_pebs: new size in physical eraseblocks |
438 | * |
439 | * This function re-sizes the volume and returns zero in case of success, and a |
440 | * negative error code in case of failure. The caller has to have the |
441 | * @ubi->device_mutex locked. |
442 | */ |
443 | int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) |
444 | { |
445 | int i, err, pebs; |
446 | struct ubi_volume *vol = desc->vol; |
447 | struct ubi_device *ubi = vol->ubi; |
448 | struct ubi_vtbl_record vtbl_rec; |
449 | struct ubi_eba_table *new_eba_tbl = NULL; |
450 | struct ubi_eba_table *old_eba_tbl = NULL; |
451 | int vol_id = vol->vol_id; |
452 | |
453 | if (ubi->ro_mode) |
454 | return -EROFS; |
455 | |
456 | dbg_gen("re-size device %d, volume %d to from %d to %d PEBs" , |
457 | ubi->ubi_num, vol_id, vol->reserved_pebs, reserved_pebs); |
458 | |
459 | if (vol->vol_type == UBI_STATIC_VOLUME && |
460 | reserved_pebs < vol->used_ebs) { |
461 | ubi_err(ubi, fmt: "too small size %d, %d LEBs contain data" , |
462 | reserved_pebs, vol->used_ebs); |
463 | return -EINVAL; |
464 | } |
465 | |
466 | /* If the size is the same, we have nothing to do */ |
467 | if (reserved_pebs == vol->reserved_pebs) |
468 | return 0; |
469 | |
470 | new_eba_tbl = ubi_eba_create_table(vol, nentries: reserved_pebs); |
471 | if (IS_ERR(ptr: new_eba_tbl)) |
472 | return PTR_ERR(ptr: new_eba_tbl); |
473 | |
474 | spin_lock(lock: &ubi->volumes_lock); |
475 | if (vol->ref_count > 1) { |
476 | spin_unlock(lock: &ubi->volumes_lock); |
477 | err = -EBUSY; |
478 | goto out_free; |
479 | } |
480 | spin_unlock(lock: &ubi->volumes_lock); |
481 | |
482 | /* Reserve physical eraseblocks */ |
483 | pebs = reserved_pebs - vol->reserved_pebs; |
484 | if (pebs > 0) { |
485 | spin_lock(lock: &ubi->volumes_lock); |
486 | if (pebs > ubi->avail_pebs) { |
487 | ubi_err(ubi, fmt: "not enough PEBs: requested %d, available %d" , |
488 | pebs, ubi->avail_pebs); |
489 | if (ubi->corr_peb_count) |
490 | ubi_err(ubi, fmt: "%d PEBs are corrupted and not used" , |
491 | ubi->corr_peb_count); |
492 | spin_unlock(lock: &ubi->volumes_lock); |
493 | err = -ENOSPC; |
494 | goto out_free; |
495 | } |
496 | |
497 | ubi->avail_pebs -= pebs; |
498 | ubi->rsvd_pebs += pebs; |
499 | ubi_eba_copy_table(vol, dst: new_eba_tbl, nentries: vol->reserved_pebs); |
500 | old_eba_tbl = vol->eba_tbl; |
501 | vol->eba_tbl = new_eba_tbl; |
502 | vol->reserved_pebs = reserved_pebs; |
503 | spin_unlock(lock: &ubi->volumes_lock); |
504 | } |
505 | |
506 | if (pebs < 0) { |
507 | for (i = 0; i < -pebs; i++) { |
508 | err = ubi_eba_unmap_leb(ubi, vol, lnum: reserved_pebs + i); |
509 | if (err) |
510 | goto out_free; |
511 | } |
512 | spin_lock(lock: &ubi->volumes_lock); |
513 | ubi->rsvd_pebs += pebs; |
514 | ubi->avail_pebs -= pebs; |
515 | ubi_update_reserved(ubi); |
516 | ubi_eba_copy_table(vol, dst: new_eba_tbl, nentries: reserved_pebs); |
517 | old_eba_tbl = vol->eba_tbl; |
518 | vol->eba_tbl = new_eba_tbl; |
519 | vol->reserved_pebs = reserved_pebs; |
520 | spin_unlock(lock: &ubi->volumes_lock); |
521 | } |
522 | |
523 | /* |
524 | * When we shrink a volume we have to flush all pending (erase) work. |
525 | * Otherwise it can happen that upon next attach UBI finds a LEB with |
526 | * lnum > highest_lnum and refuses to attach. |
527 | */ |
528 | if (pebs < 0) { |
529 | err = ubi_wl_flush(ubi, vol_id, UBI_ALL); |
530 | if (err) |
531 | goto out_acc; |
532 | } |
533 | |
534 | /* Change volume table record */ |
535 | vtbl_rec = ubi->vtbl[vol_id]; |
536 | vtbl_rec.reserved_pebs = cpu_to_be32(reserved_pebs); |
537 | err = ubi_change_vtbl_record(ubi, idx: vol_id, vtbl_rec: &vtbl_rec); |
538 | if (err) |
539 | goto out_acc; |
540 | |
541 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) { |
542 | vol->used_ebs = reserved_pebs; |
543 | vol->last_eb_bytes = vol->usable_leb_size; |
544 | vol->used_bytes = |
545 | (long long)vol->used_ebs * vol->usable_leb_size; |
546 | } |
547 | |
548 | /* destroy old table */ |
549 | ubi_eba_destroy_table(tbl: old_eba_tbl); |
550 | ubi_volume_notify(ubi, vol, ntype: UBI_VOLUME_RESIZED); |
551 | self_check_volumes(ubi); |
552 | return err; |
553 | |
554 | out_acc: |
555 | spin_lock(lock: &ubi->volumes_lock); |
556 | vol->reserved_pebs = reserved_pebs - pebs; |
557 | ubi->rsvd_pebs -= pebs; |
558 | ubi->avail_pebs += pebs; |
559 | if (pebs > 0) |
560 | ubi_eba_copy_table(vol, dst: old_eba_tbl, nentries: vol->reserved_pebs); |
561 | else |
562 | ubi_eba_copy_table(vol, dst: old_eba_tbl, nentries: reserved_pebs); |
563 | vol->eba_tbl = old_eba_tbl; |
564 | spin_unlock(lock: &ubi->volumes_lock); |
565 | out_free: |
566 | ubi_eba_destroy_table(tbl: new_eba_tbl); |
567 | return err; |
568 | } |
569 | |
570 | /** |
571 | * ubi_rename_volumes - re-name UBI volumes. |
572 | * @ubi: UBI device description object |
573 | * @rename_list: list of &struct ubi_rename_entry objects |
574 | * |
575 | * This function re-names or removes volumes specified in the re-name list. |
576 | * Returns zero in case of success and a negative error code in case of |
577 | * failure. |
578 | */ |
579 | int ubi_rename_volumes(struct ubi_device *ubi, struct list_head *rename_list) |
580 | { |
581 | int err; |
582 | struct ubi_rename_entry *re; |
583 | |
584 | err = ubi_vtbl_rename_volumes(ubi, rename_list); |
585 | if (err) |
586 | return err; |
587 | |
588 | list_for_each_entry(re, rename_list, list) { |
589 | if (re->remove) { |
590 | err = ubi_remove_volume(desc: re->desc, no_vtbl: 1); |
591 | if (err) |
592 | break; |
593 | } else { |
594 | struct ubi_volume *vol = re->desc->vol; |
595 | |
596 | spin_lock(lock: &ubi->volumes_lock); |
597 | vol->name_len = re->new_name_len; |
598 | memcpy(vol->name, re->new_name, re->new_name_len + 1); |
599 | spin_unlock(lock: &ubi->volumes_lock); |
600 | ubi_volume_notify(ubi, vol, ntype: UBI_VOLUME_RENAMED); |
601 | } |
602 | } |
603 | |
604 | if (!err) |
605 | self_check_volumes(ubi); |
606 | return err; |
607 | } |
608 | |
609 | /** |
610 | * ubi_add_volume - add volume. |
611 | * @ubi: UBI device description object |
612 | * @vol: volume description object |
613 | * |
614 | * This function adds an existing volume and initializes all its data |
615 | * structures. Returns zero in case of success and a negative error code in |
616 | * case of failure. |
617 | */ |
618 | int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol) |
619 | { |
620 | int err, vol_id = vol->vol_id; |
621 | dev_t dev; |
622 | |
623 | dbg_gen("add volume %d" , vol_id); |
624 | |
625 | /* Register character device for the volume */ |
626 | cdev_init(&vol->cdev, &ubi_vol_cdev_operations); |
627 | vol->cdev.owner = THIS_MODULE; |
628 | dev = MKDEV(MAJOR(ubi->cdev.dev), vol->vol_id + 1); |
629 | err = cdev_add(&vol->cdev, dev, 1); |
630 | if (err) { |
631 | ubi_err(ubi, fmt: "cannot add character device for volume %d, error %d" , |
632 | vol_id, err); |
633 | vol_release(dev: &vol->dev); |
634 | return err; |
635 | } |
636 | |
637 | vol->dev.release = vol_release; |
638 | vol->dev.parent = &ubi->dev; |
639 | vol->dev.devt = dev; |
640 | vol->dev.class = &ubi_class; |
641 | vol->dev.groups = volume_dev_groups; |
642 | dev_set_name(dev: &vol->dev, name: "%s_%d" , ubi->ubi_name, vol->vol_id); |
643 | device_set_node(dev: &vol->dev, fwnode: find_volume_fwnode(vol)); |
644 | err = device_register(dev: &vol->dev); |
645 | if (err) { |
646 | cdev_del(&vol->cdev); |
647 | put_device(dev: &vol->dev); |
648 | return err; |
649 | } |
650 | |
651 | self_check_volumes(ubi); |
652 | return err; |
653 | } |
654 | |
655 | /** |
656 | * ubi_free_volume - free volume. |
657 | * @ubi: UBI device description object |
658 | * @vol: volume description object |
659 | * |
660 | * This function frees all resources for volume @vol but does not remove it. |
661 | * Used only when the UBI device is detached. |
662 | */ |
663 | void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol) |
664 | { |
665 | dbg_gen("free volume %d" , vol->vol_id); |
666 | |
667 | ubi->volumes[vol->vol_id] = NULL; |
668 | cdev_del(&vol->cdev); |
669 | device_unregister(dev: &vol->dev); |
670 | } |
671 | |
672 | /** |
673 | * self_check_volume - check volume information. |
674 | * @ubi: UBI device description object |
675 | * @vol_id: volume ID |
676 | * |
677 | * Returns zero if volume is all right and a negative error code if not. |
678 | */ |
679 | static int self_check_volume(struct ubi_device *ubi, int vol_id) |
680 | { |
681 | int idx = vol_id2idx(ubi, vol_id); |
682 | int reserved_pebs, alignment, data_pad, vol_type, name_len, upd_marker; |
683 | const struct ubi_volume *vol; |
684 | long long n; |
685 | const char *name; |
686 | |
687 | spin_lock(lock: &ubi->volumes_lock); |
688 | reserved_pebs = be32_to_cpu(ubi->vtbl[vol_id].reserved_pebs); |
689 | vol = ubi->volumes[idx]; |
690 | |
691 | if (!vol) { |
692 | if (reserved_pebs) { |
693 | ubi_err(ubi, fmt: "no volume info, but volume exists" ); |
694 | goto fail; |
695 | } |
696 | spin_unlock(lock: &ubi->volumes_lock); |
697 | return 0; |
698 | } |
699 | |
700 | if (vol->reserved_pebs < 0 || vol->alignment < 0 || vol->data_pad < 0 || |
701 | vol->name_len < 0) { |
702 | ubi_err(ubi, fmt: "negative values" ); |
703 | goto fail; |
704 | } |
705 | if (vol->alignment > ubi->leb_size || vol->alignment == 0) { |
706 | ubi_err(ubi, fmt: "bad alignment" ); |
707 | goto fail; |
708 | } |
709 | |
710 | n = vol->alignment & (ubi->min_io_size - 1); |
711 | if (vol->alignment != 1 && n) { |
712 | ubi_err(ubi, fmt: "alignment is not multiple of min I/O unit" ); |
713 | goto fail; |
714 | } |
715 | |
716 | n = ubi->leb_size % vol->alignment; |
717 | if (vol->data_pad != n) { |
718 | ubi_err(ubi, fmt: "bad data_pad, has to be %lld" , n); |
719 | goto fail; |
720 | } |
721 | |
722 | if (vol->vol_type != UBI_DYNAMIC_VOLUME && |
723 | vol->vol_type != UBI_STATIC_VOLUME) { |
724 | ubi_err(ubi, fmt: "bad vol_type" ); |
725 | goto fail; |
726 | } |
727 | |
728 | if (vol->upd_marker && vol->corrupted) { |
729 | ubi_err(ubi, fmt: "update marker and corrupted simultaneously" ); |
730 | goto fail; |
731 | } |
732 | |
733 | if (vol->reserved_pebs > ubi->good_peb_count) { |
734 | ubi_err(ubi, fmt: "too large reserved_pebs" ); |
735 | goto fail; |
736 | } |
737 | |
738 | n = ubi->leb_size - vol->data_pad; |
739 | if (vol->usable_leb_size != ubi->leb_size - vol->data_pad) { |
740 | ubi_err(ubi, fmt: "bad usable_leb_size, has to be %lld" , n); |
741 | goto fail; |
742 | } |
743 | |
744 | if (vol->name_len > UBI_VOL_NAME_MAX) { |
745 | ubi_err(ubi, fmt: "too long volume name, max is %d" , |
746 | UBI_VOL_NAME_MAX); |
747 | goto fail; |
748 | } |
749 | |
750 | n = strnlen(p: vol->name, maxlen: vol->name_len + 1); |
751 | if (n != vol->name_len) { |
752 | ubi_err(ubi, fmt: "bad name_len %lld" , n); |
753 | goto fail; |
754 | } |
755 | |
756 | n = (long long)vol->used_ebs * vol->usable_leb_size; |
757 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) { |
758 | if (vol->corrupted) { |
759 | ubi_err(ubi, fmt: "corrupted dynamic volume" ); |
760 | goto fail; |
761 | } |
762 | if (vol->used_ebs != vol->reserved_pebs) { |
763 | ubi_err(ubi, fmt: "bad used_ebs" ); |
764 | goto fail; |
765 | } |
766 | if (vol->last_eb_bytes != vol->usable_leb_size) { |
767 | ubi_err(ubi, fmt: "bad last_eb_bytes" ); |
768 | goto fail; |
769 | } |
770 | if (vol->used_bytes != n) { |
771 | ubi_err(ubi, fmt: "bad used_bytes" ); |
772 | goto fail; |
773 | } |
774 | |
775 | if (vol->skip_check) { |
776 | ubi_err(ubi, fmt: "bad skip_check" ); |
777 | goto fail; |
778 | } |
779 | } else { |
780 | if (vol->used_ebs < 0 || vol->used_ebs > vol->reserved_pebs) { |
781 | ubi_err(ubi, fmt: "bad used_ebs" ); |
782 | goto fail; |
783 | } |
784 | if (vol->last_eb_bytes < 0 || |
785 | vol->last_eb_bytes > vol->usable_leb_size) { |
786 | ubi_err(ubi, fmt: "bad last_eb_bytes" ); |
787 | goto fail; |
788 | } |
789 | if (vol->used_bytes < 0 || vol->used_bytes > n || |
790 | vol->used_bytes < n - vol->usable_leb_size) { |
791 | ubi_err(ubi, fmt: "bad used_bytes" ); |
792 | goto fail; |
793 | } |
794 | } |
795 | |
796 | alignment = be32_to_cpu(ubi->vtbl[vol_id].alignment); |
797 | data_pad = be32_to_cpu(ubi->vtbl[vol_id].data_pad); |
798 | name_len = be16_to_cpu(ubi->vtbl[vol_id].name_len); |
799 | upd_marker = ubi->vtbl[vol_id].upd_marker; |
800 | name = &ubi->vtbl[vol_id].name[0]; |
801 | if (ubi->vtbl[vol_id].vol_type == UBI_VID_DYNAMIC) |
802 | vol_type = UBI_DYNAMIC_VOLUME; |
803 | else |
804 | vol_type = UBI_STATIC_VOLUME; |
805 | |
806 | if (alignment != vol->alignment || data_pad != vol->data_pad || |
807 | upd_marker != vol->upd_marker || vol_type != vol->vol_type || |
808 | name_len != vol->name_len || strncmp(name, vol->name, name_len)) { |
809 | ubi_err(ubi, fmt: "volume info is different" ); |
810 | goto fail; |
811 | } |
812 | |
813 | spin_unlock(lock: &ubi->volumes_lock); |
814 | return 0; |
815 | |
816 | fail: |
817 | ubi_err(ubi, fmt: "self-check failed for volume %d" , vol_id); |
818 | if (vol) |
819 | ubi_dump_vol_info(vol); |
820 | ubi_dump_vtbl_record(r: &ubi->vtbl[vol_id], idx: vol_id); |
821 | dump_stack(); |
822 | spin_unlock(lock: &ubi->volumes_lock); |
823 | return -EINVAL; |
824 | } |
825 | |
826 | /** |
827 | * self_check_volumes - check information about all volumes. |
828 | * @ubi: UBI device description object |
829 | * |
830 | * Returns zero if volumes are all right and a negative error code if not. |
831 | */ |
832 | static int self_check_volumes(struct ubi_device *ubi) |
833 | { |
834 | int i, err = 0; |
835 | |
836 | if (!ubi_dbg_chk_gen(ubi)) |
837 | return 0; |
838 | |
839 | for (i = 0; i < ubi->vtbl_slots; i++) { |
840 | err = self_check_volume(ubi, vol_id: i); |
841 | if (err) |
842 | break; |
843 | } |
844 | |
845 | return err; |
846 | } |
847 | |