This source file includes following definitions.
- valuable
- scan_for_dirty_cb
- scan_for_dirty
- ubifs_find_dirty_leb
- scan_for_free_cb
- do_find_free_space
- ubifs_find_free_space
- scan_for_idx_cb
- scan_for_leb_for_idx
- ubifs_find_free_leb_for_idx
- cmp_dirty_idx
- ubifs_save_dirty_idx_lnums
- scan_dirty_idx_cb
- find_dirty_idx_leb
- get_idx_gc_leb
- find_dirtiest_idx_leb
- ubifs_find_dirty_idx_leb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 #include <linux/sort.h>
18 #include "ubifs.h"
19
20
21
22
23
24
25
26
27 struct scan_data {
28 int min_space;
29 int pick_free;
30 int lnum;
31 int exclude_index;
32 };
33
34
35
36
37
38
39
40
41
42 static int valuable(struct ubifs_info *c, const struct ubifs_lprops *lprops)
43 {
44 int n, cat = lprops->flags & LPROPS_CAT_MASK;
45 struct ubifs_lpt_heap *heap;
46
47 switch (cat) {
48 case LPROPS_DIRTY:
49 case LPROPS_DIRTY_IDX:
50 case LPROPS_FREE:
51 heap = &c->lpt_heap[cat - 1];
52 if (heap->cnt < heap->max_cnt)
53 return 1;
54 if (lprops->free + lprops->dirty >= c->dark_wm)
55 return 1;
56 return 0;
57 case LPROPS_EMPTY:
58 n = c->lst.empty_lebs + c->freeable_cnt -
59 c->lst.taken_empty_lebs;
60 if (n < c->lsave_cnt)
61 return 1;
62 return 0;
63 case LPROPS_FREEABLE:
64 return 1;
65 case LPROPS_FRDI_IDX:
66 return 1;
67 }
68 return 0;
69 }
70
71
72
73
74
75
76
77
78
79
80
81
82
83 static int scan_for_dirty_cb(struct ubifs_info *c,
84 const struct ubifs_lprops *lprops, int in_tree,
85 struct scan_data *data)
86 {
87 int ret = LPT_SCAN_CONTINUE;
88
89
90 if (lprops->flags & LPROPS_TAKEN)
91 return LPT_SCAN_CONTINUE;
92
93 if (!in_tree && valuable(c, lprops))
94 ret |= LPT_SCAN_ADD;
95
96 if (lprops->free + lprops->dirty < data->min_space)
97 return ret;
98
99 if (data->exclude_index && lprops->flags & LPROPS_INDEX)
100 return ret;
101
102 if (lprops->free + lprops->dirty == c->leb_size) {
103 if (!data->pick_free)
104 return ret;
105
106 } else if (lprops->dirty < c->dead_wm)
107 return ret;
108
109 data->lnum = lprops->lnum;
110 return LPT_SCAN_ADD | LPT_SCAN_STOP;
111 }
112
113
114
115
116
117
118
119
120
121
122
123
124 static const struct ubifs_lprops *scan_for_dirty(struct ubifs_info *c,
125 int min_space, int pick_free,
126 int exclude_index)
127 {
128 const struct ubifs_lprops *lprops;
129 struct ubifs_lpt_heap *heap;
130 struct scan_data data;
131 int err, i;
132
133
134 heap = &c->lpt_heap[LPROPS_FREE - 1];
135 for (i = 0; i < heap->cnt; i++) {
136 lprops = heap->arr[i];
137 if (lprops->free + lprops->dirty < min_space)
138 continue;
139 if (lprops->dirty < c->dead_wm)
140 continue;
141 return lprops;
142 }
143
144
145
146
147
148
149
150 list_for_each_entry(lprops, &c->uncat_list, list) {
151 if (lprops->flags & LPROPS_TAKEN)
152 continue;
153 if (lprops->free + lprops->dirty < min_space)
154 continue;
155 if (exclude_index && (lprops->flags & LPROPS_INDEX))
156 continue;
157 if (lprops->dirty < c->dead_wm)
158 continue;
159 return lprops;
160 }
161
162 if (c->pnodes_have >= c->pnode_cnt)
163
164 return ERR_PTR(-ENOSPC);
165 data.min_space = min_space;
166 data.pick_free = pick_free;
167 data.lnum = -1;
168 data.exclude_index = exclude_index;
169 err = ubifs_lpt_scan_nolock(c, -1, c->lscan_lnum,
170 (ubifs_lpt_scan_callback)scan_for_dirty_cb,
171 &data);
172 if (err)
173 return ERR_PTR(err);
174 ubifs_assert(c, data.lnum >= c->main_first && data.lnum < c->leb_cnt);
175 c->lscan_lnum = data.lnum;
176 lprops = ubifs_lpt_lookup_dirty(c, data.lnum);
177 if (IS_ERR(lprops))
178 return lprops;
179 ubifs_assert(c, lprops->lnum == data.lnum);
180 ubifs_assert(c, lprops->free + lprops->dirty >= min_space);
181 ubifs_assert(c, lprops->dirty >= c->dead_wm ||
182 (pick_free &&
183 lprops->free + lprops->dirty == c->leb_size));
184 ubifs_assert(c, !(lprops->flags & LPROPS_TAKEN));
185 ubifs_assert(c, !exclude_index || !(lprops->flags & LPROPS_INDEX));
186 return lprops;
187 }
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221 int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp,
222 int min_space, int pick_free)
223 {
224 int err = 0, sum, exclude_index = pick_free == 2 ? 1 : 0;
225 const struct ubifs_lprops *lp = NULL, *idx_lp = NULL;
226 struct ubifs_lpt_heap *heap, *idx_heap;
227
228 ubifs_get_lprops(c);
229
230 if (pick_free) {
231 int lebs, rsvd_idx_lebs = 0;
232
233 spin_lock(&c->space_lock);
234 lebs = c->lst.empty_lebs + c->idx_gc_cnt;
235 lebs += c->freeable_cnt - c->lst.taken_empty_lebs;
236
237
238
239
240
241
242
243 if (c->bi.min_idx_lebs >= c->lst.idx_lebs) {
244 rsvd_idx_lebs = c->bi.min_idx_lebs - c->lst.idx_lebs;
245 exclude_index = 1;
246 }
247 spin_unlock(&c->space_lock);
248
249
250 if (rsvd_idx_lebs < lebs) {
251
252 lp = ubifs_fast_find_empty(c);
253 if (lp)
254 goto found;
255
256
257 lp = ubifs_fast_find_freeable(c);
258 if (lp)
259 goto found;
260 } else
261
262
263
264 pick_free = 0;
265 } else {
266 spin_lock(&c->space_lock);
267 exclude_index = (c->bi.min_idx_lebs >= c->lst.idx_lebs);
268 spin_unlock(&c->space_lock);
269 }
270
271
272 heap = &c->lpt_heap[LPROPS_DIRTY - 1];
273 idx_heap = &c->lpt_heap[LPROPS_DIRTY_IDX - 1];
274
275 if (idx_heap->cnt && !exclude_index) {
276 idx_lp = idx_heap->arr[0];
277 sum = idx_lp->free + idx_lp->dirty;
278
279
280
281
282
283
284
285
286
287
288 if (sum < min_space || sum < c->half_leb_size)
289 idx_lp = NULL;
290 }
291
292 if (heap->cnt) {
293 lp = heap->arr[0];
294 if (lp->dirty + lp->free < min_space)
295 lp = NULL;
296 }
297
298
299 if (idx_lp && lp) {
300 if (idx_lp->free + idx_lp->dirty >= lp->free + lp->dirty)
301 lp = idx_lp;
302 } else if (idx_lp && !lp)
303 lp = idx_lp;
304
305 if (lp) {
306 ubifs_assert(c, lp->free + lp->dirty >= c->dead_wm);
307 goto found;
308 }
309
310
311 dbg_find("scanning LPT for a dirty LEB");
312 lp = scan_for_dirty(c, min_space, pick_free, exclude_index);
313 if (IS_ERR(lp)) {
314 err = PTR_ERR(lp);
315 goto out;
316 }
317 ubifs_assert(c, lp->dirty >= c->dead_wm ||
318 (pick_free && lp->free + lp->dirty == c->leb_size));
319
320 found:
321 dbg_find("found LEB %d, free %d, dirty %d, flags %#x",
322 lp->lnum, lp->free, lp->dirty, lp->flags);
323
324 lp = ubifs_change_lp(c, lp, LPROPS_NC, LPROPS_NC,
325 lp->flags | LPROPS_TAKEN, 0);
326 if (IS_ERR(lp)) {
327 err = PTR_ERR(lp);
328 goto out;
329 }
330
331 memcpy(ret_lp, lp, sizeof(struct ubifs_lprops));
332
333 out:
334 ubifs_release_lprops(c);
335 return err;
336 }
337
338
339
340
341
342
343
344
345
346
347
348
349
350 static int scan_for_free_cb(struct ubifs_info *c,
351 const struct ubifs_lprops *lprops, int in_tree,
352 struct scan_data *data)
353 {
354 int ret = LPT_SCAN_CONTINUE;
355
356
357 if (lprops->flags & LPROPS_TAKEN)
358 return LPT_SCAN_CONTINUE;
359
360 if (!in_tree && valuable(c, lprops))
361 ret |= LPT_SCAN_ADD;
362
363 if (lprops->flags & LPROPS_INDEX)
364 return ret;
365
366 if (lprops->free < data->min_space)
367 return ret;
368
369 if (!data->pick_free && lprops->free == c->leb_size)
370 return ret;
371
372
373
374
375
376
377 if (lprops->free + lprops->dirty == c->leb_size && lprops->dirty > 0)
378 return ret;
379
380 data->lnum = lprops->lnum;
381 return LPT_SCAN_ADD | LPT_SCAN_STOP;
382 }
383
384
385
386
387
388
389
390
391
392
393
394 static
395 const struct ubifs_lprops *do_find_free_space(struct ubifs_info *c,
396 int min_space, int pick_free,
397 int squeeze)
398 {
399 const struct ubifs_lprops *lprops;
400 struct ubifs_lpt_heap *heap;
401 struct scan_data data;
402 int err, i;
403
404 if (squeeze) {
405 lprops = ubifs_fast_find_free(c);
406 if (lprops && lprops->free >= min_space)
407 return lprops;
408 }
409 if (pick_free) {
410 lprops = ubifs_fast_find_empty(c);
411 if (lprops)
412 return lprops;
413 }
414 if (!squeeze) {
415 lprops = ubifs_fast_find_free(c);
416 if (lprops && lprops->free >= min_space)
417 return lprops;
418 }
419
420 heap = &c->lpt_heap[LPROPS_DIRTY - 1];
421 for (i = 0; i < heap->cnt; i++) {
422 lprops = heap->arr[i];
423 if (lprops->free >= min_space)
424 return lprops;
425 }
426
427
428
429
430
431
432
433 list_for_each_entry(lprops, &c->uncat_list, list) {
434 if (lprops->flags & LPROPS_TAKEN)
435 continue;
436 if (lprops->flags & LPROPS_INDEX)
437 continue;
438 if (lprops->free >= min_space)
439 return lprops;
440 }
441
442 if (c->pnodes_have >= c->pnode_cnt)
443
444 return ERR_PTR(-ENOSPC);
445 data.min_space = min_space;
446 data.pick_free = pick_free;
447 data.lnum = -1;
448 err = ubifs_lpt_scan_nolock(c, -1, c->lscan_lnum,
449 (ubifs_lpt_scan_callback)scan_for_free_cb,
450 &data);
451 if (err)
452 return ERR_PTR(err);
453 ubifs_assert(c, data.lnum >= c->main_first && data.lnum < c->leb_cnt);
454 c->lscan_lnum = data.lnum;
455 lprops = ubifs_lpt_lookup_dirty(c, data.lnum);
456 if (IS_ERR(lprops))
457 return lprops;
458 ubifs_assert(c, lprops->lnum == data.lnum);
459 ubifs_assert(c, lprops->free >= min_space);
460 ubifs_assert(c, !(lprops->flags & LPROPS_TAKEN));
461 ubifs_assert(c, !(lprops->flags & LPROPS_INDEX));
462 return lprops;
463 }
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481 int ubifs_find_free_space(struct ubifs_info *c, int min_space, int *offs,
482 int squeeze)
483 {
484 const struct ubifs_lprops *lprops;
485 int lebs, rsvd_idx_lebs, pick_free = 0, err, lnum, flags;
486
487 dbg_find("min_space %d", min_space);
488 ubifs_get_lprops(c);
489
490
491 spin_lock(&c->space_lock);
492 if (c->bi.min_idx_lebs > c->lst.idx_lebs)
493 rsvd_idx_lebs = c->bi.min_idx_lebs - c->lst.idx_lebs;
494 else
495 rsvd_idx_lebs = 0;
496 lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt -
497 c->lst.taken_empty_lebs;
498 if (rsvd_idx_lebs < lebs)
499
500
501
502
503 if (c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) {
504 pick_free = 1;
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524 c->lst.taken_empty_lebs += 1;
525 }
526 spin_unlock(&c->space_lock);
527
528 lprops = do_find_free_space(c, min_space, pick_free, squeeze);
529 if (IS_ERR(lprops)) {
530 err = PTR_ERR(lprops);
531 goto out;
532 }
533
534 lnum = lprops->lnum;
535 flags = lprops->flags | LPROPS_TAKEN;
536
537 lprops = ubifs_change_lp(c, lprops, LPROPS_NC, LPROPS_NC, flags, 0);
538 if (IS_ERR(lprops)) {
539 err = PTR_ERR(lprops);
540 goto out;
541 }
542
543 if (pick_free) {
544 spin_lock(&c->space_lock);
545 c->lst.taken_empty_lebs -= 1;
546 spin_unlock(&c->space_lock);
547 }
548
549 *offs = c->leb_size - lprops->free;
550 ubifs_release_lprops(c);
551
552 if (*offs == 0) {
553
554
555
556
557
558
559 err = ubifs_leb_unmap(c, lnum);
560 if (err)
561 return err;
562 }
563
564 dbg_find("found LEB %d, free %d", lnum, c->leb_size - *offs);
565 ubifs_assert(c, *offs <= c->leb_size - min_space);
566 return lnum;
567
568 out:
569 if (pick_free) {
570 spin_lock(&c->space_lock);
571 c->lst.taken_empty_lebs -= 1;
572 spin_unlock(&c->space_lock);
573 }
574 ubifs_release_lprops(c);
575 return err;
576 }
577
578
579
580
581
582
583
584
585
586
587
588
589
590 static int scan_for_idx_cb(struct ubifs_info *c,
591 const struct ubifs_lprops *lprops, int in_tree,
592 struct scan_data *data)
593 {
594 int ret = LPT_SCAN_CONTINUE;
595
596
597 if (lprops->flags & LPROPS_TAKEN)
598 return LPT_SCAN_CONTINUE;
599
600 if (!in_tree && valuable(c, lprops))
601 ret |= LPT_SCAN_ADD;
602
603 if (lprops->flags & LPROPS_INDEX)
604 return ret;
605
606 if (lprops->free + lprops->dirty != c->leb_size)
607 return ret;
608
609
610
611
612
613 data->lnum = lprops->lnum;
614 return LPT_SCAN_ADD | LPT_SCAN_STOP;
615 }
616
617
618
619
620
621 static const struct ubifs_lprops *scan_for_leb_for_idx(struct ubifs_info *c)
622 {
623 const struct ubifs_lprops *lprops;
624 struct scan_data data;
625 int err;
626
627 data.lnum = -1;
628 err = ubifs_lpt_scan_nolock(c, -1, c->lscan_lnum,
629 (ubifs_lpt_scan_callback)scan_for_idx_cb,
630 &data);
631 if (err)
632 return ERR_PTR(err);
633 ubifs_assert(c, data.lnum >= c->main_first && data.lnum < c->leb_cnt);
634 c->lscan_lnum = data.lnum;
635 lprops = ubifs_lpt_lookup_dirty(c, data.lnum);
636 if (IS_ERR(lprops))
637 return lprops;
638 ubifs_assert(c, lprops->lnum == data.lnum);
639 ubifs_assert(c, lprops->free + lprops->dirty == c->leb_size);
640 ubifs_assert(c, !(lprops->flags & LPROPS_TAKEN));
641 ubifs_assert(c, !(lprops->flags & LPROPS_INDEX));
642 return lprops;
643 }
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661 int ubifs_find_free_leb_for_idx(struct ubifs_info *c)
662 {
663 const struct ubifs_lprops *lprops;
664 int lnum = -1, err, flags;
665
666 ubifs_get_lprops(c);
667
668 lprops = ubifs_fast_find_empty(c);
669 if (!lprops) {
670 lprops = ubifs_fast_find_freeable(c);
671 if (!lprops) {
672
673
674
675
676
677
678
679 if (c->in_a_category_cnt != c->main_lebs ||
680 c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) {
681 ubifs_assert(c, c->freeable_cnt == 0);
682 lprops = scan_for_leb_for_idx(c);
683 if (IS_ERR(lprops)) {
684 err = PTR_ERR(lprops);
685 goto out;
686 }
687 }
688 }
689 }
690
691 if (!lprops) {
692 err = -ENOSPC;
693 goto out;
694 }
695
696 lnum = lprops->lnum;
697
698 dbg_find("found LEB %d, free %d, dirty %d, flags %#x",
699 lnum, lprops->free, lprops->dirty, lprops->flags);
700
701 flags = lprops->flags | LPROPS_TAKEN | LPROPS_INDEX;
702 lprops = ubifs_change_lp(c, lprops, c->leb_size, 0, flags, 0);
703 if (IS_ERR(lprops)) {
704 err = PTR_ERR(lprops);
705 goto out;
706 }
707
708 ubifs_release_lprops(c);
709
710
711
712
713
714
715 err = ubifs_leb_unmap(c, lnum);
716 if (err) {
717 ubifs_change_one_lp(c, lnum, LPROPS_NC, LPROPS_NC, 0,
718 LPROPS_TAKEN | LPROPS_INDEX, 0);
719 return err;
720 }
721
722 return lnum;
723
724 out:
725 ubifs_release_lprops(c);
726 return err;
727 }
728
729 static int cmp_dirty_idx(const struct ubifs_lprops **a,
730 const struct ubifs_lprops **b)
731 {
732 const struct ubifs_lprops *lpa = *a;
733 const struct ubifs_lprops *lpb = *b;
734
735 return lpa->dirty + lpa->free - lpb->dirty - lpb->free;
736 }
737
738
739
740
741
742
743
744
745
746 int ubifs_save_dirty_idx_lnums(struct ubifs_info *c)
747 {
748 int i;
749
750 ubifs_get_lprops(c);
751
752 c->dirty_idx.cnt = c->lpt_heap[LPROPS_DIRTY_IDX - 1].cnt;
753 memcpy(c->dirty_idx.arr, c->lpt_heap[LPROPS_DIRTY_IDX - 1].arr,
754 sizeof(void *) * c->dirty_idx.cnt);
755
756 sort(c->dirty_idx.arr, c->dirty_idx.cnt, sizeof(void *),
757 (int (*)(const void *, const void *))cmp_dirty_idx, NULL);
758 dbg_find("found %d dirty index LEBs", c->dirty_idx.cnt);
759 if (c->dirty_idx.cnt)
760 dbg_find("dirtiest index LEB is %d with dirty %d and free %d",
761 c->dirty_idx.arr[c->dirty_idx.cnt - 1]->lnum,
762 c->dirty_idx.arr[c->dirty_idx.cnt - 1]->dirty,
763 c->dirty_idx.arr[c->dirty_idx.cnt - 1]->free);
764
765 for (i = 0; i < c->dirty_idx.cnt; i++)
766 c->dirty_idx.arr[i] = (void *)(size_t)c->dirty_idx.arr[i]->lnum;
767 ubifs_release_lprops(c);
768 return 0;
769 }
770
771
772
773
774
775
776
777
778
779
780
781
782
783 static int scan_dirty_idx_cb(struct ubifs_info *c,
784 const struct ubifs_lprops *lprops, int in_tree,
785 struct scan_data *data)
786 {
787 int ret = LPT_SCAN_CONTINUE;
788
789
790 if (lprops->flags & LPROPS_TAKEN)
791 return LPT_SCAN_CONTINUE;
792
793 if (!in_tree && valuable(c, lprops))
794 ret |= LPT_SCAN_ADD;
795
796 if (!(lprops->flags & LPROPS_INDEX))
797 return ret;
798
799 if (lprops->free + lprops->dirty < c->min_idx_node_sz)
800 return ret;
801
802 data->lnum = lprops->lnum;
803 return LPT_SCAN_ADD | LPT_SCAN_STOP;
804 }
805
806
807
808
809
810
811
812
813
814
815
816 static int find_dirty_idx_leb(struct ubifs_info *c)
817 {
818 const struct ubifs_lprops *lprops;
819 struct ubifs_lpt_heap *heap;
820 struct scan_data data;
821 int err, i, ret;
822
823
824 data.lnum = -1;
825 heap = &c->lpt_heap[LPROPS_DIRTY_IDX - 1];
826 for (i = 0; i < heap->cnt; i++) {
827 lprops = heap->arr[i];
828 ret = scan_dirty_idx_cb(c, lprops, 1, &data);
829 if (ret & LPT_SCAN_STOP)
830 goto found;
831 }
832 list_for_each_entry(lprops, &c->frdi_idx_list, list) {
833 ret = scan_dirty_idx_cb(c, lprops, 1, &data);
834 if (ret & LPT_SCAN_STOP)
835 goto found;
836 }
837 list_for_each_entry(lprops, &c->uncat_list, list) {
838 ret = scan_dirty_idx_cb(c, lprops, 1, &data);
839 if (ret & LPT_SCAN_STOP)
840 goto found;
841 }
842 if (c->pnodes_have >= c->pnode_cnt)
843
844 return -ENOSPC;
845 err = ubifs_lpt_scan_nolock(c, -1, c->lscan_lnum,
846 (ubifs_lpt_scan_callback)scan_dirty_idx_cb,
847 &data);
848 if (err)
849 return err;
850 found:
851 ubifs_assert(c, data.lnum >= c->main_first && data.lnum < c->leb_cnt);
852 c->lscan_lnum = data.lnum;
853 lprops = ubifs_lpt_lookup_dirty(c, data.lnum);
854 if (IS_ERR(lprops))
855 return PTR_ERR(lprops);
856 ubifs_assert(c, lprops->lnum == data.lnum);
857 ubifs_assert(c, lprops->free + lprops->dirty >= c->min_idx_node_sz);
858 ubifs_assert(c, !(lprops->flags & LPROPS_TAKEN));
859 ubifs_assert(c, (lprops->flags & LPROPS_INDEX));
860
861 dbg_find("found dirty LEB %d, free %d, dirty %d, flags %#x",
862 lprops->lnum, lprops->free, lprops->dirty, lprops->flags);
863
864 lprops = ubifs_change_lp(c, lprops, LPROPS_NC, LPROPS_NC,
865 lprops->flags | LPROPS_TAKEN, 0);
866 if (IS_ERR(lprops))
867 return PTR_ERR(lprops);
868
869 return lprops->lnum;
870 }
871
872
873
874
875
876 static int get_idx_gc_leb(struct ubifs_info *c)
877 {
878 const struct ubifs_lprops *lp;
879 int err, lnum;
880
881 err = ubifs_get_idx_gc_leb(c);
882 if (err < 0)
883 return err;
884 lnum = err;
885
886
887
888
889 lp = ubifs_lpt_lookup_dirty(c, lnum);
890 if (IS_ERR(lp))
891 return PTR_ERR(lp);
892 lp = ubifs_change_lp(c, lp, LPROPS_NC, LPROPS_NC,
893 lp->flags | LPROPS_INDEX, -1);
894 if (IS_ERR(lp))
895 return PTR_ERR(lp);
896 dbg_find("LEB %d, dirty %d and free %d flags %#x",
897 lp->lnum, lp->dirty, lp->free, lp->flags);
898 return lnum;
899 }
900
901
902
903
904
905 static int find_dirtiest_idx_leb(struct ubifs_info *c)
906 {
907 const struct ubifs_lprops *lp;
908 int lnum;
909
910 while (1) {
911 if (!c->dirty_idx.cnt)
912 return -ENOSPC;
913
914 lnum = (size_t)c->dirty_idx.arr[--c->dirty_idx.cnt];
915 lp = ubifs_lpt_lookup(c, lnum);
916 if (IS_ERR(lp))
917 return PTR_ERR(lp);
918 if ((lp->flags & LPROPS_TAKEN) || !(lp->flags & LPROPS_INDEX))
919 continue;
920 lp = ubifs_change_lp(c, lp, LPROPS_NC, LPROPS_NC,
921 lp->flags | LPROPS_TAKEN, 0);
922 if (IS_ERR(lp))
923 return PTR_ERR(lp);
924 break;
925 }
926 dbg_find("LEB %d, dirty %d and free %d flags %#x", lp->lnum, lp->dirty,
927 lp->free, lp->flags);
928 ubifs_assert(c, lp->flags & LPROPS_TAKEN);
929 ubifs_assert(c, lp->flags & LPROPS_INDEX);
930 return lnum;
931 }
932
933
934
935
936
937
938
939
940
941 int ubifs_find_dirty_idx_leb(struct ubifs_info *c)
942 {
943 int err;
944
945 ubifs_get_lprops(c);
946
947
948
949
950
951 err = find_dirtiest_idx_leb(c);
952
953
954 if (err == -ENOSPC)
955 err = find_dirty_idx_leb(c);
956
957
958 if (err == -ENOSPC)
959 err = get_idx_gc_leb(c);
960
961 ubifs_release_lprops(c);
962 return err;
963 }