1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#ifdef __UBOOT__
24#include <log.h>
25#include <dm/devres.h>
26#include <linux/compat.h>
27#include <linux/err.h>
28#endif
29#include "ubifs.h"
30#include <linux/bug.h>
31#include <linux/list_sort.h>
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50struct replay_entry {
51 int lnum;
52 int offs;
53 int len;
54 unsigned int deletion:1;
55 unsigned long long sqnum;
56 struct list_head list;
57 union ubifs_key key;
58 union {
59 struct qstr nm;
60 struct {
61 loff_t old_size;
62 loff_t new_size;
63 };
64 };
65};
66
67
68
69
70
71
72
73
74
75struct bud_entry {
76 struct list_head list;
77 struct ubifs_bud *bud;
78 unsigned long long sqnum;
79 int free;
80 int dirty;
81};
82
83
84
85
86
87
88
89
90
91
92static int set_bud_lprops(struct ubifs_info *c, struct bud_entry *b)
93{
94 const struct ubifs_lprops *lp;
95 int err = 0, dirty;
96
97 ubifs_get_lprops(c);
98
99 lp = ubifs_lpt_lookup_dirty(c, b->bud->lnum);
100 if (IS_ERR(lp)) {
101 err = PTR_ERR(lp);
102 goto out;
103 }
104
105 dirty = lp->dirty;
106 if (b->bud->start == 0 && (lp->free != c->leb_size || lp->dirty != 0)) {
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126 dbg_mnt("bud LEB %d was GC'd (%d free, %d dirty)", b->bud->lnum,
127 lp->free, lp->dirty);
128 dbg_gc("bud LEB %d was GC'd (%d free, %d dirty)", b->bud->lnum,
129 lp->free, lp->dirty);
130 dirty -= c->leb_size - lp->free;
131
132
133
134
135
136
137
138 if (dirty != 0)
139 dbg_mnt("LEB %d lp: %d free %d dirty replay: %d free %d dirty",
140 b->bud->lnum, lp->free, lp->dirty, b->free,
141 b->dirty);
142 }
143 lp = ubifs_change_lp(c, lp, b->free, dirty + b->dirty,
144 lp->flags | LPROPS_TAKEN, 0);
145 if (IS_ERR(lp)) {
146 err = PTR_ERR(lp);
147 goto out;
148 }
149
150
151 err = ubifs_wbuf_seek_nolock(&c->jheads[b->bud->jhead].wbuf,
152 b->bud->lnum, c->leb_size - b->free);
153
154out:
155 ubifs_release_lprops(c);
156 return err;
157}
158
159
160
161
162
163
164
165
166static int set_buds_lprops(struct ubifs_info *c)
167{
168 struct bud_entry *b;
169 int err;
170
171 list_for_each_entry(b, &c->replay_buds, list) {
172 err = set_bud_lprops(c, b);
173 if (err)
174 return err;
175 }
176
177 return 0;
178}
179
180
181
182
183
184
185static int trun_remove_range(struct ubifs_info *c, struct replay_entry *r)
186{
187 unsigned min_blk, max_blk;
188 union ubifs_key min_key, max_key;
189 ino_t ino;
190
191 min_blk = r->new_size / UBIFS_BLOCK_SIZE;
192 if (r->new_size & (UBIFS_BLOCK_SIZE - 1))
193 min_blk += 1;
194
195 max_blk = r->old_size / UBIFS_BLOCK_SIZE;
196 if ((r->old_size & (UBIFS_BLOCK_SIZE - 1)) == 0)
197 max_blk -= 1;
198
199 ino = key_inum(c, &r->key);
200
201 data_key_init(c, &min_key, ino, min_blk);
202 data_key_init(c, &max_key, ino, max_blk);
203
204 return ubifs_tnc_remove_range(c, &min_key, &max_key);
205}
206
207
208
209
210
211
212
213
214static int apply_replay_entry(struct ubifs_info *c, struct replay_entry *r)
215{
216 int err;
217
218 dbg_mntk(&r->key, "LEB %d:%d len %d deletion %d sqnum %llu key ",
219 r->lnum, r->offs, r->len, r->deletion, r->sqnum);
220
221
222 c->replay_sqnum = r->sqnum;
223
224 if (is_hash_key(c, &r->key)) {
225 if (r->deletion)
226 err = ubifs_tnc_remove_nm(c, &r->key, &r->nm);
227 else
228 err = ubifs_tnc_add_nm(c, &r->key, r->lnum, r->offs,
229 r->len, &r->nm);
230 } else {
231 if (r->deletion)
232 switch (key_type(c, &r->key)) {
233 case UBIFS_INO_KEY:
234 {
235 ino_t inum = key_inum(c, &r->key);
236
237 err = ubifs_tnc_remove_ino(c, inum);
238 break;
239 }
240 case UBIFS_TRUN_KEY:
241 err = trun_remove_range(c, r);
242 break;
243 default:
244 err = ubifs_tnc_remove(c, &r->key);
245 break;
246 }
247 else
248 err = ubifs_tnc_add(c, &r->key, r->lnum, r->offs,
249 r->len);
250 if (err)
251 return err;
252
253 if (c->need_recovery)
254 err = ubifs_recover_size_accum(c, &r->key, r->deletion,
255 r->new_size);
256 }
257
258 return err;
259}
260
261
262
263
264
265
266
267
268
269
270
271static int replay_entries_cmp(void *priv, struct list_head *a,
272 struct list_head *b)
273{
274 struct replay_entry *ra, *rb;
275
276 cond_resched();
277 if (a == b)
278 return 0;
279
280 ra = list_entry(a, struct replay_entry, list);
281 rb = list_entry(b, struct replay_entry, list);
282 ubifs_assert(ra->sqnum != rb->sqnum);
283 if (ra->sqnum > rb->sqnum)
284 return 1;
285 return -1;
286}
287
288
289
290
291
292
293
294
295static int apply_replay_list(struct ubifs_info *c)
296{
297 struct replay_entry *r;
298 int err;
299
300 list_sort(c, &c->replay_list, &replay_entries_cmp);
301
302 list_for_each_entry(r, &c->replay_list, list) {
303 cond_resched();
304
305 err = apply_replay_entry(c, r);
306 if (err)
307 return err;
308 }
309
310 return 0;
311}
312
313
314
315
316
317
318
319static void destroy_replay_list(struct ubifs_info *c)
320{
321 struct replay_entry *r, *tmp;
322
323 list_for_each_entry_safe(r, tmp, &c->replay_list, list) {
324 if (is_hash_key(c, &r->key))
325 kfree(r->nm.name);
326 list_del(&r->list);
327 kfree(r);
328 }
329}
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351static int insert_node(struct ubifs_info *c, int lnum, int offs, int len,
352 union ubifs_key *key, unsigned long long sqnum,
353 int deletion, int *used, loff_t old_size,
354 loff_t new_size)
355{
356 struct replay_entry *r;
357
358 dbg_mntk(key, "add LEB %d:%d, key ", lnum, offs);
359
360 if (key_inum(c, key) >= c->highest_inum)
361 c->highest_inum = key_inum(c, key);
362
363 r = kzalloc(sizeof(struct replay_entry), GFP_KERNEL);
364 if (!r)
365 return -ENOMEM;
366
367 if (!deletion)
368 *used += ALIGN(len, 8);
369 r->lnum = lnum;
370 r->offs = offs;
371 r->len = len;
372 r->deletion = !!deletion;
373 r->sqnum = sqnum;
374 key_copy(c, key, &r->key);
375 r->old_size = old_size;
376 r->new_size = new_size;
377
378 list_add_tail(&r->list, &c->replay_list);
379 return 0;
380}
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399static int insert_dent(struct ubifs_info *c, int lnum, int offs, int len,
400 union ubifs_key *key, const char *name, int nlen,
401 unsigned long long sqnum, int deletion, int *used)
402{
403 struct replay_entry *r;
404 char *nbuf;
405
406 dbg_mntk(key, "add LEB %d:%d, key ", lnum, offs);
407 if (key_inum(c, key) >= c->highest_inum)
408 c->highest_inum = key_inum(c, key);
409
410 r = kzalloc(sizeof(struct replay_entry), GFP_KERNEL);
411 if (!r)
412 return -ENOMEM;
413
414 nbuf = kmalloc(nlen + 1, GFP_KERNEL);
415 if (!nbuf) {
416 kfree(r);
417 return -ENOMEM;
418 }
419
420 if (!deletion)
421 *used += ALIGN(len, 8);
422 r->lnum = lnum;
423 r->offs = offs;
424 r->len = len;
425 r->deletion = !!deletion;
426 r->sqnum = sqnum;
427 key_copy(c, key, &r->key);
428 r->nm.len = nlen;
429 memcpy(nbuf, name, nlen);
430 nbuf[nlen] = '\0';
431 r->nm.name = nbuf;
432
433 list_add_tail(&r->list, &c->replay_list);
434 return 0;
435}
436
437
438
439
440
441
442
443
444
445int ubifs_validate_entry(struct ubifs_info *c,
446 const struct ubifs_dent_node *dent)
447{
448 int key_type = key_type_flash(c, dent->key);
449 int nlen = le16_to_cpu(dent->nlen);
450
451 if (le32_to_cpu(dent->ch.len) != nlen + UBIFS_DENT_NODE_SZ + 1 ||
452 dent->type >= UBIFS_ITYPES_CNT ||
453 nlen > UBIFS_MAX_NLEN || dent->name[nlen] != 0 ||
454 strnlen(dent->name, nlen) != nlen ||
455 le64_to_cpu(dent->inum) > MAX_INUM) {
456 ubifs_err(c, "bad %s node", key_type == UBIFS_DENT_KEY ?
457 "directory entry" : "extended attribute entry");
458 return -EINVAL;
459 }
460
461 if (key_type != UBIFS_DENT_KEY && key_type != UBIFS_XENT_KEY) {
462 ubifs_err(c, "bad key type %d", key_type);
463 return -EINVAL;
464 }
465
466 return 0;
467}
468
469
470
471
472
473
474
475
476
477
478
479static int is_last_bud(struct ubifs_info *c, struct ubifs_bud *bud)
480{
481 struct ubifs_jhead *jh = &c->jheads[bud->jhead];
482 struct ubifs_bud *next;
483 uint32_t data;
484 int err;
485
486 if (list_is_last(&bud->list, &jh->buds_list))
487 return 1;
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516 next = list_entry(bud->list.next, struct ubifs_bud, list);
517 if (!list_is_last(&next->list, &jh->buds_list))
518 return 0;
519
520 err = ubifs_leb_read(c, next->lnum, (char *)&data, next->start, 4, 1);
521 if (err)
522 return 0;
523
524 return data == 0xFFFFFFFF;
525}
526
527
528
529
530
531
532
533
534
535
536static int replay_bud(struct ubifs_info *c, struct bud_entry *b)
537{
538 int is_last = is_last_bud(c, b->bud);
539 int err = 0, used = 0, lnum = b->bud->lnum, offs = b->bud->start;
540 struct ubifs_scan_leb *sleb;
541 struct ubifs_scan_node *snod;
542
543 dbg_mnt("replay bud LEB %d, head %d, offs %d, is_last %d",
544 lnum, b->bud->jhead, offs, is_last);
545
546 if (c->need_recovery && is_last)
547
548
549
550
551
552
553 sleb = ubifs_recover_leb(c, lnum, offs, c->sbuf, b->bud->jhead);
554 else
555 sleb = ubifs_scan(c, lnum, offs, c->sbuf, 0);
556 if (IS_ERR(sleb))
557 return PTR_ERR(sleb);
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581 list_for_each_entry(snod, &sleb->nodes, list) {
582 int deletion = 0;
583
584 cond_resched();
585
586 if (snod->sqnum >= SQNUM_WATERMARK) {
587 ubifs_err(c, "file system's life ended");
588 goto out_dump;
589 }
590
591 if (snod->sqnum > c->max_sqnum)
592 c->max_sqnum = snod->sqnum;
593
594 switch (snod->type) {
595 case UBIFS_INO_NODE:
596 {
597 struct ubifs_ino_node *ino = snod->node;
598 loff_t new_size = le64_to_cpu(ino->size);
599
600 if (le32_to_cpu(ino->nlink) == 0)
601 deletion = 1;
602 err = insert_node(c, lnum, snod->offs, snod->len,
603 &snod->key, snod->sqnum, deletion,
604 &used, 0, new_size);
605 break;
606 }
607 case UBIFS_DATA_NODE:
608 {
609 struct ubifs_data_node *dn = snod->node;
610 loff_t new_size = le32_to_cpu(dn->size) +
611 key_block(c, &snod->key) *
612 UBIFS_BLOCK_SIZE;
613
614 err = insert_node(c, lnum, snod->offs, snod->len,
615 &snod->key, snod->sqnum, deletion,
616 &used, 0, new_size);
617 break;
618 }
619 case UBIFS_DENT_NODE:
620 case UBIFS_XENT_NODE:
621 {
622 struct ubifs_dent_node *dent = snod->node;
623
624 err = ubifs_validate_entry(c, dent);
625 if (err)
626 goto out_dump;
627
628 err = insert_dent(c, lnum, snod->offs, snod->len,
629 &snod->key, dent->name,
630 le16_to_cpu(dent->nlen), snod->sqnum,
631 !le64_to_cpu(dent->inum), &used);
632 break;
633 }
634 case UBIFS_TRUN_NODE:
635 {
636 struct ubifs_trun_node *trun = snod->node;
637 loff_t old_size = le64_to_cpu(trun->old_size);
638 loff_t new_size = le64_to_cpu(trun->new_size);
639 union ubifs_key key;
640
641
642 if (old_size < 0 || old_size > c->max_inode_sz ||
643 new_size < 0 || new_size > c->max_inode_sz ||
644 old_size <= new_size) {
645 ubifs_err(c, "bad truncation node");
646 goto out_dump;
647 }
648
649
650
651
652
653 trun_key_init(c, &key, le32_to_cpu(trun->inum));
654 err = insert_node(c, lnum, snod->offs, snod->len,
655 &key, snod->sqnum, 1, &used,
656 old_size, new_size);
657 break;
658 }
659 default:
660 ubifs_err(c, "unexpected node type %d in bud LEB %d:%d",
661 snod->type, lnum, snod->offs);
662 err = -EINVAL;
663 goto out_dump;
664 }
665 if (err)
666 goto out;
667 }
668
669 ubifs_assert(ubifs_search_bud(c, lnum));
670 ubifs_assert(sleb->endpt - offs >= used);
671 ubifs_assert(sleb->endpt % c->min_io_size == 0);
672
673 b->dirty = sleb->endpt - offs - used;
674 b->free = c->leb_size - sleb->endpt;
675 dbg_mnt("bud LEB %d replied: dirty %d, free %d",
676 lnum, b->dirty, b->free);
677
678out:
679 ubifs_scan_destroy(sleb);
680 return err;
681
682out_dump:
683 ubifs_err(c, "bad node is at LEB %d:%d", lnum, snod->offs);
684 ubifs_dump_node(c, snod->node);
685 ubifs_scan_destroy(sleb);
686 return -EINVAL;
687}
688
689
690
691
692
693
694
695
696static int replay_buds(struct ubifs_info *c)
697{
698 struct bud_entry *b;
699 int err;
700 unsigned long long prev_sqnum = 0;
701
702 list_for_each_entry(b, &c->replay_buds, list) {
703 err = replay_bud(c, b);
704 if (err)
705 return err;
706
707 ubifs_assert(b->sqnum > prev_sqnum);
708 prev_sqnum = b->sqnum;
709 }
710
711 return 0;
712}
713
714
715
716
717
718static void destroy_bud_list(struct ubifs_info *c)
719{
720 struct bud_entry *b;
721
722 while (!list_empty(&c->replay_buds)) {
723 b = list_entry(c->replay_buds.next, struct bud_entry, list);
724 list_del(&b->list);
725 kfree(b);
726 }
727}
728
729
730
731
732
733
734
735
736
737
738
739
740static int add_replay_bud(struct ubifs_info *c, int lnum, int offs, int jhead,
741 unsigned long long sqnum)
742{
743 struct ubifs_bud *bud;
744 struct bud_entry *b;
745
746 dbg_mnt("add replay bud LEB %d:%d, head %d", lnum, offs, jhead);
747
748 bud = kmalloc(sizeof(struct ubifs_bud), GFP_KERNEL);
749 if (!bud)
750 return -ENOMEM;
751
752 b = kmalloc(sizeof(struct bud_entry), GFP_KERNEL);
753 if (!b) {
754 kfree(bud);
755 return -ENOMEM;
756 }
757
758 bud->lnum = lnum;
759 bud->start = offs;
760 bud->jhead = jhead;
761 ubifs_add_bud(c, bud);
762
763 b->bud = bud;
764 b->sqnum = sqnum;
765 list_add_tail(&b->list, &c->replay_buds);
766
767 return 0;
768}
769
770
771
772
773
774
775
776
777
778
779
780
781static int validate_ref(struct ubifs_info *c, const struct ubifs_ref_node *ref)
782{
783 struct ubifs_bud *bud;
784 int lnum = le32_to_cpu(ref->lnum);
785 unsigned int offs = le32_to_cpu(ref->offs);
786 unsigned int jhead = le32_to_cpu(ref->jhead);
787
788
789
790
791
792
793 if (jhead >= c->jhead_cnt || lnum >= c->leb_cnt ||
794 lnum < c->main_first || offs > c->leb_size ||
795 offs & (c->min_io_size - 1))
796 return -EINVAL;
797
798
799 bud = ubifs_search_bud(c, lnum);
800 if (bud) {
801 if (bud->jhead == jhead && bud->start <= offs)
802 return 1;
803 ubifs_err(c, "bud at LEB %d:%d was already referred", lnum, offs);
804 return -EINVAL;
805 }
806
807 return 0;
808}
809
810
811
812
813
814
815
816
817
818
819
820
821static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf)
822{
823 int err;
824 struct ubifs_scan_leb *sleb;
825 struct ubifs_scan_node *snod;
826 const struct ubifs_cs_node *node;
827
828 dbg_mnt("replay log LEB %d:%d", lnum, offs);
829 sleb = ubifs_scan(c, lnum, offs, sbuf, c->need_recovery);
830 if (IS_ERR(sleb)) {
831 if (PTR_ERR(sleb) != -EUCLEAN || !c->need_recovery)
832 return PTR_ERR(sleb);
833
834
835
836
837
838 sleb = ubifs_recover_log_leb(c, lnum, offs, sbuf);
839 if (IS_ERR(sleb))
840 return PTR_ERR(sleb);
841 }
842
843 if (sleb->nodes_cnt == 0) {
844 err = 1;
845 goto out;
846 }
847
848 node = sleb->buf;
849 snod = list_entry(sleb->nodes.next, struct ubifs_scan_node, list);
850 if (c->cs_sqnum == 0) {
851
852
853
854
855
856
857
858 if (snod->type != UBIFS_CS_NODE) {
859 ubifs_err(c, "first log node at LEB %d:%d is not CS node",
860 lnum, offs);
861 goto out_dump;
862 }
863 if (le64_to_cpu(node->cmt_no) != c->cmt_no) {
864 ubifs_err(c, "first CS node at LEB %d:%d has wrong commit number %llu expected %llu",
865 lnum, offs,
866 (unsigned long long)le64_to_cpu(node->cmt_no),
867 c->cmt_no);
868 goto out_dump;
869 }
870
871 c->cs_sqnum = le64_to_cpu(node->ch.sqnum);
872 dbg_mnt("commit start sqnum %llu", c->cs_sqnum);
873 }
874
875 if (snod->sqnum < c->cs_sqnum) {
876
877
878
879
880
881
882
883 err = 1;
884 goto out;
885 }
886
887
888 if (snod->offs != 0) {
889 ubifs_err(c, "first node is not at zero offset");
890 goto out_dump;
891 }
892
893 list_for_each_entry(snod, &sleb->nodes, list) {
894 cond_resched();
895
896 if (snod->sqnum >= SQNUM_WATERMARK) {
897 ubifs_err(c, "file system's life ended");
898 goto out_dump;
899 }
900
901 if (snod->sqnum < c->cs_sqnum) {
902 ubifs_err(c, "bad sqnum %llu, commit sqnum %llu",
903 snod->sqnum, c->cs_sqnum);
904 goto out_dump;
905 }
906
907 if (snod->sqnum > c->max_sqnum)
908 c->max_sqnum = snod->sqnum;
909
910 switch (snod->type) {
911 case UBIFS_REF_NODE: {
912 const struct ubifs_ref_node *ref = snod->node;
913
914 err = validate_ref(c, ref);
915 if (err == 1)
916 break;
917 if (err)
918 goto out_dump;
919
920 err = add_replay_bud(c, le32_to_cpu(ref->lnum),
921 le32_to_cpu(ref->offs),
922 le32_to_cpu(ref->jhead),
923 snod->sqnum);
924 if (err)
925 goto out;
926
927 break;
928 }
929 case UBIFS_CS_NODE:
930
931 if (snod->offs != 0) {
932 ubifs_err(c, "unexpected node in log");
933 goto out_dump;
934 }
935 break;
936 default:
937 ubifs_err(c, "unexpected node in log");
938 goto out_dump;
939 }
940 }
941
942 if (sleb->endpt || c->lhead_offs >= c->leb_size) {
943 c->lhead_lnum = lnum;
944 c->lhead_offs = sleb->endpt;
945 }
946
947 err = !sleb->endpt;
948out:
949 ubifs_scan_destroy(sleb);
950 return err;
951
952out_dump:
953 ubifs_err(c, "log error detected while replaying the log at LEB %d:%d",
954 lnum, offs + snod->offs);
955 ubifs_dump_node(c, snod->node);
956 ubifs_scan_destroy(sleb);
957 return -EINVAL;
958}
959
960
961
962
963
964
965
966
967static int take_ihead(struct ubifs_info *c)
968{
969 const struct ubifs_lprops *lp;
970 int err, free;
971
972 ubifs_get_lprops(c);
973
974 lp = ubifs_lpt_lookup_dirty(c, c->ihead_lnum);
975 if (IS_ERR(lp)) {
976 err = PTR_ERR(lp);
977 goto out;
978 }
979
980 free = lp->free;
981
982 lp = ubifs_change_lp(c, lp, LPROPS_NC, LPROPS_NC,
983 lp->flags | LPROPS_TAKEN, 0);
984 if (IS_ERR(lp)) {
985 err = PTR_ERR(lp);
986 goto out;
987 }
988
989 err = free;
990out:
991 ubifs_release_lprops(c);
992 return err;
993}
994
995
996
997
998
999
1000
1001
1002
1003int ubifs_replay_journal(struct ubifs_info *c)
1004{
1005 int err, lnum, free;
1006
1007 BUILD_BUG_ON(UBIFS_TRUN_KEY > 5);
1008
1009
1010 free = take_ihead(c);
1011 if (free < 0)
1012 return free;
1013
1014 if (c->ihead_offs != c->leb_size - free) {
1015 ubifs_err(c, "bad index head LEB %d:%d", c->ihead_lnum,
1016 c->ihead_offs);
1017 return -EINVAL;
1018 }
1019
1020 dbg_mnt("start replaying the journal");
1021 c->replaying = 1;
1022 lnum = c->ltail_lnum = c->lhead_lnum;
1023
1024 do {
1025 err = replay_log_leb(c, lnum, 0, c->sbuf);
1026 if (err == 1) {
1027 if (lnum != c->lhead_lnum)
1028
1029 break;
1030
1031
1032
1033
1034
1035
1036
1037
1038 ubifs_err(c, "no UBIFS nodes found at the log head LEB %d:%d, possibly corrupted",
1039 lnum, 0);
1040 err = -EINVAL;
1041 }
1042 if (err)
1043 goto out;
1044 lnum = ubifs_next_log_lnum(c, lnum);
1045 } while (lnum != c->ltail_lnum);
1046
1047 err = replay_buds(c);
1048 if (err)
1049 goto out;
1050
1051 err = apply_replay_list(c);
1052 if (err)
1053 goto out;
1054
1055 err = set_buds_lprops(c);
1056 if (err)
1057 goto out;
1058
1059
1060
1061
1062
1063
1064
1065 c->bi.uncommitted_idx = atomic_long_read(&c->dirty_zn_cnt);
1066 c->bi.uncommitted_idx *= c->max_idx_node_sz;
1067
1068 ubifs_assert(c->bud_bytes <= c->max_bud_bytes || c->need_recovery);
1069 dbg_mnt("finished, log head LEB %d:%d, max_sqnum %llu, highest_inum %lu",
1070 c->lhead_lnum, c->lhead_offs, c->max_sqnum,
1071 (unsigned long)c->highest_inum);
1072out:
1073 destroy_replay_list(c);
1074 destroy_bud_list(c);
1075 c->replaying = 0;
1076 return err;
1077}
1078