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(c, 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(c, lprops->lnum == data.lnum);
192 ubifs_assert(c, lprops->free + lprops->dirty >= min_space);
193 ubifs_assert(c, lprops->dirty >= c->dead_wm ||
194 (pick_free &&
195 lprops->free + lprops->dirty == c->leb_size));
196 ubifs_assert(c, !(lprops->flags & LPROPS_TAKEN));
197 ubifs_assert(c, !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(c, 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(c, 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(c, 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(c, lprops->lnum == data.lnum);
471 ubifs_assert(c, lprops->free >= min_space);
472 ubifs_assert(c, !(lprops->flags & LPROPS_TAKEN));
473 ubifs_assert(c, !(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(c, *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 const 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(c, 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(c, lprops->lnum == data.lnum);
651 ubifs_assert(c, lprops->free + lprops->dirty == c->leb_size);
652 ubifs_assert(c, !(lprops->flags & LPROPS_TAKEN));
653 ubifs_assert(c, !(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, 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 swap(*a, *b);
754}
755
756
757
758
759
760
761
762
763
764int ubifs_save_dirty_idx_lnums(struct ubifs_info *c)
765{
766 int i;
767
768 ubifs_get_lprops(c);
769
770 c->dirty_idx.cnt = c->lpt_heap[LPROPS_DIRTY_IDX - 1].cnt;
771 memcpy(c->dirty_idx.arr, c->lpt_heap[LPROPS_DIRTY_IDX - 1].arr,
772 sizeof(void *) * c->dirty_idx.cnt);
773
774 sort(c->dirty_idx.arr, c->dirty_idx.cnt, sizeof(void *),
775 (int (*)(const void *, const void *))cmp_dirty_idx,
776 (void (*)(void *, void *, int))swap_dirty_idx);
777 dbg_find("found %d dirty index LEBs", c->dirty_idx.cnt);
778 if (c->dirty_idx.cnt)
779 dbg_find("dirtiest index LEB is %d with dirty %d and free %d",
780 c->dirty_idx.arr[c->dirty_idx.cnt - 1]->lnum,
781 c->dirty_idx.arr[c->dirty_idx.cnt - 1]->dirty,
782 c->dirty_idx.arr[c->dirty_idx.cnt - 1]->free);
783
784 for (i = 0; i < c->dirty_idx.cnt; i++)
785 c->dirty_idx.arr[i] = (void *)(size_t)c->dirty_idx.arr[i]->lnum;
786 ubifs_release_lprops(c);
787 return 0;
788}
789
790
791
792
793
794
795
796
797
798
799
800
801
802static int scan_dirty_idx_cb(struct ubifs_info *c,
803 const struct ubifs_lprops *lprops, int in_tree,
804 struct scan_data *data)
805{
806 int ret = LPT_SCAN_CONTINUE;
807
808
809 if (lprops->flags & LPROPS_TAKEN)
810 return LPT_SCAN_CONTINUE;
811
812 if (!in_tree && valuable(c, lprops))
813 ret |= LPT_SCAN_ADD;
814
815 if (!(lprops->flags & LPROPS_INDEX))
816 return ret;
817
818 if (lprops->free + lprops->dirty < c->min_idx_node_sz)
819 return ret;
820
821 data->lnum = lprops->lnum;
822 return LPT_SCAN_ADD | LPT_SCAN_STOP;
823}
824
825
826
827
828
829
830
831
832
833
834
835static int find_dirty_idx_leb(struct ubifs_info *c)
836{
837 const struct ubifs_lprops *lprops;
838 struct ubifs_lpt_heap *heap;
839 struct scan_data data;
840 int err, i, ret;
841
842
843 data.lnum = -1;
844 heap = &c->lpt_heap[LPROPS_DIRTY_IDX - 1];
845 for (i = 0; i < heap->cnt; i++) {
846 lprops = heap->arr[i];
847 ret = scan_dirty_idx_cb(c, lprops, 1, &data);
848 if (ret & LPT_SCAN_STOP)
849 goto found;
850 }
851 list_for_each_entry(lprops, &c->frdi_idx_list, list) {
852 ret = scan_dirty_idx_cb(c, lprops, 1, &data);
853 if (ret & LPT_SCAN_STOP)
854 goto found;
855 }
856 list_for_each_entry(lprops, &c->uncat_list, list) {
857 ret = scan_dirty_idx_cb(c, lprops, 1, &data);
858 if (ret & LPT_SCAN_STOP)
859 goto found;
860 }
861 if (c->pnodes_have >= c->pnode_cnt)
862
863 return -ENOSPC;
864 err = ubifs_lpt_scan_nolock(c, -1, c->lscan_lnum,
865 (ubifs_lpt_scan_callback)scan_dirty_idx_cb,
866 &data);
867 if (err)
868 return err;
869found:
870 ubifs_assert(c, data.lnum >= c->main_first && data.lnum < c->leb_cnt);
871 c->lscan_lnum = data.lnum;
872 lprops = ubifs_lpt_lookup_dirty(c, data.lnum);
873 if (IS_ERR(lprops))
874 return PTR_ERR(lprops);
875 ubifs_assert(c, lprops->lnum == data.lnum);
876 ubifs_assert(c, lprops->free + lprops->dirty >= c->min_idx_node_sz);
877 ubifs_assert(c, !(lprops->flags & LPROPS_TAKEN));
878 ubifs_assert(c, (lprops->flags & LPROPS_INDEX));
879
880 dbg_find("found dirty LEB %d, free %d, dirty %d, flags %#x",
881 lprops->lnum, lprops->free, lprops->dirty, lprops->flags);
882
883 lprops = ubifs_change_lp(c, lprops, LPROPS_NC, LPROPS_NC,
884 lprops->flags | LPROPS_TAKEN, 0);
885 if (IS_ERR(lprops))
886 return PTR_ERR(lprops);
887
888 return lprops->lnum;
889}
890
891
892
893
894
895static int get_idx_gc_leb(struct ubifs_info *c)
896{
897 const struct ubifs_lprops *lp;
898 int err, lnum;
899
900 err = ubifs_get_idx_gc_leb(c);
901 if (err < 0)
902 return err;
903 lnum = err;
904
905
906
907
908 lp = ubifs_lpt_lookup_dirty(c, lnum);
909 if (IS_ERR(lp))
910 return PTR_ERR(lp);
911 lp = ubifs_change_lp(c, lp, LPROPS_NC, LPROPS_NC,
912 lp->flags | LPROPS_INDEX, -1);
913 if (IS_ERR(lp))
914 return PTR_ERR(lp);
915 dbg_find("LEB %d, dirty %d and free %d flags %#x",
916 lp->lnum, lp->dirty, lp->free, lp->flags);
917 return lnum;
918}
919
920
921
922
923
924static int find_dirtiest_idx_leb(struct ubifs_info *c)
925{
926 const struct ubifs_lprops *lp;
927 int lnum;
928
929 while (1) {
930 if (!c->dirty_idx.cnt)
931 return -ENOSPC;
932
933 lnum = (size_t)c->dirty_idx.arr[--c->dirty_idx.cnt];
934 lp = ubifs_lpt_lookup(c, lnum);
935 if (IS_ERR(lp))
936 return PTR_ERR(lp);
937 if ((lp->flags & LPROPS_TAKEN) || !(lp->flags & LPROPS_INDEX))
938 continue;
939 lp = ubifs_change_lp(c, lp, LPROPS_NC, LPROPS_NC,
940 lp->flags | LPROPS_TAKEN, 0);
941 if (IS_ERR(lp))
942 return PTR_ERR(lp);
943 break;
944 }
945 dbg_find("LEB %d, dirty %d and free %d flags %#x", lp->lnum, lp->dirty,
946 lp->free, lp->flags);
947 ubifs_assert(c, lp->flags & LPROPS_TAKEN);
948 ubifs_assert(c, lp->flags & LPROPS_INDEX);
949 return lnum;
950}
951
952
953
954
955
956
957
958
959
960int ubifs_find_dirty_idx_leb(struct ubifs_info *c)
961{
962 int err;
963
964 ubifs_get_lprops(c);
965
966
967
968
969
970 err = find_dirtiest_idx_leb(c);
971
972
973 if (err == -ENOSPC)
974 err = find_dirty_idx_leb(c);
975
976
977 if (err == -ENOSPC)
978 err = get_idx_gc_leb(c);
979
980 ubifs_release_lprops(c);
981 return err;
982}
983