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