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