1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include <linux/module.h>
24#include <linux/err.h>
25#include <asm/div64.h>
26#include "ubi.h"
27
28
29
30
31
32
33
34
35
36void ubi_do_get_device_info(struct ubi_device *ubi, struct ubi_device_info *di)
37{
38 di->ubi_num = ubi->ubi_num;
39 di->leb_size = ubi->leb_size;
40 di->min_io_size = ubi->min_io_size;
41 di->ro_mode = ubi->ro_mode;
42 di->cdev = ubi->cdev.dev;
43}
44EXPORT_SYMBOL_GPL(ubi_do_get_device_info);
45
46
47
48
49
50
51
52
53
54int ubi_get_device_info(int ubi_num, struct ubi_device_info *di)
55{
56 struct ubi_device *ubi;
57
58 if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
59 return -EINVAL;
60 ubi = ubi_get_device(ubi_num);
61 if (!ubi)
62 return -ENODEV;
63 ubi_do_get_device_info(ubi, di);
64 ubi_put_device(ubi);
65 return 0;
66}
67EXPORT_SYMBOL_GPL(ubi_get_device_info);
68
69
70
71
72
73
74
75void ubi_do_get_volume_info(struct ubi_device *ubi, struct ubi_volume *vol,
76 struct ubi_volume_info *vi)
77{
78 vi->vol_id = vol->vol_id;
79 vi->ubi_num = ubi->ubi_num;
80 vi->size = vol->reserved_pebs;
81 vi->used_bytes = vol->used_bytes;
82 vi->vol_type = vol->vol_type;
83 vi->corrupted = vol->corrupted;
84 vi->upd_marker = vol->upd_marker;
85 vi->alignment = vol->alignment;
86 vi->usable_leb_size = vol->usable_leb_size;
87 vi->name_len = vol->name_len;
88 vi->name = vol->name;
89 vi->cdev = vol->cdev.dev;
90}
91
92
93
94
95
96
97void ubi_get_volume_info(struct ubi_volume_desc *desc,
98 struct ubi_volume_info *vi)
99{
100 ubi_do_get_volume_info(desc->vol->ubi, desc->vol, vi);
101}
102EXPORT_SYMBOL_GPL(ubi_get_volume_info);
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode)
123{
124 int err;
125 struct ubi_volume_desc *desc;
126 struct ubi_device *ubi;
127 struct ubi_volume *vol;
128
129 dbg_gen("open device %d, volume %d, mode %d", ubi_num, vol_id, mode);
130
131 if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
132 return ERR_PTR(-EINVAL);
133
134 if (mode != UBI_READONLY && mode != UBI_READWRITE &&
135 mode != UBI_EXCLUSIVE)
136 return ERR_PTR(-EINVAL);
137
138
139
140
141 ubi = ubi_get_device(ubi_num);
142 if (!ubi)
143 return ERR_PTR(-ENODEV);
144
145 if (vol_id < 0 || vol_id >= ubi->vtbl_slots) {
146 err = -EINVAL;
147 goto out_put_ubi;
148 }
149
150 desc = kmalloc(sizeof(struct ubi_volume_desc), GFP_KERNEL);
151 if (!desc) {
152 err = -ENOMEM;
153 goto out_put_ubi;
154 }
155
156 err = -ENODEV;
157 if (!try_module_get(THIS_MODULE))
158 goto out_free;
159
160 spin_lock(&ubi->volumes_lock);
161 vol = ubi->volumes[vol_id];
162 if (!vol)
163 goto out_unlock;
164
165 err = -EBUSY;
166 switch (mode) {
167 case UBI_READONLY:
168 if (vol->exclusive)
169 goto out_unlock;
170 vol->readers += 1;
171 break;
172
173 case UBI_READWRITE:
174 if (vol->exclusive || vol->writers > 0)
175 goto out_unlock;
176 vol->writers += 1;
177 break;
178
179 case UBI_EXCLUSIVE:
180 if (vol->exclusive || vol->writers || vol->readers)
181 goto out_unlock;
182 vol->exclusive = 1;
183 break;
184 }
185 get_device(&vol->dev);
186 vol->ref_count += 1;
187 spin_unlock(&ubi->volumes_lock);
188
189 desc->vol = vol;
190 desc->mode = mode;
191
192 mutex_lock(&ubi->ckvol_mutex);
193 if (!vol->checked) {
194
195 err = ubi_check_volume(ubi, vol_id);
196 if (err < 0) {
197 mutex_unlock(&ubi->ckvol_mutex);
198 ubi_close_volume(desc);
199 return ERR_PTR(err);
200 }
201 if (err == 1) {
202 ubi_warn("volume %d on UBI device %d is corrupted",
203 vol_id, ubi->ubi_num);
204 vol->corrupted = 1;
205 }
206 vol->checked = 1;
207 }
208 mutex_unlock(&ubi->ckvol_mutex);
209
210 return desc;
211
212out_unlock:
213 spin_unlock(&ubi->volumes_lock);
214 module_put(THIS_MODULE);
215out_free:
216 kfree(desc);
217out_put_ubi:
218 ubi_put_device(ubi);
219 dbg_err("cannot open device %d, volume %d, error %d",
220 ubi_num, vol_id, err);
221 return ERR_PTR(err);
222}
223EXPORT_SYMBOL_GPL(ubi_open_volume);
224
225
226
227
228
229
230
231
232
233struct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name,
234 int mode)
235{
236 int i, vol_id = -1, len;
237 struct ubi_device *ubi;
238 struct ubi_volume_desc *ret;
239
240 dbg_gen("open device %d, volume %s, mode %d", ubi_num, name, mode);
241
242 if (!name)
243 return ERR_PTR(-EINVAL);
244
245 len = strnlen(name, UBI_VOL_NAME_MAX + 1);
246 if (len > UBI_VOL_NAME_MAX)
247 return ERR_PTR(-EINVAL);
248
249 if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
250 return ERR_PTR(-EINVAL);
251
252 ubi = ubi_get_device(ubi_num);
253 if (!ubi)
254 return ERR_PTR(-ENODEV);
255
256 spin_lock(&ubi->volumes_lock);
257
258 for (i = 0; i < ubi->vtbl_slots; i++) {
259 struct ubi_volume *vol = ubi->volumes[i];
260
261 if (vol && len == vol->name_len && !strcmp(name, vol->name)) {
262 vol_id = i;
263 break;
264 }
265 }
266 spin_unlock(&ubi->volumes_lock);
267
268 if (vol_id >= 0)
269 ret = ubi_open_volume(ubi_num, vol_id, mode);
270 else
271 ret = ERR_PTR(-ENODEV);
272
273
274
275
276
277 ubi_put_device(ubi);
278 return ret;
279}
280EXPORT_SYMBOL_GPL(ubi_open_volume_nm);
281
282
283
284
285
286void ubi_close_volume(struct ubi_volume_desc *desc)
287{
288 struct ubi_volume *vol = desc->vol;
289 struct ubi_device *ubi = vol->ubi;
290
291 dbg_gen("close device %d, volume %d, mode %d",
292 ubi->ubi_num, vol->vol_id, desc->mode);
293
294 spin_lock(&ubi->volumes_lock);
295 switch (desc->mode) {
296 case UBI_READONLY:
297 vol->readers -= 1;
298 break;
299 case UBI_READWRITE:
300 vol->writers -= 1;
301 break;
302 case UBI_EXCLUSIVE:
303 vol->exclusive = 0;
304 }
305 vol->ref_count -= 1;
306 spin_unlock(&ubi->volumes_lock);
307
308 kfree(desc);
309 put_device(&vol->dev);
310 ubi_put_device(ubi);
311 module_put(THIS_MODULE);
312}
313EXPORT_SYMBOL_GPL(ubi_close_volume);
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
343 int len, int check)
344{
345 struct ubi_volume *vol = desc->vol;
346 struct ubi_device *ubi = vol->ubi;
347 int err, vol_id = vol->vol_id;
348
349 dbg_gen("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset);
350
351 if (vol_id < 0 || vol_id >= ubi->vtbl_slots || lnum < 0 ||
352 lnum >= vol->used_ebs || offset < 0 || len < 0 ||
353 offset + len > vol->usable_leb_size)
354 return -EINVAL;
355
356 if (vol->vol_type == UBI_STATIC_VOLUME) {
357 if (vol->used_ebs == 0)
358
359 return 0;
360 if (lnum == vol->used_ebs - 1 &&
361 offset + len > vol->last_eb_bytes)
362 return -EINVAL;
363 }
364
365 if (vol->upd_marker)
366 return -EBADF;
367 if (len == 0)
368 return 0;
369
370 err = ubi_eba_read_leb(ubi, vol, lnum, buf, offset, len, check);
371 if (err && err == -EBADMSG && vol->vol_type == UBI_STATIC_VOLUME) {
372 ubi_warn("mark volume %d as corrupted", vol_id);
373 vol->corrupted = 1;
374 }
375
376 return err;
377}
378EXPORT_SYMBOL_GPL(ubi_leb_read);
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
408 int offset, int len, int dtype)
409{
410 struct ubi_volume *vol = desc->vol;
411 struct ubi_device *ubi = vol->ubi;
412 int vol_id = vol->vol_id;
413
414 dbg_gen("write %d bytes to LEB %d:%d:%d", len, vol_id, lnum, offset);
415
416 if (vol_id < 0 || vol_id >= ubi->vtbl_slots)
417 return -EINVAL;
418
419 if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
420 return -EROFS;
421
422 if (lnum < 0 || lnum >= vol->reserved_pebs || offset < 0 || len < 0 ||
423 offset + len > vol->usable_leb_size ||
424 offset & (ubi->min_io_size - 1) || len & (ubi->min_io_size - 1))
425 return -EINVAL;
426
427 if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
428 dtype != UBI_UNKNOWN)
429 return -EINVAL;
430
431 if (vol->upd_marker)
432 return -EBADF;
433
434 if (len == 0)
435 return 0;
436
437 return ubi_eba_write_leb(ubi, vol, lnum, buf, offset, len, dtype);
438}
439EXPORT_SYMBOL_GPL(ubi_leb_write);
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
458 int len, int dtype)
459{
460 struct ubi_volume *vol = desc->vol;
461 struct ubi_device *ubi = vol->ubi;
462 int vol_id = vol->vol_id;
463
464 dbg_gen("atomically write %d bytes to LEB %d:%d", len, vol_id, lnum);
465
466 if (vol_id < 0 || vol_id >= ubi->vtbl_slots)
467 return -EINVAL;
468
469 if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
470 return -EROFS;
471
472 if (lnum < 0 || lnum >= vol->reserved_pebs || len < 0 ||
473 len > vol->usable_leb_size || len & (ubi->min_io_size - 1))
474 return -EINVAL;
475
476 if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
477 dtype != UBI_UNKNOWN)
478 return -EINVAL;
479
480 if (vol->upd_marker)
481 return -EBADF;
482
483 if (len == 0)
484 return 0;
485
486 return ubi_eba_atomic_leb_change(ubi, vol, lnum, buf, len, dtype);
487}
488EXPORT_SYMBOL_GPL(ubi_leb_change);
489
490
491
492
493
494
495
496
497
498
499
500
501
502int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum)
503{
504 struct ubi_volume *vol = desc->vol;
505 struct ubi_device *ubi = vol->ubi;
506 int err;
507
508 dbg_gen("erase LEB %d:%d", vol->vol_id, lnum);
509
510 if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
511 return -EROFS;
512
513 if (lnum < 0 || lnum >= vol->reserved_pebs)
514 return -EINVAL;
515
516 if (vol->upd_marker)
517 return -EBADF;
518
519 err = ubi_eba_unmap_leb(ubi, vol, lnum);
520 if (err)
521 return err;
522
523 return ubi_wl_flush(ubi);
524}
525EXPORT_SYMBOL_GPL(ubi_leb_erase);
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum)
564{
565 struct ubi_volume *vol = desc->vol;
566 struct ubi_device *ubi = vol->ubi;
567
568 dbg_gen("unmap LEB %d:%d", vol->vol_id, lnum);
569
570 if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
571 return -EROFS;
572
573 if (lnum < 0 || lnum >= vol->reserved_pebs)
574 return -EINVAL;
575
576 if (vol->upd_marker)
577 return -EBADF;
578
579 return ubi_eba_unmap_leb(ubi, vol, lnum);
580}
581EXPORT_SYMBOL_GPL(ubi_leb_unmap);
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype)
601{
602 struct ubi_volume *vol = desc->vol;
603 struct ubi_device *ubi = vol->ubi;
604
605 dbg_gen("unmap LEB %d:%d", vol->vol_id, lnum);
606
607 if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME)
608 return -EROFS;
609
610 if (lnum < 0 || lnum >= vol->reserved_pebs)
611 return -EINVAL;
612
613 if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
614 dtype != UBI_UNKNOWN)
615 return -EINVAL;
616
617 if (vol->upd_marker)
618 return -EBADF;
619
620 if (vol->eba_tbl[lnum] >= 0)
621 return -EBADMSG;
622
623 return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0, dtype);
624}
625EXPORT_SYMBOL_GPL(ubi_leb_map);
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum)
644{
645 struct ubi_volume *vol = desc->vol;
646
647 dbg_gen("test LEB %d:%d", vol->vol_id, lnum);
648
649 if (lnum < 0 || lnum >= vol->reserved_pebs)
650 return -EINVAL;
651
652 if (vol->upd_marker)
653 return -EBADF;
654
655 return vol->eba_tbl[lnum] >= 0;
656}
657EXPORT_SYMBOL_GPL(ubi_is_mapped);
658
659
660
661
662
663
664
665
666
667int ubi_sync(int ubi_num)
668{
669 struct ubi_device *ubi;
670
671 ubi = ubi_get_device(ubi_num);
672 if (!ubi)
673 return -ENODEV;
674
675 if (ubi->mtd->sync)
676 ubi->mtd->sync(ubi->mtd);
677
678 ubi_put_device(ubi);
679 return 0;
680}
681EXPORT_SYMBOL_GPL(ubi_sync);
682
683BLOCKING_NOTIFIER_HEAD(ubi_notifiers);
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701int ubi_register_volume_notifier(struct notifier_block *nb,
702 int ignore_existing)
703{
704 int err;
705
706 err = blocking_notifier_chain_register(&ubi_notifiers, nb);
707 if (err != 0)
708 return err;
709 if (ignore_existing)
710 return 0;
711
712
713
714
715
716
717
718 mutex_lock(&ubi_devices_mutex);
719 ubi_enumerate_volumes(nb);
720 mutex_unlock(&ubi_devices_mutex);
721
722 return err;
723}
724EXPORT_SYMBOL_GPL(ubi_register_volume_notifier);
725
726
727
728
729
730
731
732
733int ubi_unregister_volume_notifier(struct notifier_block *nb)
734{
735 return blocking_notifier_chain_unregister(&ubi_notifiers, nb);
736}
737EXPORT_SYMBOL_GPL(ubi_unregister_volume_notifier);
738