1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#include <linux/crc16.h>
29#include <linux/slab.h>
30#include <linux/random.h>
31#include "ubifs.h"
32
33static int dbg_populate_lsave(struct ubifs_info *c);
34
35
36
37
38
39
40
41
42static struct ubifs_cnode *first_dirty_cnode(struct ubifs_nnode *nnode)
43{
44 ubifs_assert(nnode);
45 while (1) {
46 int i, cont = 0;
47
48 for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
49 struct ubifs_cnode *cnode;
50
51 cnode = nnode->nbranch[i].cnode;
52 if (cnode &&
53 test_bit(DIRTY_CNODE, &cnode->flags)) {
54 if (cnode->level == 0)
55 return cnode;
56 nnode = (struct ubifs_nnode *)cnode;
57 cont = 1;
58 break;
59 }
60 }
61 if (!cont)
62 return (struct ubifs_cnode *)nnode;
63 }
64}
65
66
67
68
69
70
71
72static struct ubifs_cnode *next_dirty_cnode(struct ubifs_cnode *cnode)
73{
74 struct ubifs_nnode *nnode;
75 int i;
76
77 ubifs_assert(cnode);
78 nnode = cnode->parent;
79 if (!nnode)
80 return NULL;
81 for (i = cnode->iip + 1; i < UBIFS_LPT_FANOUT; i++) {
82 cnode = nnode->nbranch[i].cnode;
83 if (cnode && test_bit(DIRTY_CNODE, &cnode->flags)) {
84 if (cnode->level == 0)
85 return cnode;
86
87 return first_dirty_cnode((struct ubifs_nnode *)cnode);
88 }
89 }
90 return (struct ubifs_cnode *)nnode;
91}
92
93
94
95
96
97
98
99static int get_cnodes_to_commit(struct ubifs_info *c)
100{
101 struct ubifs_cnode *cnode, *cnext;
102 int cnt = 0;
103
104 if (!c->nroot)
105 return 0;
106
107 if (!test_bit(DIRTY_CNODE, &c->nroot->flags))
108 return 0;
109
110 c->lpt_cnext = first_dirty_cnode(c->nroot);
111 cnode = c->lpt_cnext;
112 if (!cnode)
113 return 0;
114 cnt += 1;
115 while (1) {
116 ubifs_assert(!test_bit(COW_CNODE, &cnode->flags));
117 __set_bit(COW_CNODE, &cnode->flags);
118 cnext = next_dirty_cnode(cnode);
119 if (!cnext) {
120 cnode->cnext = c->lpt_cnext;
121 break;
122 }
123 cnode->cnext = cnext;
124 cnode = cnext;
125 cnt += 1;
126 }
127 dbg_cmt("committing %d cnodes", cnt);
128 dbg_lp("committing %d cnodes", cnt);
129 ubifs_assert(cnt == c->dirty_nn_cnt + c->dirty_pn_cnt);
130 return cnt;
131}
132
133
134
135
136
137
138
139
140static void upd_ltab(struct ubifs_info *c, int lnum, int free, int dirty)
141{
142 dbg_lp("LEB %d free %d dirty %d to %d +%d",
143 lnum, c->ltab[lnum - c->lpt_first].free,
144 c->ltab[lnum - c->lpt_first].dirty, free, dirty);
145 ubifs_assert(lnum >= c->lpt_first && lnum <= c->lpt_last);
146 c->ltab[lnum - c->lpt_first].free = free;
147 c->ltab[lnum - c->lpt_first].dirty += dirty;
148}
149
150
151
152
153
154
155
156
157
158
159
160static int alloc_lpt_leb(struct ubifs_info *c, int *lnum)
161{
162 int i, n;
163
164 n = *lnum - c->lpt_first + 1;
165 for (i = n; i < c->lpt_lebs; i++) {
166 if (c->ltab[i].tgc || c->ltab[i].cmt)
167 continue;
168 if (c->ltab[i].free == c->leb_size) {
169 c->ltab[i].cmt = 1;
170 *lnum = i + c->lpt_first;
171 return 0;
172 }
173 }
174
175 for (i = 0; i < n; i++) {
176 if (c->ltab[i].tgc || c->ltab[i].cmt)
177 continue;
178 if (c->ltab[i].free == c->leb_size) {
179 c->ltab[i].cmt = 1;
180 *lnum = i + c->lpt_first;
181 return 0;
182 }
183 }
184 return -ENOSPC;
185}
186
187
188
189
190
191
192
193static int layout_cnodes(struct ubifs_info *c)
194{
195 int lnum, offs, len, alen, done_lsave, done_ltab, err;
196 struct ubifs_cnode *cnode;
197
198 err = dbg_chk_lpt_sz(c, 0, 0);
199 if (err)
200 return err;
201 cnode = c->lpt_cnext;
202 if (!cnode)
203 return 0;
204 lnum = c->nhead_lnum;
205 offs = c->nhead_offs;
206
207 done_lsave = !c->big_lpt;
208 done_ltab = 0;
209 if (!done_lsave && offs + c->lsave_sz <= c->leb_size) {
210 done_lsave = 1;
211 c->lsave_lnum = lnum;
212 c->lsave_offs = offs;
213 offs += c->lsave_sz;
214 dbg_chk_lpt_sz(c, 1, c->lsave_sz);
215 }
216
217 if (offs + c->ltab_sz <= c->leb_size) {
218 done_ltab = 1;
219 c->ltab_lnum = lnum;
220 c->ltab_offs = offs;
221 offs += c->ltab_sz;
222 dbg_chk_lpt_sz(c, 1, c->ltab_sz);
223 }
224
225 do {
226 if (cnode->level) {
227 len = c->nnode_sz;
228 c->dirty_nn_cnt -= 1;
229 } else {
230 len = c->pnode_sz;
231 c->dirty_pn_cnt -= 1;
232 }
233 while (offs + len > c->leb_size) {
234 alen = ALIGN(offs, c->min_io_size);
235 upd_ltab(c, lnum, c->leb_size - alen, alen - offs);
236 dbg_chk_lpt_sz(c, 2, c->leb_size - offs);
237 err = alloc_lpt_leb(c, &lnum);
238 if (err)
239 goto no_space;
240 offs = 0;
241 ubifs_assert(lnum >= c->lpt_first &&
242 lnum <= c->lpt_last);
243
244 if (!done_lsave) {
245 done_lsave = 1;
246 c->lsave_lnum = lnum;
247 c->lsave_offs = offs;
248 offs += c->lsave_sz;
249 dbg_chk_lpt_sz(c, 1, c->lsave_sz);
250 continue;
251 }
252 if (!done_ltab) {
253 done_ltab = 1;
254 c->ltab_lnum = lnum;
255 c->ltab_offs = offs;
256 offs += c->ltab_sz;
257 dbg_chk_lpt_sz(c, 1, c->ltab_sz);
258 continue;
259 }
260 break;
261 }
262 if (cnode->parent) {
263 cnode->parent->nbranch[cnode->iip].lnum = lnum;
264 cnode->parent->nbranch[cnode->iip].offs = offs;
265 } else {
266 c->lpt_lnum = lnum;
267 c->lpt_offs = offs;
268 }
269 offs += len;
270 dbg_chk_lpt_sz(c, 1, len);
271 cnode = cnode->cnext;
272 } while (cnode && cnode != c->lpt_cnext);
273
274
275 if (!done_lsave) {
276 if (offs + c->lsave_sz > c->leb_size) {
277 alen = ALIGN(offs, c->min_io_size);
278 upd_ltab(c, lnum, c->leb_size - alen, alen - offs);
279 dbg_chk_lpt_sz(c, 2, c->leb_size - offs);
280 err = alloc_lpt_leb(c, &lnum);
281 if (err)
282 goto no_space;
283 offs = 0;
284 ubifs_assert(lnum >= c->lpt_first &&
285 lnum <= c->lpt_last);
286 }
287 done_lsave = 1;
288 c->lsave_lnum = lnum;
289 c->lsave_offs = offs;
290 offs += c->lsave_sz;
291 dbg_chk_lpt_sz(c, 1, c->lsave_sz);
292 }
293
294
295 if (!done_ltab) {
296 if (offs + c->ltab_sz > c->leb_size) {
297 alen = ALIGN(offs, c->min_io_size);
298 upd_ltab(c, lnum, c->leb_size - alen, alen - offs);
299 dbg_chk_lpt_sz(c, 2, c->leb_size - offs);
300 err = alloc_lpt_leb(c, &lnum);
301 if (err)
302 goto no_space;
303 offs = 0;
304 ubifs_assert(lnum >= c->lpt_first &&
305 lnum <= c->lpt_last);
306 }
307 done_ltab = 1;
308 c->ltab_lnum = lnum;
309 c->ltab_offs = offs;
310 offs += c->ltab_sz;
311 dbg_chk_lpt_sz(c, 1, c->ltab_sz);
312 }
313
314 alen = ALIGN(offs, c->min_io_size);
315 upd_ltab(c, lnum, c->leb_size - alen, alen - offs);
316 dbg_chk_lpt_sz(c, 4, alen - offs);
317 err = dbg_chk_lpt_sz(c, 3, alen);
318 if (err)
319 return err;
320 return 0;
321
322no_space:
323 ubifs_err("LPT out of space at LEB %d:%d needing %d, done_ltab %d, "
324 "done_lsave %d", lnum, offs, len, done_ltab, done_lsave);
325 ubifs_dump_lpt_info(c);
326 ubifs_dump_lpt_lebs(c);
327 dump_stack();
328 return err;
329}
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345static int realloc_lpt_leb(struct ubifs_info *c, int *lnum)
346{
347 int i, n;
348
349 n = *lnum - c->lpt_first + 1;
350 for (i = n; i < c->lpt_lebs; i++)
351 if (c->ltab[i].cmt) {
352 c->ltab[i].cmt = 0;
353 *lnum = i + c->lpt_first;
354 return 0;
355 }
356
357 for (i = 0; i < n; i++)
358 if (c->ltab[i].cmt) {
359 c->ltab[i].cmt = 0;
360 *lnum = i + c->lpt_first;
361 return 0;
362 }
363 return -ENOSPC;
364}
365
366
367
368
369
370
371
372static int write_cnodes(struct ubifs_info *c)
373{
374 int lnum, offs, len, from, err, wlen, alen, done_ltab, done_lsave;
375 struct ubifs_cnode *cnode;
376 void *buf = c->lpt_buf;
377
378 cnode = c->lpt_cnext;
379 if (!cnode)
380 return 0;
381 lnum = c->nhead_lnum;
382 offs = c->nhead_offs;
383 from = offs;
384
385 if (offs == 0) {
386 err = ubifs_leb_unmap(c, lnum);
387 if (err)
388 return err;
389 }
390
391 done_lsave = !c->big_lpt;
392 done_ltab = 0;
393 if (!done_lsave && offs + c->lsave_sz <= c->leb_size) {
394 done_lsave = 1;
395 ubifs_pack_lsave(c, buf + offs, c->lsave);
396 offs += c->lsave_sz;
397 dbg_chk_lpt_sz(c, 1, c->lsave_sz);
398 }
399
400 if (offs + c->ltab_sz <= c->leb_size) {
401 done_ltab = 1;
402 ubifs_pack_ltab(c, buf + offs, c->ltab_cmt);
403 offs += c->ltab_sz;
404 dbg_chk_lpt_sz(c, 1, c->ltab_sz);
405 }
406
407
408 do {
409 if (cnode->level)
410 len = c->nnode_sz;
411 else
412 len = c->pnode_sz;
413 while (offs + len > c->leb_size) {
414 wlen = offs - from;
415 if (wlen) {
416 alen = ALIGN(wlen, c->min_io_size);
417 memset(buf + offs, 0xff, alen - wlen);
418 err = ubifs_leb_write(c, lnum, buf + from, from,
419 alen);
420 if (err)
421 return err;
422 }
423 dbg_chk_lpt_sz(c, 2, c->leb_size - offs);
424 err = realloc_lpt_leb(c, &lnum);
425 if (err)
426 goto no_space;
427 offs = from = 0;
428 ubifs_assert(lnum >= c->lpt_first &&
429 lnum <= c->lpt_last);
430 err = ubifs_leb_unmap(c, lnum);
431 if (err)
432 return err;
433
434 if (!done_lsave) {
435 done_lsave = 1;
436 ubifs_pack_lsave(c, buf + offs, c->lsave);
437 offs += c->lsave_sz;
438 dbg_chk_lpt_sz(c, 1, c->lsave_sz);
439 continue;
440 }
441 if (!done_ltab) {
442 done_ltab = 1;
443 ubifs_pack_ltab(c, buf + offs, c->ltab_cmt);
444 offs += c->ltab_sz;
445 dbg_chk_lpt_sz(c, 1, c->ltab_sz);
446 continue;
447 }
448 break;
449 }
450 if (cnode->level)
451 ubifs_pack_nnode(c, buf + offs,
452 (struct ubifs_nnode *)cnode);
453 else
454 ubifs_pack_pnode(c, buf + offs,
455 (struct ubifs_pnode *)cnode);
456
457
458
459
460
461
462 clear_bit(DIRTY_CNODE, &cnode->flags);
463 smp_mb__before_clear_bit();
464 clear_bit(COW_CNODE, &cnode->flags);
465 smp_mb__after_clear_bit();
466 offs += len;
467 dbg_chk_lpt_sz(c, 1, len);
468 cnode = cnode->cnext;
469 } while (cnode && cnode != c->lpt_cnext);
470
471
472 if (!done_lsave) {
473 if (offs + c->lsave_sz > c->leb_size) {
474 wlen = offs - from;
475 alen = ALIGN(wlen, c->min_io_size);
476 memset(buf + offs, 0xff, alen - wlen);
477 err = ubifs_leb_write(c, lnum, buf + from, from, alen);
478 if (err)
479 return err;
480 dbg_chk_lpt_sz(c, 2, c->leb_size - offs);
481 err = realloc_lpt_leb(c, &lnum);
482 if (err)
483 goto no_space;
484 offs = from = 0;
485 ubifs_assert(lnum >= c->lpt_first &&
486 lnum <= c->lpt_last);
487 err = ubifs_leb_unmap(c, lnum);
488 if (err)
489 return err;
490 }
491 done_lsave = 1;
492 ubifs_pack_lsave(c, buf + offs, c->lsave);
493 offs += c->lsave_sz;
494 dbg_chk_lpt_sz(c, 1, c->lsave_sz);
495 }
496
497
498 if (!done_ltab) {
499 if (offs + c->ltab_sz > c->leb_size) {
500 wlen = offs - from;
501 alen = ALIGN(wlen, c->min_io_size);
502 memset(buf + offs, 0xff, alen - wlen);
503 err = ubifs_leb_write(c, lnum, buf + from, from, alen);
504 if (err)
505 return err;
506 dbg_chk_lpt_sz(c, 2, c->leb_size - offs);
507 err = realloc_lpt_leb(c, &lnum);
508 if (err)
509 goto no_space;
510 offs = from = 0;
511 ubifs_assert(lnum >= c->lpt_first &&
512 lnum <= c->lpt_last);
513 err = ubifs_leb_unmap(c, lnum);
514 if (err)
515 return err;
516 }
517 done_ltab = 1;
518 ubifs_pack_ltab(c, buf + offs, c->ltab_cmt);
519 offs += c->ltab_sz;
520 dbg_chk_lpt_sz(c, 1, c->ltab_sz);
521 }
522
523
524 wlen = offs - from;
525 alen = ALIGN(wlen, c->min_io_size);
526 memset(buf + offs, 0xff, alen - wlen);
527 err = ubifs_leb_write(c, lnum, buf + from, from, alen);
528 if (err)
529 return err;
530
531 dbg_chk_lpt_sz(c, 4, alen - wlen);
532 err = dbg_chk_lpt_sz(c, 3, ALIGN(offs, c->min_io_size));
533 if (err)
534 return err;
535
536 c->nhead_lnum = lnum;
537 c->nhead_offs = ALIGN(offs, c->min_io_size);
538
539 dbg_lp("LPT root is at %d:%d", c->lpt_lnum, c->lpt_offs);
540 dbg_lp("LPT head is at %d:%d", c->nhead_lnum, c->nhead_offs);
541 dbg_lp("LPT ltab is at %d:%d", c->ltab_lnum, c->ltab_offs);
542 if (c->big_lpt)
543 dbg_lp("LPT lsave is at %d:%d", c->lsave_lnum, c->lsave_offs);
544
545 return 0;
546
547no_space:
548 ubifs_err("LPT out of space mismatch at LEB %d:%d needing %d, done_ltab "
549 "%d, done_lsave %d", lnum, offs, len, done_ltab, done_lsave);
550 ubifs_dump_lpt_info(c);
551 ubifs_dump_lpt_lebs(c);
552 dump_stack();
553 return err;
554}
555
556
557
558
559
560
561
562
563
564
565static struct ubifs_pnode *next_pnode_to_dirty(struct ubifs_info *c,
566 struct ubifs_pnode *pnode)
567{
568 struct ubifs_nnode *nnode;
569 int iip;
570
571
572 nnode = pnode->parent;
573 for (iip = pnode->iip + 1; iip < UBIFS_LPT_FANOUT; iip++) {
574 if (nnode->nbranch[iip].lnum)
575 return ubifs_get_pnode(c, nnode, iip);
576 }
577
578
579 do {
580 iip = nnode->iip + 1;
581 nnode = nnode->parent;
582 if (!nnode)
583 return NULL;
584 for (; iip < UBIFS_LPT_FANOUT; iip++) {
585 if (nnode->nbranch[iip].lnum)
586 break;
587 }
588 } while (iip >= UBIFS_LPT_FANOUT);
589
590
591 nnode = ubifs_get_nnode(c, nnode, iip);
592 if (IS_ERR(nnode))
593 return (void *)nnode;
594
595
596 while (nnode->level > 1) {
597 for (iip = 0; iip < UBIFS_LPT_FANOUT; iip++) {
598 if (nnode->nbranch[iip].lnum)
599 break;
600 }
601 if (iip >= UBIFS_LPT_FANOUT) {
602
603
604
605
606 iip = 0;
607 }
608 nnode = ubifs_get_nnode(c, nnode, iip);
609 if (IS_ERR(nnode))
610 return (void *)nnode;
611 }
612
613 for (iip = 0; iip < UBIFS_LPT_FANOUT; iip++)
614 if (nnode->nbranch[iip].lnum)
615 break;
616 if (iip >= UBIFS_LPT_FANOUT)
617
618 iip = 0;
619 return ubifs_get_pnode(c, nnode, iip);
620}
621
622
623
624
625
626
627
628
629
630static struct ubifs_pnode *pnode_lookup(struct ubifs_info *c, int i)
631{
632 int err, h, iip, shft;
633 struct ubifs_nnode *nnode;
634
635 if (!c->nroot) {
636 err = ubifs_read_nnode(c, NULL, 0);
637 if (err)
638 return ERR_PTR(err);
639 }
640 i <<= UBIFS_LPT_FANOUT_SHIFT;
641 nnode = c->nroot;
642 shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT;
643 for (h = 1; h < c->lpt_hght; h++) {
644 iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
645 shft -= UBIFS_LPT_FANOUT_SHIFT;
646 nnode = ubifs_get_nnode(c, nnode, iip);
647 if (IS_ERR(nnode))
648 return ERR_CAST(nnode);
649 }
650 iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
651 return ubifs_get_pnode(c, nnode, iip);
652}
653
654
655
656
657
658
659static void add_pnode_dirt(struct ubifs_info *c, struct ubifs_pnode *pnode)
660{
661 ubifs_add_lpt_dirt(c, pnode->parent->nbranch[pnode->iip].lnum,
662 c->pnode_sz);
663}
664
665
666
667
668
669
670static void do_make_pnode_dirty(struct ubifs_info *c, struct ubifs_pnode *pnode)
671{
672
673 if (!test_and_set_bit(DIRTY_CNODE, &pnode->flags)) {
674 struct ubifs_nnode *nnode;
675
676 c->dirty_pn_cnt += 1;
677 add_pnode_dirt(c, pnode);
678
679 nnode = pnode->parent;
680 while (nnode) {
681 if (!test_and_set_bit(DIRTY_CNODE, &nnode->flags)) {
682 c->dirty_nn_cnt += 1;
683 ubifs_add_nnode_dirt(c, nnode);
684 nnode = nnode->parent;
685 } else
686 break;
687 }
688 }
689}
690
691
692
693
694
695
696
697
698
699
700
701
702static int make_tree_dirty(struct ubifs_info *c)
703{
704 struct ubifs_pnode *pnode;
705
706 pnode = pnode_lookup(c, 0);
707 if (IS_ERR(pnode))
708 return PTR_ERR(pnode);
709
710 while (pnode) {
711 do_make_pnode_dirty(c, pnode);
712 pnode = next_pnode_to_dirty(c, pnode);
713 if (IS_ERR(pnode))
714 return PTR_ERR(pnode);
715 }
716 return 0;
717}
718
719
720
721
722
723
724
725
726static int need_write_all(struct ubifs_info *c)
727{
728 long long free = 0;
729 int i;
730
731 for (i = 0; i < c->lpt_lebs; i++) {
732 if (i + c->lpt_first == c->nhead_lnum)
733 free += c->leb_size - c->nhead_offs;
734 else if (c->ltab[i].free == c->leb_size)
735 free += c->leb_size;
736 else if (c->ltab[i].free + c->ltab[i].dirty == c->leb_size)
737 free += c->leb_size;
738 }
739
740 if (free <= c->lpt_sz * 2)
741 return 1;
742 return 0;
743}
744
745
746
747
748
749
750
751
752
753static void lpt_tgc_start(struct ubifs_info *c)
754{
755 int i;
756
757 for (i = 0; i < c->lpt_lebs; i++) {
758 if (i + c->lpt_first == c->nhead_lnum)
759 continue;
760 if (c->ltab[i].dirty > 0 &&
761 c->ltab[i].free + c->ltab[i].dirty == c->leb_size) {
762 c->ltab[i].tgc = 1;
763 c->ltab[i].free = c->leb_size;
764 c->ltab[i].dirty = 0;
765 dbg_lp("LEB %d", i + c->lpt_first);
766 }
767 }
768}
769
770
771
772
773
774
775
776
777
778
779static int lpt_tgc_end(struct ubifs_info *c)
780{
781 int i, err;
782
783 for (i = 0; i < c->lpt_lebs; i++)
784 if (c->ltab[i].tgc) {
785 err = ubifs_leb_unmap(c, i + c->lpt_first);
786 if (err)
787 return err;
788 c->ltab[i].tgc = 0;
789 dbg_lp("LEB %d", i + c->lpt_first);
790 }
791 return 0;
792}
793
794
795
796
797
798
799
800
801
802
803
804
805
806static void populate_lsave(struct ubifs_info *c)
807{
808 struct ubifs_lprops *lprops;
809 struct ubifs_lpt_heap *heap;
810 int i, cnt = 0;
811
812 ubifs_assert(c->big_lpt);
813 if (!(c->lpt_drty_flgs & LSAVE_DIRTY)) {
814 c->lpt_drty_flgs |= LSAVE_DIRTY;
815 ubifs_add_lpt_dirt(c, c->lsave_lnum, c->lsave_sz);
816 }
817
818 if (dbg_populate_lsave(c))
819 return;
820
821 list_for_each_entry(lprops, &c->empty_list, list) {
822 c->lsave[cnt++] = lprops->lnum;
823 if (cnt >= c->lsave_cnt)
824 return;
825 }
826 list_for_each_entry(lprops, &c->freeable_list, list) {
827 c->lsave[cnt++] = lprops->lnum;
828 if (cnt >= c->lsave_cnt)
829 return;
830 }
831 list_for_each_entry(lprops, &c->frdi_idx_list, list) {
832 c->lsave[cnt++] = lprops->lnum;
833 if (cnt >= c->lsave_cnt)
834 return;
835 }
836 heap = &c->lpt_heap[LPROPS_DIRTY_IDX - 1];
837 for (i = 0; i < heap->cnt; i++) {
838 c->lsave[cnt++] = heap->arr[i]->lnum;
839 if (cnt >= c->lsave_cnt)
840 return;
841 }
842 heap = &c->lpt_heap[LPROPS_DIRTY - 1];
843 for (i = 0; i < heap->cnt; i++) {
844 c->lsave[cnt++] = heap->arr[i]->lnum;
845 if (cnt >= c->lsave_cnt)
846 return;
847 }
848 heap = &c->lpt_heap[LPROPS_FREE - 1];
849 for (i = 0; i < heap->cnt; i++) {
850 c->lsave[cnt++] = heap->arr[i]->lnum;
851 if (cnt >= c->lsave_cnt)
852 return;
853 }
854
855 while (cnt < c->lsave_cnt)
856 c->lsave[cnt++] = c->main_first;
857}
858
859
860
861
862
863
864
865
866
867static struct ubifs_nnode *nnode_lookup(struct ubifs_info *c, int i)
868{
869 int err, iip;
870 struct ubifs_nnode *nnode;
871
872 if (!c->nroot) {
873 err = ubifs_read_nnode(c, NULL, 0);
874 if (err)
875 return ERR_PTR(err);
876 }
877 nnode = c->nroot;
878 while (1) {
879 iip = i & (UBIFS_LPT_FANOUT - 1);
880 i >>= UBIFS_LPT_FANOUT_SHIFT;
881 if (!i)
882 break;
883 nnode = ubifs_get_nnode(c, nnode, iip);
884 if (IS_ERR(nnode))
885 return nnode;
886 }
887 return nnode;
888}
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905static int make_nnode_dirty(struct ubifs_info *c, int node_num, int lnum,
906 int offs)
907{
908 struct ubifs_nnode *nnode;
909
910 nnode = nnode_lookup(c, node_num);
911 if (IS_ERR(nnode))
912 return PTR_ERR(nnode);
913 if (nnode->parent) {
914 struct ubifs_nbranch *branch;
915
916 branch = &nnode->parent->nbranch[nnode->iip];
917 if (branch->lnum != lnum || branch->offs != offs)
918 return 0;
919 } else if (c->lpt_lnum != lnum || c->lpt_offs != offs)
920 return 0;
921
922 if (!test_and_set_bit(DIRTY_CNODE, &nnode->flags)) {
923 c->dirty_nn_cnt += 1;
924 ubifs_add_nnode_dirt(c, nnode);
925
926 nnode = nnode->parent;
927 while (nnode) {
928 if (!test_and_set_bit(DIRTY_CNODE, &nnode->flags)) {
929 c->dirty_nn_cnt += 1;
930 ubifs_add_nnode_dirt(c, nnode);
931 nnode = nnode->parent;
932 } else
933 break;
934 }
935 }
936 return 0;
937}
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954static int make_pnode_dirty(struct ubifs_info *c, int node_num, int lnum,
955 int offs)
956{
957 struct ubifs_pnode *pnode;
958 struct ubifs_nbranch *branch;
959
960 pnode = pnode_lookup(c, node_num);
961 if (IS_ERR(pnode))
962 return PTR_ERR(pnode);
963 branch = &pnode->parent->nbranch[pnode->iip];
964 if (branch->lnum != lnum || branch->offs != offs)
965 return 0;
966 do_make_pnode_dirty(c, pnode);
967 return 0;
968}
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984static int make_ltab_dirty(struct ubifs_info *c, int lnum, int offs)
985{
986 if (lnum != c->ltab_lnum || offs != c->ltab_offs)
987 return 0;
988 if (!(c->lpt_drty_flgs & LTAB_DIRTY)) {
989 c->lpt_drty_flgs |= LTAB_DIRTY;
990 ubifs_add_lpt_dirt(c, c->ltab_lnum, c->ltab_sz);
991 }
992 return 0;
993}
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009static int make_lsave_dirty(struct ubifs_info *c, int lnum, int offs)
1010{
1011 if (lnum != c->lsave_lnum || offs != c->lsave_offs)
1012 return 0;
1013 if (!(c->lpt_drty_flgs & LSAVE_DIRTY)) {
1014 c->lpt_drty_flgs |= LSAVE_DIRTY;
1015 ubifs_add_lpt_dirt(c, c->lsave_lnum, c->lsave_sz);
1016 }
1017 return 0;
1018}
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036static int make_node_dirty(struct ubifs_info *c, int node_type, int node_num,
1037 int lnum, int offs)
1038{
1039 switch (node_type) {
1040 case UBIFS_LPT_NNODE:
1041 return make_nnode_dirty(c, node_num, lnum, offs);
1042 case UBIFS_LPT_PNODE:
1043 return make_pnode_dirty(c, node_num, lnum, offs);
1044 case UBIFS_LPT_LTAB:
1045 return make_ltab_dirty(c, lnum, offs);
1046 case UBIFS_LPT_LSAVE:
1047 return make_lsave_dirty(c, lnum, offs);
1048 }
1049 return -EINVAL;
1050}
1051
1052
1053
1054
1055
1056
1057static int get_lpt_node_len(const struct ubifs_info *c, int node_type)
1058{
1059 switch (node_type) {
1060 case UBIFS_LPT_NNODE:
1061 return c->nnode_sz;
1062 case UBIFS_LPT_PNODE:
1063 return c->pnode_sz;
1064 case UBIFS_LPT_LTAB:
1065 return c->ltab_sz;
1066 case UBIFS_LPT_LSAVE:
1067 return c->lsave_sz;
1068 }
1069 return 0;
1070}
1071
1072
1073
1074
1075
1076
1077
1078static int get_pad_len(const struct ubifs_info *c, uint8_t *buf, int len)
1079{
1080 int offs, pad_len;
1081
1082 if (c->min_io_size == 1)
1083 return 0;
1084 offs = c->leb_size - len;
1085 pad_len = ALIGN(offs, c->min_io_size) - offs;
1086 return pad_len;
1087}
1088
1089
1090
1091
1092
1093
1094
1095static int get_lpt_node_type(const struct ubifs_info *c, uint8_t *buf,
1096 int *node_num)
1097{
1098 uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
1099 int pos = 0, node_type;
1100
1101 node_type = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_TYPE_BITS);
1102 *node_num = ubifs_unpack_bits(&addr, &pos, c->pcnt_bits);
1103 return node_type;
1104}
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114static int is_a_node(const struct ubifs_info *c, uint8_t *buf, int len)
1115{
1116 uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
1117 int pos = 0, node_type, node_len;
1118 uint16_t crc, calc_crc;
1119
1120 if (len < UBIFS_LPT_CRC_BYTES + (UBIFS_LPT_TYPE_BITS + 7) / 8)
1121 return 0;
1122 node_type = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_TYPE_BITS);
1123 if (node_type == UBIFS_LPT_NOT_A_NODE)
1124 return 0;
1125 node_len = get_lpt_node_len(c, node_type);
1126 if (!node_len || node_len > len)
1127 return 0;
1128 pos = 0;
1129 addr = buf;
1130 crc = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_CRC_BITS);
1131 calc_crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
1132 node_len - UBIFS_LPT_CRC_BYTES);
1133 if (crc != calc_crc)
1134 return 0;
1135 return 1;
1136}
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150static int lpt_gc_lnum(struct ubifs_info *c, int lnum)
1151{
1152 int err, len = c->leb_size, node_type, node_num, node_len, offs;
1153 void *buf = c->lpt_buf;
1154
1155 dbg_lp("LEB %d", lnum);
1156
1157 err = ubifs_leb_read(c, lnum, buf, 0, c->leb_size, 1);
1158 if (err)
1159 return err;
1160
1161 while (1) {
1162 if (!is_a_node(c, buf, len)) {
1163 int pad_len;
1164
1165 pad_len = get_pad_len(c, buf, len);
1166 if (pad_len) {
1167 buf += pad_len;
1168 len -= pad_len;
1169 continue;
1170 }
1171 return 0;
1172 }
1173 node_type = get_lpt_node_type(c, buf, &node_num);
1174 node_len = get_lpt_node_len(c, node_type);
1175 offs = c->leb_size - len;
1176 ubifs_assert(node_len != 0);
1177 mutex_lock(&c->lp_mutex);
1178 err = make_node_dirty(c, node_type, node_num, lnum, offs);
1179 mutex_unlock(&c->lp_mutex);
1180 if (err)
1181 return err;
1182 buf += node_len;
1183 len -= node_len;
1184 }
1185 return 0;
1186}
1187
1188
1189
1190
1191
1192
1193
1194
1195static int lpt_gc(struct ubifs_info *c)
1196{
1197 int i, lnum = -1, dirty = 0;
1198
1199 mutex_lock(&c->lp_mutex);
1200 for (i = 0; i < c->lpt_lebs; i++) {
1201 ubifs_assert(!c->ltab[i].tgc);
1202 if (i + c->lpt_first == c->nhead_lnum ||
1203 c->ltab[i].free + c->ltab[i].dirty == c->leb_size)
1204 continue;
1205 if (c->ltab[i].dirty > dirty) {
1206 dirty = c->ltab[i].dirty;
1207 lnum = i + c->lpt_first;
1208 }
1209 }
1210 mutex_unlock(&c->lp_mutex);
1211 if (lnum == -1)
1212 return -ENOSPC;
1213 return lpt_gc_lnum(c, lnum);
1214}
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226int ubifs_lpt_start_commit(struct ubifs_info *c)
1227{
1228 int err, cnt;
1229
1230 dbg_lp("");
1231
1232 mutex_lock(&c->lp_mutex);
1233 err = dbg_chk_lpt_free_spc(c);
1234 if (err)
1235 goto out;
1236 err = dbg_check_ltab(c);
1237 if (err)
1238 goto out;
1239
1240 if (c->check_lpt_free) {
1241
1242
1243
1244
1245
1246
1247 c->check_lpt_free = 0;
1248 while (need_write_all(c)) {
1249 mutex_unlock(&c->lp_mutex);
1250 err = lpt_gc(c);
1251 if (err)
1252 return err;
1253 mutex_lock(&c->lp_mutex);
1254 }
1255 }
1256
1257 lpt_tgc_start(c);
1258
1259 if (!c->dirty_pn_cnt) {
1260 dbg_cmt("no cnodes to commit");
1261 err = 0;
1262 goto out;
1263 }
1264
1265 if (!c->big_lpt && need_write_all(c)) {
1266
1267 err = make_tree_dirty(c);
1268 if (err)
1269 goto out;
1270 lpt_tgc_start(c);
1271 }
1272
1273 if (c->big_lpt)
1274 populate_lsave(c);
1275
1276 cnt = get_cnodes_to_commit(c);
1277 ubifs_assert(cnt != 0);
1278
1279 err = layout_cnodes(c);
1280 if (err)
1281 goto out;
1282
1283
1284 memcpy(c->ltab_cmt, c->ltab,
1285 sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs);
1286 c->lpt_drty_flgs &= ~(LTAB_DIRTY | LSAVE_DIRTY);
1287
1288out:
1289 mutex_unlock(&c->lp_mutex);
1290 return err;
1291}
1292
1293
1294
1295
1296
1297static void free_obsolete_cnodes(struct ubifs_info *c)
1298{
1299 struct ubifs_cnode *cnode, *cnext;
1300
1301 cnext = c->lpt_cnext;
1302 if (!cnext)
1303 return;
1304 do {
1305 cnode = cnext;
1306 cnext = cnode->cnext;
1307 if (test_bit(OBSOLETE_CNODE, &cnode->flags))
1308 kfree(cnode);
1309 else
1310 cnode->cnext = NULL;
1311 } while (cnext != c->lpt_cnext);
1312 c->lpt_cnext = NULL;
1313}
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324int ubifs_lpt_end_commit(struct ubifs_info *c)
1325{
1326 int err;
1327
1328 dbg_lp("");
1329
1330 if (!c->lpt_cnext)
1331 return 0;
1332
1333 err = write_cnodes(c);
1334 if (err)
1335 return err;
1336
1337 mutex_lock(&c->lp_mutex);
1338 free_obsolete_cnodes(c);
1339 mutex_unlock(&c->lp_mutex);
1340
1341 return 0;
1342}
1343
1344
1345
1346
1347
1348
1349
1350
1351int ubifs_lpt_post_commit(struct ubifs_info *c)
1352{
1353 int err;
1354
1355 mutex_lock(&c->lp_mutex);
1356 err = lpt_tgc_end(c);
1357 if (err)
1358 goto out;
1359 if (c->big_lpt)
1360 while (need_write_all(c)) {
1361 mutex_unlock(&c->lp_mutex);
1362 err = lpt_gc(c);
1363 if (err)
1364 return err;
1365 mutex_lock(&c->lp_mutex);
1366 }
1367out:
1368 mutex_unlock(&c->lp_mutex);
1369 return err;
1370}
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380static struct ubifs_nnode *first_nnode(struct ubifs_info *c, int *hght)
1381{
1382 struct ubifs_nnode *nnode;
1383 int h, i, found;
1384
1385 nnode = c->nroot;
1386 *hght = 0;
1387 if (!nnode)
1388 return NULL;
1389 for (h = 1; h < c->lpt_hght; h++) {
1390 found = 0;
1391 for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
1392 if (nnode->nbranch[i].nnode) {
1393 found = 1;
1394 nnode = nnode->nbranch[i].nnode;
1395 *hght = h;
1396 break;
1397 }
1398 }
1399 if (!found)
1400 break;
1401 }
1402 return nnode;
1403}
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414static struct ubifs_nnode *next_nnode(struct ubifs_info *c,
1415 struct ubifs_nnode *nnode, int *hght)
1416{
1417 struct ubifs_nnode *parent;
1418 int iip, h, i, found;
1419
1420 parent = nnode->parent;
1421 if (!parent)
1422 return NULL;
1423 if (nnode->iip == UBIFS_LPT_FANOUT - 1) {
1424 *hght -= 1;
1425 return parent;
1426 }
1427 for (iip = nnode->iip + 1; iip < UBIFS_LPT_FANOUT; iip++) {
1428 nnode = parent->nbranch[iip].nnode;
1429 if (nnode)
1430 break;
1431 }
1432 if (!nnode) {
1433 *hght -= 1;
1434 return parent;
1435 }
1436 for (h = *hght + 1; h < c->lpt_hght; h++) {
1437 found = 0;
1438 for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
1439 if (nnode->nbranch[i].nnode) {
1440 found = 1;
1441 nnode = nnode->nbranch[i].nnode;
1442 *hght = h;
1443 break;
1444 }
1445 }
1446 if (!found)
1447 break;
1448 }
1449 return nnode;
1450}
1451
1452
1453
1454
1455
1456
1457void ubifs_lpt_free(struct ubifs_info *c, int wr_only)
1458{
1459 struct ubifs_nnode *nnode;
1460 int i, hght;
1461
1462
1463
1464 free_obsolete_cnodes(c);
1465
1466 vfree(c->ltab_cmt);
1467 c->ltab_cmt = NULL;
1468 vfree(c->lpt_buf);
1469 c->lpt_buf = NULL;
1470 kfree(c->lsave);
1471 c->lsave = NULL;
1472
1473 if (wr_only)
1474 return;
1475
1476
1477
1478 nnode = first_nnode(c, &hght);
1479 while (nnode) {
1480 for (i = 0; i < UBIFS_LPT_FANOUT; i++)
1481 kfree(nnode->nbranch[i].nnode);
1482 nnode = next_nnode(c, nnode, &hght);
1483 }
1484 for (i = 0; i < LPROPS_HEAP_CNT; i++)
1485 kfree(c->lpt_heap[i].arr);
1486 kfree(c->dirty_idx.arr);
1487 kfree(c->nroot);
1488 vfree(c->ltab);
1489 kfree(c->lpt_nod_buf);
1490}
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501static int dbg_is_all_ff(uint8_t *buf, int len)
1502{
1503 int i;
1504
1505 for (i = 0; i < len; i++)
1506 if (buf[i] != 0xff)
1507 return 0;
1508 return 1;
1509}
1510
1511
1512
1513
1514
1515
1516
1517static int dbg_is_nnode_dirty(struct ubifs_info *c, int lnum, int offs)
1518{
1519 struct ubifs_nnode *nnode;
1520 int hght;
1521
1522
1523 nnode = first_nnode(c, &hght);
1524 for (; nnode; nnode = next_nnode(c, nnode, &hght)) {
1525 struct ubifs_nbranch *branch;
1526
1527 cond_resched();
1528 if (nnode->parent) {
1529 branch = &nnode->parent->nbranch[nnode->iip];
1530 if (branch->lnum != lnum || branch->offs != offs)
1531 continue;
1532 if (test_bit(DIRTY_CNODE, &nnode->flags))
1533 return 1;
1534 return 0;
1535 } else {
1536 if (c->lpt_lnum != lnum || c->lpt_offs != offs)
1537 continue;
1538 if (test_bit(DIRTY_CNODE, &nnode->flags))
1539 return 1;
1540 return 0;
1541 }
1542 }
1543 return 1;
1544}
1545
1546
1547
1548
1549
1550
1551
1552static int dbg_is_pnode_dirty(struct ubifs_info *c, int lnum, int offs)
1553{
1554 int i, cnt;
1555
1556 cnt = DIV_ROUND_UP(c->main_lebs, UBIFS_LPT_FANOUT);
1557 for (i = 0; i < cnt; i++) {
1558 struct ubifs_pnode *pnode;
1559 struct ubifs_nbranch *branch;
1560
1561 cond_resched();
1562 pnode = pnode_lookup(c, i);
1563 if (IS_ERR(pnode))
1564 return PTR_ERR(pnode);
1565 branch = &pnode->parent->nbranch[pnode->iip];
1566 if (branch->lnum != lnum || branch->offs != offs)
1567 continue;
1568 if (test_bit(DIRTY_CNODE, &pnode->flags))
1569 return 1;
1570 return 0;
1571 }
1572 return 1;
1573}
1574
1575
1576
1577
1578
1579
1580
1581static int dbg_is_ltab_dirty(struct ubifs_info *c, int lnum, int offs)
1582{
1583 if (lnum != c->ltab_lnum || offs != c->ltab_offs)
1584 return 1;
1585 return (c->lpt_drty_flgs & LTAB_DIRTY) != 0;
1586}
1587
1588
1589
1590
1591
1592
1593
1594static int dbg_is_lsave_dirty(struct ubifs_info *c, int lnum, int offs)
1595{
1596 if (lnum != c->lsave_lnum || offs != c->lsave_offs)
1597 return 1;
1598 return (c->lpt_drty_flgs & LSAVE_DIRTY) != 0;
1599}
1600
1601
1602
1603
1604
1605
1606
1607
1608static int dbg_is_node_dirty(struct ubifs_info *c, int node_type, int lnum,
1609 int offs)
1610{
1611 switch (node_type) {
1612 case UBIFS_LPT_NNODE:
1613 return dbg_is_nnode_dirty(c, lnum, offs);
1614 case UBIFS_LPT_PNODE:
1615 return dbg_is_pnode_dirty(c, lnum, offs);
1616 case UBIFS_LPT_LTAB:
1617 return dbg_is_ltab_dirty(c, lnum, offs);
1618 case UBIFS_LPT_LSAVE:
1619 return dbg_is_lsave_dirty(c, lnum, offs);
1620 }
1621 return 1;
1622}
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum)
1633{
1634 int err, len = c->leb_size, dirty = 0, node_type, node_num, node_len;
1635 int ret;
1636 void *buf, *p;
1637
1638 if (!dbg_is_chk_lprops(c))
1639 return 0;
1640
1641 buf = p = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL);
1642 if (!buf) {
1643 ubifs_err("cannot allocate memory for ltab checking");
1644 return 0;
1645 }
1646
1647 dbg_lp("LEB %d", lnum);
1648
1649 err = ubifs_leb_read(c, lnum, buf, 0, c->leb_size, 1);
1650 if (err)
1651 goto out;
1652
1653 while (1) {
1654 if (!is_a_node(c, p, len)) {
1655 int i, pad_len;
1656
1657 pad_len = get_pad_len(c, p, len);
1658 if (pad_len) {
1659 p += pad_len;
1660 len -= pad_len;
1661 dirty += pad_len;
1662 continue;
1663 }
1664 if (!dbg_is_all_ff(p, len)) {
1665 dbg_msg("invalid empty space in LEB %d at %d",
1666 lnum, c->leb_size - len);
1667 err = -EINVAL;
1668 }
1669 i = lnum - c->lpt_first;
1670 if (len != c->ltab[i].free) {
1671 dbg_msg("invalid free space in LEB %d "
1672 "(free %d, expected %d)",
1673 lnum, len, c->ltab[i].free);
1674 err = -EINVAL;
1675 }
1676 if (dirty != c->ltab[i].dirty) {
1677 dbg_msg("invalid dirty space in LEB %d "
1678 "(dirty %d, expected %d)",
1679 lnum, dirty, c->ltab[i].dirty);
1680 err = -EINVAL;
1681 }
1682 goto out;
1683 }
1684 node_type = get_lpt_node_type(c, p, &node_num);
1685 node_len = get_lpt_node_len(c, node_type);
1686 ret = dbg_is_node_dirty(c, node_type, lnum, c->leb_size - len);
1687 if (ret == 1)
1688 dirty += node_len;
1689 p += node_len;
1690 len -= node_len;
1691 }
1692
1693 err = 0;
1694out:
1695 vfree(buf);
1696 return err;
1697}
1698
1699
1700
1701
1702
1703
1704
1705int dbg_check_ltab(struct ubifs_info *c)
1706{
1707 int lnum, err, i, cnt;
1708
1709 if (!dbg_is_chk_lprops(c))
1710 return 0;
1711
1712
1713 cnt = DIV_ROUND_UP(c->main_lebs, UBIFS_LPT_FANOUT);
1714 for (i = 0; i < cnt; i++) {
1715 struct ubifs_pnode *pnode;
1716
1717 pnode = pnode_lookup(c, i);
1718 if (IS_ERR(pnode))
1719 return PTR_ERR(pnode);
1720 cond_resched();
1721 }
1722
1723
1724 err = dbg_check_lpt_nodes(c, (struct ubifs_cnode *)c->nroot, 0, 0);
1725 if (err)
1726 return err;
1727
1728
1729 for (lnum = c->lpt_first; lnum <= c->lpt_last; lnum++) {
1730 err = dbg_check_ltab_lnum(c, lnum);
1731 if (err) {
1732 ubifs_err("failed at LEB %d", lnum);
1733 return err;
1734 }
1735 }
1736
1737 dbg_lp("succeeded");
1738 return 0;
1739}
1740
1741
1742
1743
1744
1745
1746
1747int dbg_chk_lpt_free_spc(struct ubifs_info *c)
1748{
1749 long long free = 0;
1750 int i;
1751
1752 if (!dbg_is_chk_lprops(c))
1753 return 0;
1754
1755 for (i = 0; i < c->lpt_lebs; i++) {
1756 if (c->ltab[i].tgc || c->ltab[i].cmt)
1757 continue;
1758 if (i + c->lpt_first == c->nhead_lnum)
1759 free += c->leb_size - c->nhead_offs;
1760 else if (c->ltab[i].free == c->leb_size)
1761 free += c->leb_size;
1762 }
1763 if (free < c->lpt_sz) {
1764 ubifs_err("LPT space error: free %lld lpt_sz %lld",
1765 free, c->lpt_sz);
1766 ubifs_dump_lpt_info(c);
1767 ubifs_dump_lpt_lebs(c);
1768 dump_stack();
1769 return -EINVAL;
1770 }
1771 return 0;
1772}
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len)
1789{
1790 struct ubifs_debug_info *d = c->dbg;
1791 long long chk_lpt_sz, lpt_sz;
1792 int err = 0;
1793
1794 if (!dbg_is_chk_lprops(c))
1795 return 0;
1796
1797 switch (action) {
1798 case 0:
1799 d->chk_lpt_sz = 0;
1800 d->chk_lpt_sz2 = 0;
1801 d->chk_lpt_lebs = 0;
1802 d->chk_lpt_wastage = 0;
1803 if (c->dirty_pn_cnt > c->pnode_cnt) {
1804 ubifs_err("dirty pnodes %d exceed max %d",
1805 c->dirty_pn_cnt, c->pnode_cnt);
1806 err = -EINVAL;
1807 }
1808 if (c->dirty_nn_cnt > c->nnode_cnt) {
1809 ubifs_err("dirty nnodes %d exceed max %d",
1810 c->dirty_nn_cnt, c->nnode_cnt);
1811 err = -EINVAL;
1812 }
1813 return err;
1814 case 1:
1815 d->chk_lpt_sz += len;
1816 return 0;
1817 case 2:
1818 d->chk_lpt_sz += len;
1819 d->chk_lpt_wastage += len;
1820 d->chk_lpt_lebs += 1;
1821 return 0;
1822 case 3:
1823 chk_lpt_sz = c->leb_size;
1824 chk_lpt_sz *= d->chk_lpt_lebs;
1825 chk_lpt_sz += len - c->nhead_offs;
1826 if (d->chk_lpt_sz != chk_lpt_sz) {
1827 ubifs_err("LPT wrote %lld but space used was %lld",
1828 d->chk_lpt_sz, chk_lpt_sz);
1829 err = -EINVAL;
1830 }
1831 if (d->chk_lpt_sz > c->lpt_sz) {
1832 ubifs_err("LPT wrote %lld but lpt_sz is %lld",
1833 d->chk_lpt_sz, c->lpt_sz);
1834 err = -EINVAL;
1835 }
1836 if (d->chk_lpt_sz2 && d->chk_lpt_sz != d->chk_lpt_sz2) {
1837 ubifs_err("LPT layout size %lld but wrote %lld",
1838 d->chk_lpt_sz, d->chk_lpt_sz2);
1839 err = -EINVAL;
1840 }
1841 if (d->chk_lpt_sz2 && d->new_nhead_offs != len) {
1842 ubifs_err("LPT new nhead offs: expected %d was %d",
1843 d->new_nhead_offs, len);
1844 err = -EINVAL;
1845 }
1846 lpt_sz = (long long)c->pnode_cnt * c->pnode_sz;
1847 lpt_sz += (long long)c->nnode_cnt * c->nnode_sz;
1848 lpt_sz += c->ltab_sz;
1849 if (c->big_lpt)
1850 lpt_sz += c->lsave_sz;
1851 if (d->chk_lpt_sz - d->chk_lpt_wastage > lpt_sz) {
1852 ubifs_err("LPT chk_lpt_sz %lld + waste %lld exceeds %lld",
1853 d->chk_lpt_sz, d->chk_lpt_wastage, lpt_sz);
1854 err = -EINVAL;
1855 }
1856 if (err) {
1857 ubifs_dump_lpt_info(c);
1858 ubifs_dump_lpt_lebs(c);
1859 dump_stack();
1860 }
1861 d->chk_lpt_sz2 = d->chk_lpt_sz;
1862 d->chk_lpt_sz = 0;
1863 d->chk_lpt_wastage = 0;
1864 d->chk_lpt_lebs = 0;
1865 d->new_nhead_offs = len;
1866 return err;
1867 case 4:
1868 d->chk_lpt_sz += len;
1869 d->chk_lpt_wastage += len;
1870 return 0;
1871 default:
1872 return -EINVAL;
1873 }
1874}
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886static void dump_lpt_leb(const struct ubifs_info *c, int lnum)
1887{
1888 int err, len = c->leb_size, node_type, node_num, node_len, offs;
1889 void *buf, *p;
1890
1891 printk(KERN_DEBUG "(pid %d) start dumping LEB %d\n",
1892 current->pid, lnum);
1893 buf = p = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL);
1894 if (!buf) {
1895 ubifs_err("cannot allocate memory to dump LPT");
1896 return;
1897 }
1898
1899 err = ubifs_leb_read(c, lnum, buf, 0, c->leb_size, 1);
1900 if (err)
1901 goto out;
1902
1903 while (1) {
1904 offs = c->leb_size - len;
1905 if (!is_a_node(c, p, len)) {
1906 int pad_len;
1907
1908 pad_len = get_pad_len(c, p, len);
1909 if (pad_len) {
1910 printk(KERN_DEBUG "LEB %d:%d, pad %d bytes\n",
1911 lnum, offs, pad_len);
1912 p += pad_len;
1913 len -= pad_len;
1914 continue;
1915 }
1916 if (len)
1917 printk(KERN_DEBUG "LEB %d:%d, free %d bytes\n",
1918 lnum, offs, len);
1919 break;
1920 }
1921
1922 node_type = get_lpt_node_type(c, p, &node_num);
1923 switch (node_type) {
1924 case UBIFS_LPT_PNODE:
1925 {
1926 node_len = c->pnode_sz;
1927 if (c->big_lpt)
1928 printk(KERN_DEBUG "LEB %d:%d, pnode num %d\n",
1929 lnum, offs, node_num);
1930 else
1931 printk(KERN_DEBUG "LEB %d:%d, pnode\n",
1932 lnum, offs);
1933 break;
1934 }
1935 case UBIFS_LPT_NNODE:
1936 {
1937 int i;
1938 struct ubifs_nnode nnode;
1939
1940 node_len = c->nnode_sz;
1941 if (c->big_lpt)
1942 printk(KERN_DEBUG "LEB %d:%d, nnode num %d, ",
1943 lnum, offs, node_num);
1944 else
1945 printk(KERN_DEBUG "LEB %d:%d, nnode, ",
1946 lnum, offs);
1947 err = ubifs_unpack_nnode(c, p, &nnode);
1948 for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
1949 printk(KERN_CONT "%d:%d", nnode.nbranch[i].lnum,
1950 nnode.nbranch[i].offs);
1951 if (i != UBIFS_LPT_FANOUT - 1)
1952 printk(KERN_CONT ", ");
1953 }
1954 printk(KERN_CONT "\n");
1955 break;
1956 }
1957 case UBIFS_LPT_LTAB:
1958 node_len = c->ltab_sz;
1959 printk(KERN_DEBUG "LEB %d:%d, ltab\n",
1960 lnum, offs);
1961 break;
1962 case UBIFS_LPT_LSAVE:
1963 node_len = c->lsave_sz;
1964 printk(KERN_DEBUG "LEB %d:%d, lsave len\n", lnum, offs);
1965 break;
1966 default:
1967 ubifs_err("LPT node type %d not recognized", node_type);
1968 goto out;
1969 }
1970
1971 p += node_len;
1972 len -= node_len;
1973 }
1974
1975 printk(KERN_DEBUG "(pid %d) finish dumping LEB %d\n",
1976 current->pid, lnum);
1977out:
1978 vfree(buf);
1979 return;
1980}
1981
1982
1983
1984
1985
1986
1987
1988
1989void ubifs_dump_lpt_lebs(const struct ubifs_info *c)
1990{
1991 int i;
1992
1993 printk(KERN_DEBUG "(pid %d) start dumping all LPT LEBs\n",
1994 current->pid);
1995 for (i = 0; i < c->lpt_lebs; i++)
1996 dump_lpt_leb(c, i + c->lpt_first);
1997 printk(KERN_DEBUG "(pid %d) finish dumping all LPT LEBs\n",
1998 current->pid);
1999}
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010static int dbg_populate_lsave(struct ubifs_info *c)
2011{
2012 struct ubifs_lprops *lprops;
2013 struct ubifs_lpt_heap *heap;
2014 int i;
2015
2016 if (!dbg_is_chk_gen(c))
2017 return 0;
2018 if (random32() & 3)
2019 return 0;
2020
2021 for (i = 0; i < c->lsave_cnt; i++)
2022 c->lsave[i] = c->main_first;
2023
2024 list_for_each_entry(lprops, &c->empty_list, list)
2025 c->lsave[random32() % c->lsave_cnt] = lprops->lnum;
2026 list_for_each_entry(lprops, &c->freeable_list, list)
2027 c->lsave[random32() % c->lsave_cnt] = lprops->lnum;
2028 list_for_each_entry(lprops, &c->frdi_idx_list, list)
2029 c->lsave[random32() % c->lsave_cnt] = lprops->lnum;
2030
2031 heap = &c->lpt_heap[LPROPS_DIRTY_IDX - 1];
2032 for (i = 0; i < heap->cnt; i++)
2033 c->lsave[random32() % c->lsave_cnt] = heap->arr[i]->lnum;
2034 heap = &c->lpt_heap[LPROPS_DIRTY - 1];
2035 for (i = 0; i < heap->cnt; i++)
2036 c->lsave[random32() % c->lsave_cnt] = heap->arr[i]->lnum;
2037 heap = &c->lpt_heap[LPROPS_FREE - 1];
2038 for (i = 0; i < heap->cnt; i++)
2039 c->lsave[random32() % c->lsave_cnt] = heap->arr[i]->lnum;
2040
2041 return 1;
2042}
2043