Lines Matching +full:- +full:c

1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright (C) 2006-2008 Nokia Corporation.
22 * get_heap_comp_val - get the LEB properties value for heap comparisons.
30 return lprops->free; in get_heap_comp_val()
32 return lprops->free + lprops->dirty; in get_heap_comp_val()
34 return lprops->dirty; in get_heap_comp_val()
39 * move_up_lpt_heap - move a new heap entry up as far as possible.
40 * @c: UBIFS file-system description object
50 static void move_up_lpt_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, in move_up_lpt_heap() argument
55 hpos = lprops->hpos; in move_up_lpt_heap()
61 int ppos = (hpos - 1) / 2; in move_up_lpt_heap()
63 val2 = get_heap_comp_val(heap->arr[ppos], cat); in move_up_lpt_heap()
67 heap->arr[ppos]->hpos = hpos; in move_up_lpt_heap()
68 heap->arr[hpos] = heap->arr[ppos]; in move_up_lpt_heap()
69 heap->arr[ppos] = lprops; in move_up_lpt_heap()
70 lprops->hpos = ppos; in move_up_lpt_heap()
76 * adjust_lpt_heap - move a changed heap entry up or down the heap.
77 * @c: UBIFS file-system description object
87 static void adjust_lpt_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, in adjust_lpt_heap() argument
95 int ppos = (hpos - 1) / 2; in adjust_lpt_heap()
97 val2 = get_heap_comp_val(heap->arr[ppos], cat); in adjust_lpt_heap()
101 heap->arr[ppos]->hpos = hpos; in adjust_lpt_heap()
102 heap->arr[hpos] = heap->arr[ppos]; in adjust_lpt_heap()
103 heap->arr[ppos] = lprops; in adjust_lpt_heap()
104 lprops->hpos = ppos; in adjust_lpt_heap()
108 ppos = (hpos - 1) / 2; in adjust_lpt_heap()
109 val2 = get_heap_comp_val(heap->arr[ppos], cat); in adjust_lpt_heap()
121 if (cpos >= heap->cnt) in adjust_lpt_heap()
123 val2 = get_heap_comp_val(heap->arr[cpos], cat); in adjust_lpt_heap()
126 if (cpos + 1 < heap->cnt) { in adjust_lpt_heap()
127 val3 = get_heap_comp_val(heap->arr[cpos + 1], in adjust_lpt_heap()
132 heap->arr[cpos]->hpos = hpos; in adjust_lpt_heap()
133 heap->arr[hpos] = heap->arr[cpos]; in adjust_lpt_heap()
134 heap->arr[cpos] = lprops; in adjust_lpt_heap()
135 lprops->hpos = cpos; in adjust_lpt_heap()
141 if (cpos >= heap->cnt) in adjust_lpt_heap()
143 val3 = get_heap_comp_val(heap->arr[cpos], cat); in adjust_lpt_heap()
146 heap->arr[cpos]->hpos = hpos; in adjust_lpt_heap()
147 heap->arr[hpos] = heap->arr[cpos]; in adjust_lpt_heap()
148 heap->arr[cpos] = lprops; in adjust_lpt_heap()
149 lprops->hpos = cpos; in adjust_lpt_heap()
158 * add_to_lpt_heap - add LEB properties to a LEB category heap.
159 * @c: UBIFS file-system description object
166 static int add_to_lpt_heap(struct ubifs_info *c, struct ubifs_lprops *lprops, in add_to_lpt_heap() argument
169 struct ubifs_lpt_heap *heap = &c->lpt_heap[cat - 1]; in add_to_lpt_heap()
171 if (heap->cnt >= heap->max_cnt) { in add_to_lpt_heap()
172 const int b = LPT_HEAP_SZ / 2 - 1; in add_to_lpt_heap()
178 ubifs_assert(c, cpos >= b); in add_to_lpt_heap()
179 ubifs_assert(c, cpos < LPT_HEAP_SZ); in add_to_lpt_heap()
180 ubifs_assert(c, cpos < heap->cnt); in add_to_lpt_heap()
183 val2 = get_heap_comp_val(heap->arr[cpos], cat); in add_to_lpt_heap()
187 lp = heap->arr[cpos]; in add_to_lpt_heap()
188 lp->flags &= ~LPROPS_CAT_MASK; in add_to_lpt_heap()
189 lp->flags |= LPROPS_UNCAT; in add_to_lpt_heap()
190 list_add(&lp->list, &c->uncat_list); in add_to_lpt_heap()
191 lprops->hpos = cpos; in add_to_lpt_heap()
192 heap->arr[cpos] = lprops; in add_to_lpt_heap()
193 move_up_lpt_heap(c, heap, lprops, cat); in add_to_lpt_heap()
194 dbg_check_heap(c, heap, cat, lprops->hpos); in add_to_lpt_heap()
197 dbg_check_heap(c, heap, cat, -1); in add_to_lpt_heap()
200 lprops->hpos = heap->cnt++; in add_to_lpt_heap()
201 heap->arr[lprops->hpos] = lprops; in add_to_lpt_heap()
202 move_up_lpt_heap(c, heap, lprops, cat); in add_to_lpt_heap()
203 dbg_check_heap(c, heap, cat, lprops->hpos); in add_to_lpt_heap()
209 * remove_from_lpt_heap - remove LEB properties from a LEB category heap.
210 * @c: UBIFS file-system description object
214 static void remove_from_lpt_heap(struct ubifs_info *c, in remove_from_lpt_heap() argument
218 int hpos = lprops->hpos; in remove_from_lpt_heap()
220 heap = &c->lpt_heap[cat - 1]; in remove_from_lpt_heap()
221 ubifs_assert(c, hpos >= 0 && hpos < heap->cnt); in remove_from_lpt_heap()
222 ubifs_assert(c, heap->arr[hpos] == lprops); in remove_from_lpt_heap()
223 heap->cnt -= 1; in remove_from_lpt_heap()
224 if (hpos < heap->cnt) { in remove_from_lpt_heap()
225 heap->arr[hpos] = heap->arr[heap->cnt]; in remove_from_lpt_heap()
226 heap->arr[hpos]->hpos = hpos; in remove_from_lpt_heap()
227 adjust_lpt_heap(c, heap, heap->arr[hpos], hpos, cat); in remove_from_lpt_heap()
229 dbg_check_heap(c, heap, cat, -1); in remove_from_lpt_heap()
233 * lpt_heap_replace - replace lprops in a category heap.
234 * @c: UBIFS file-system description object
243 static void lpt_heap_replace(struct ubifs_info *c, in lpt_heap_replace() argument
247 int hpos = new_lprops->hpos; in lpt_heap_replace()
249 heap = &c->lpt_heap[cat - 1]; in lpt_heap_replace()
250 heap->arr[hpos] = new_lprops; in lpt_heap_replace()
254 * ubifs_add_to_cat - add LEB properties to a category list or heap.
255 * @c: UBIFS file-system description object
261 void ubifs_add_to_cat(struct ubifs_info *c, struct ubifs_lprops *lprops, in ubifs_add_to_cat() argument
268 if (add_to_lpt_heap(c, lprops, cat)) in ubifs_add_to_cat()
270 /* No more room on heap so make it un-categorized */ in ubifs_add_to_cat()
274 list_add(&lprops->list, &c->uncat_list); in ubifs_add_to_cat()
277 list_add(&lprops->list, &c->empty_list); in ubifs_add_to_cat()
280 list_add(&lprops->list, &c->freeable_list); in ubifs_add_to_cat()
281 c->freeable_cnt += 1; in ubifs_add_to_cat()
284 list_add(&lprops->list, &c->frdi_idx_list); in ubifs_add_to_cat()
287 ubifs_assert(c, 0); in ubifs_add_to_cat()
290 lprops->flags &= ~LPROPS_CAT_MASK; in ubifs_add_to_cat()
291 lprops->flags |= cat; in ubifs_add_to_cat()
292 c->in_a_category_cnt += 1; in ubifs_add_to_cat()
293 ubifs_assert(c, c->in_a_category_cnt <= c->main_lebs); in ubifs_add_to_cat()
297 * ubifs_remove_from_cat - remove LEB properties from a category list or heap.
298 * @c: UBIFS file-system description object
304 static void ubifs_remove_from_cat(struct ubifs_info *c, in ubifs_remove_from_cat() argument
311 remove_from_lpt_heap(c, lprops, cat); in ubifs_remove_from_cat()
314 c->freeable_cnt -= 1; in ubifs_remove_from_cat()
315 ubifs_assert(c, c->freeable_cnt >= 0); in ubifs_remove_from_cat()
320 ubifs_assert(c, !list_empty(&lprops->list)); in ubifs_remove_from_cat()
321 list_del(&lprops->list); in ubifs_remove_from_cat()
324 ubifs_assert(c, 0); in ubifs_remove_from_cat()
327 c->in_a_category_cnt -= 1; in ubifs_remove_from_cat()
328 ubifs_assert(c, c->in_a_category_cnt >= 0); in ubifs_remove_from_cat()
332 * ubifs_replace_cat - replace lprops in a category list or heap.
333 * @c: UBIFS file-system description object
341 void ubifs_replace_cat(struct ubifs_info *c, struct ubifs_lprops *old_lprops, in ubifs_replace_cat() argument
346 cat = new_lprops->flags & LPROPS_CAT_MASK; in ubifs_replace_cat()
351 lpt_heap_replace(c, new_lprops, cat); in ubifs_replace_cat()
357 list_replace(&old_lprops->list, &new_lprops->list); in ubifs_replace_cat()
360 ubifs_assert(c, 0); in ubifs_replace_cat()
365 * ubifs_ensure_cat - ensure LEB properties are categorized.
366 * @c: UBIFS file-system description object
370 * un-categorized even though it has enough space for us now. If that is the
373 void ubifs_ensure_cat(struct ubifs_info *c, struct ubifs_lprops *lprops) in ubifs_ensure_cat() argument
375 int cat = lprops->flags & LPROPS_CAT_MASK; in ubifs_ensure_cat()
379 cat = ubifs_categorize_lprops(c, lprops); in ubifs_ensure_cat()
382 ubifs_remove_from_cat(c, lprops, LPROPS_UNCAT); in ubifs_ensure_cat()
383 ubifs_add_to_cat(c, lprops, cat); in ubifs_ensure_cat()
387 * ubifs_categorize_lprops - categorize LEB properties.
388 * @c: UBIFS file-system description object
396 int ubifs_categorize_lprops(const struct ubifs_info *c, in ubifs_categorize_lprops() argument
399 if (lprops->flags & LPROPS_TAKEN) in ubifs_categorize_lprops()
402 if (lprops->free == c->leb_size) { in ubifs_categorize_lprops()
403 ubifs_assert(c, !(lprops->flags & LPROPS_INDEX)); in ubifs_categorize_lprops()
407 if (lprops->free + lprops->dirty == c->leb_size) { in ubifs_categorize_lprops()
408 if (lprops->flags & LPROPS_INDEX) in ubifs_categorize_lprops()
414 if (lprops->flags & LPROPS_INDEX) { in ubifs_categorize_lprops()
415 if (lprops->dirty + lprops->free >= c->min_idx_node_sz) in ubifs_categorize_lprops()
418 if (lprops->dirty >= c->dead_wm && in ubifs_categorize_lprops()
419 lprops->dirty > lprops->free) in ubifs_categorize_lprops()
421 if (lprops->free > 0) in ubifs_categorize_lprops()
429 * change_category - change LEB properties category.
430 * @c: UBIFS file-system description object
431 * @lprops: LEB properties to re-categorize
434 * properties change they must be re-categorized.
436 static void change_category(struct ubifs_info *c, struct ubifs_lprops *lprops) in change_category() argument
438 int old_cat = lprops->flags & LPROPS_CAT_MASK; in change_category()
439 int new_cat = ubifs_categorize_lprops(c, lprops); in change_category()
447 heap = &c->lpt_heap[new_cat - 1]; in change_category()
448 adjust_lpt_heap(c, heap, lprops, lprops->hpos, new_cat); in change_category()
450 ubifs_remove_from_cat(c, lprops, old_cat); in change_category()
451 ubifs_add_to_cat(c, lprops, new_cat); in change_category()
456 * ubifs_calc_dark - calculate LEB dark space size.
457 * @c: the UBIFS file-system description object
467 int ubifs_calc_dark(const struct ubifs_info *c, int spc) in ubifs_calc_dark() argument
469 ubifs_assert(c, !(spc & 7)); in ubifs_calc_dark()
471 if (spc < c->dark_wm) in ubifs_calc_dark()
479 if (spc - c->dark_wm < MIN_WRITE_SZ) in ubifs_calc_dark()
480 return spc - MIN_WRITE_SZ; in ubifs_calc_dark()
482 return c->dark_wm; in ubifs_calc_dark()
486 * is_lprops_dirty - determine if LEB properties are dirty.
487 * @c: the UBIFS file-system description object
490 static int is_lprops_dirty(struct ubifs_info *c, struct ubifs_lprops *lprops) in is_lprops_dirty() argument
495 pos = (lprops->lnum - c->main_first) & (UBIFS_LPT_FANOUT - 1); in is_lprops_dirty()
496 pnode = (struct ubifs_pnode *)container_of(lprops - pos, in is_lprops_dirty()
499 return !test_bit(COW_CNODE, &pnode->flags) && in is_lprops_dirty()
500 test_bit(DIRTY_CNODE, &pnode->flags); in is_lprops_dirty()
504 * ubifs_change_lp - change LEB properties.
505 * @c: the UBIFS file-system description object
520 const struct ubifs_lprops *ubifs_change_lp(struct ubifs_info *c, in ubifs_change_lp() argument
532 lprops->lnum, free, dirty, flags); in ubifs_change_lp()
534 ubifs_assert(c, mutex_is_locked(&c->lp_mutex)); in ubifs_change_lp()
535 ubifs_assert(c, c->lst.empty_lebs >= 0 && in ubifs_change_lp()
536 c->lst.empty_lebs <= c->main_lebs); in ubifs_change_lp()
537 ubifs_assert(c, c->freeable_cnt >= 0); in ubifs_change_lp()
538 ubifs_assert(c, c->freeable_cnt <= c->main_lebs); in ubifs_change_lp()
539 ubifs_assert(c, c->lst.taken_empty_lebs >= 0); in ubifs_change_lp()
540 ubifs_assert(c, c->lst.taken_empty_lebs <= c->lst.empty_lebs); in ubifs_change_lp()
541 ubifs_assert(c, !(c->lst.total_free & 7) && !(c->lst.total_dirty & 7)); in ubifs_change_lp()
542 ubifs_assert(c, !(c->lst.total_dead & 7) && !(c->lst.total_dark & 7)); in ubifs_change_lp()
543 ubifs_assert(c, !(c->lst.total_used & 7)); in ubifs_change_lp()
544 ubifs_assert(c, free == LPROPS_NC || free >= 0); in ubifs_change_lp()
545 ubifs_assert(c, dirty == LPROPS_NC || dirty >= 0); in ubifs_change_lp()
547 if (!is_lprops_dirty(c, lprops)) { in ubifs_change_lp()
548 lprops = ubifs_lpt_lookup_dirty(c, lprops->lnum); in ubifs_change_lp()
552 ubifs_assert(c, lprops == ubifs_lpt_lookup_dirty(c, lprops->lnum)); in ubifs_change_lp()
554 ubifs_assert(c, !(lprops->free & 7) && !(lprops->dirty & 7)); in ubifs_change_lp()
556 spin_lock(&c->space_lock); in ubifs_change_lp()
557 if ((lprops->flags & LPROPS_TAKEN) && lprops->free == c->leb_size) in ubifs_change_lp()
558 c->lst.taken_empty_lebs -= 1; in ubifs_change_lp()
560 if (!(lprops->flags & LPROPS_INDEX)) { in ubifs_change_lp()
563 old_spc = lprops->free + lprops->dirty; in ubifs_change_lp()
564 if (old_spc < c->dead_wm) in ubifs_change_lp()
565 c->lst.total_dead -= old_spc; in ubifs_change_lp()
567 c->lst.total_dark -= ubifs_calc_dark(c, old_spc); in ubifs_change_lp()
569 c->lst.total_used -= c->leb_size - old_spc; in ubifs_change_lp()
574 c->lst.total_free += free - lprops->free; in ubifs_change_lp()
577 if (free == c->leb_size) { in ubifs_change_lp()
578 if (lprops->free != c->leb_size) in ubifs_change_lp()
579 c->lst.empty_lebs += 1; in ubifs_change_lp()
580 } else if (lprops->free == c->leb_size) in ubifs_change_lp()
581 c->lst.empty_lebs -= 1; in ubifs_change_lp()
582 lprops->free = free; in ubifs_change_lp()
587 c->lst.total_dirty += dirty - lprops->dirty; in ubifs_change_lp()
588 lprops->dirty = dirty; in ubifs_change_lp()
593 if ((lprops->flags & LPROPS_INDEX)) { in ubifs_change_lp()
595 c->lst.idx_lebs -= 1; in ubifs_change_lp()
597 c->lst.idx_lebs += 1; in ubifs_change_lp()
598 lprops->flags = flags; in ubifs_change_lp()
601 if (!(lprops->flags & LPROPS_INDEX)) { in ubifs_change_lp()
604 new_spc = lprops->free + lprops->dirty; in ubifs_change_lp()
605 if (new_spc < c->dead_wm) in ubifs_change_lp()
606 c->lst.total_dead += new_spc; in ubifs_change_lp()
608 c->lst.total_dark += ubifs_calc_dark(c, new_spc); in ubifs_change_lp()
610 c->lst.total_used += c->leb_size - new_spc; in ubifs_change_lp()
613 if ((lprops->flags & LPROPS_TAKEN) && lprops->free == c->leb_size) in ubifs_change_lp()
614 c->lst.taken_empty_lebs += 1; in ubifs_change_lp()
616 change_category(c, lprops); in ubifs_change_lp()
617 c->idx_gc_cnt += idx_gc_cnt; in ubifs_change_lp()
618 spin_unlock(&c->space_lock); in ubifs_change_lp()
623 * ubifs_get_lp_stats - get lprops statistics.
624 * @c: UBIFS file-system description object
627 void ubifs_get_lp_stats(struct ubifs_info *c, struct ubifs_lp_stats *lst) in ubifs_get_lp_stats() argument
629 spin_lock(&c->space_lock); in ubifs_get_lp_stats()
630 memcpy(lst, &c->lst, sizeof(struct ubifs_lp_stats)); in ubifs_get_lp_stats()
631 spin_unlock(&c->space_lock); in ubifs_get_lp_stats()
635 * ubifs_change_one_lp - change LEB properties.
636 * @c: the UBIFS file-system description object
649 int ubifs_change_one_lp(struct ubifs_info *c, int lnum, int free, int dirty, in ubifs_change_one_lp() argument
655 ubifs_get_lprops(c); in ubifs_change_one_lp()
657 lp = ubifs_lpt_lookup_dirty(c, lnum); in ubifs_change_one_lp()
663 flags = (lp->flags | flags_set) & ~flags_clean; in ubifs_change_one_lp()
664 lp = ubifs_change_lp(c, lp, free, dirty, flags, idx_gc_cnt); in ubifs_change_one_lp()
669 ubifs_release_lprops(c); in ubifs_change_one_lp()
671 ubifs_err(c, "cannot change properties of LEB %d, error %d", in ubifs_change_one_lp()
677 * ubifs_update_one_lp - update LEB properties.
678 * @c: the UBIFS file-system description object
688 int ubifs_update_one_lp(struct ubifs_info *c, int lnum, int free, int dirty, in ubifs_update_one_lp() argument
694 ubifs_get_lprops(c); in ubifs_update_one_lp()
696 lp = ubifs_lpt_lookup_dirty(c, lnum); in ubifs_update_one_lp()
702 flags = (lp->flags | flags_set) & ~flags_clean; in ubifs_update_one_lp()
703 lp = ubifs_change_lp(c, lp, free, lp->dirty + dirty, flags, 0); in ubifs_update_one_lp()
708 ubifs_release_lprops(c); in ubifs_update_one_lp()
710 ubifs_err(c, "cannot update properties of LEB %d, error %d", in ubifs_update_one_lp()
716 * ubifs_read_one_lp - read LEB properties.
717 * @c: the UBIFS file-system description object
725 int ubifs_read_one_lp(struct ubifs_info *c, int lnum, struct ubifs_lprops *lp) in ubifs_read_one_lp() argument
730 ubifs_get_lprops(c); in ubifs_read_one_lp()
732 lpp = ubifs_lpt_lookup(c, lnum); in ubifs_read_one_lp()
735 ubifs_err(c, "cannot read properties of LEB %d, error %d", in ubifs_read_one_lp()
743 ubifs_release_lprops(c); in ubifs_read_one_lp()
748 * ubifs_fast_find_free - try to find a LEB with free space quickly.
749 * @c: the UBIFS file-system description object
754 const struct ubifs_lprops *ubifs_fast_find_free(struct ubifs_info *c) in ubifs_fast_find_free() argument
759 ubifs_assert(c, mutex_is_locked(&c->lp_mutex)); in ubifs_fast_find_free()
761 heap = &c->lpt_heap[LPROPS_FREE - 1]; in ubifs_fast_find_free()
762 if (heap->cnt == 0) in ubifs_fast_find_free()
765 lprops = heap->arr[0]; in ubifs_fast_find_free()
766 ubifs_assert(c, !(lprops->flags & LPROPS_TAKEN)); in ubifs_fast_find_free()
767 ubifs_assert(c, !(lprops->flags & LPROPS_INDEX)); in ubifs_fast_find_free()
772 * ubifs_fast_find_empty - try to find an empty LEB quickly.
773 * @c: the UBIFS file-system description object
778 const struct ubifs_lprops *ubifs_fast_find_empty(struct ubifs_info *c) in ubifs_fast_find_empty() argument
782 ubifs_assert(c, mutex_is_locked(&c->lp_mutex)); in ubifs_fast_find_empty()
784 if (list_empty(&c->empty_list)) in ubifs_fast_find_empty()
787 lprops = list_entry(c->empty_list.next, struct ubifs_lprops, list); in ubifs_fast_find_empty()
788 ubifs_assert(c, !(lprops->flags & LPROPS_TAKEN)); in ubifs_fast_find_empty()
789 ubifs_assert(c, !(lprops->flags & LPROPS_INDEX)); in ubifs_fast_find_empty()
790 ubifs_assert(c, lprops->free == c->leb_size); in ubifs_fast_find_empty()
795 * ubifs_fast_find_freeable - try to find a freeable LEB quickly.
796 * @c: the UBIFS file-system description object
801 const struct ubifs_lprops *ubifs_fast_find_freeable(struct ubifs_info *c) in ubifs_fast_find_freeable() argument
805 ubifs_assert(c, mutex_is_locked(&c->lp_mutex)); in ubifs_fast_find_freeable()
807 if (list_empty(&c->freeable_list)) in ubifs_fast_find_freeable()
810 lprops = list_entry(c->freeable_list.next, struct ubifs_lprops, list); in ubifs_fast_find_freeable()
811 ubifs_assert(c, !(lprops->flags & LPROPS_TAKEN)); in ubifs_fast_find_freeable()
812 ubifs_assert(c, !(lprops->flags & LPROPS_INDEX)); in ubifs_fast_find_freeable()
813 ubifs_assert(c, lprops->free + lprops->dirty == c->leb_size); in ubifs_fast_find_freeable()
814 ubifs_assert(c, c->freeable_cnt > 0); in ubifs_fast_find_freeable()
819 * ubifs_fast_find_frdi_idx - try to find a freeable index LEB quickly.
820 * @c: the UBIFS file-system description object
825 const struct ubifs_lprops *ubifs_fast_find_frdi_idx(struct ubifs_info *c) in ubifs_fast_find_frdi_idx() argument
829 ubifs_assert(c, mutex_is_locked(&c->lp_mutex)); in ubifs_fast_find_frdi_idx()
831 if (list_empty(&c->frdi_idx_list)) in ubifs_fast_find_frdi_idx()
834 lprops = list_entry(c->frdi_idx_list.next, struct ubifs_lprops, list); in ubifs_fast_find_frdi_idx()
835 ubifs_assert(c, !(lprops->flags & LPROPS_TAKEN)); in ubifs_fast_find_frdi_idx()
836 ubifs_assert(c, (lprops->flags & LPROPS_INDEX)); in ubifs_fast_find_frdi_idx()
837 ubifs_assert(c, lprops->free + lprops->dirty == c->leb_size); in ubifs_fast_find_frdi_idx()
846 * dbg_check_cats - check category heaps and lists.
847 * @c: UBIFS file-system description object
851 int dbg_check_cats(struct ubifs_info *c) in dbg_check_cats() argument
857 if (!dbg_is_chk_gen(c) && !dbg_is_chk_lprops(c)) in dbg_check_cats()
860 list_for_each_entry(lprops, &c->empty_list, list) { in dbg_check_cats()
861 if (lprops->free != c->leb_size) { in dbg_check_cats()
862 ubifs_err(c, "non-empty LEB %d on empty list (free %d dirty %d flags %d)", in dbg_check_cats()
863 lprops->lnum, lprops->free, lprops->dirty, in dbg_check_cats()
864 lprops->flags); in dbg_check_cats()
865 return -EINVAL; in dbg_check_cats()
867 if (lprops->flags & LPROPS_TAKEN) { in dbg_check_cats()
868 ubifs_err(c, "taken LEB %d on empty list (free %d dirty %d flags %d)", in dbg_check_cats()
869 lprops->lnum, lprops->free, lprops->dirty, in dbg_check_cats()
870 lprops->flags); in dbg_check_cats()
871 return -EINVAL; in dbg_check_cats()
876 list_for_each_entry(lprops, &c->freeable_list, list) { in dbg_check_cats()
877 if (lprops->free + lprops->dirty != c->leb_size) { in dbg_check_cats()
878 ubifs_err(c, "non-freeable LEB %d on freeable list (free %d dirty %d flags %d)", in dbg_check_cats()
879 lprops->lnum, lprops->free, lprops->dirty, in dbg_check_cats()
880 lprops->flags); in dbg_check_cats()
881 return -EINVAL; in dbg_check_cats()
883 if (lprops->flags & LPROPS_TAKEN) { in dbg_check_cats()
884 ubifs_err(c, "taken LEB %d on freeable list (free %d dirty %d flags %d)", in dbg_check_cats()
885 lprops->lnum, lprops->free, lprops->dirty, in dbg_check_cats()
886 lprops->flags); in dbg_check_cats()
887 return -EINVAL; in dbg_check_cats()
891 if (i != c->freeable_cnt) { in dbg_check_cats()
892 ubifs_err(c, "freeable list count %d expected %d", i, in dbg_check_cats()
893 c->freeable_cnt); in dbg_check_cats()
894 return -EINVAL; in dbg_check_cats()
898 list_for_each(pos, &c->idx_gc) in dbg_check_cats()
900 if (i != c->idx_gc_cnt) { in dbg_check_cats()
901 ubifs_err(c, "idx_gc list count %d expected %d", i, in dbg_check_cats()
902 c->idx_gc_cnt); in dbg_check_cats()
903 return -EINVAL; in dbg_check_cats()
906 list_for_each_entry(lprops, &c->frdi_idx_list, list) { in dbg_check_cats()
907 if (lprops->free + lprops->dirty != c->leb_size) { in dbg_check_cats()
908 ubifs_err(c, "non-freeable LEB %d on frdi_idx list (free %d dirty %d flags %d)", in dbg_check_cats()
909 lprops->lnum, lprops->free, lprops->dirty, in dbg_check_cats()
910 lprops->flags); in dbg_check_cats()
911 return -EINVAL; in dbg_check_cats()
913 if (lprops->flags & LPROPS_TAKEN) { in dbg_check_cats()
914 ubifs_err(c, "taken LEB %d on frdi_idx list (free %d dirty %d flags %d)", in dbg_check_cats()
915 lprops->lnum, lprops->free, lprops->dirty, in dbg_check_cats()
916 lprops->flags); in dbg_check_cats()
917 return -EINVAL; in dbg_check_cats()
919 if (!(lprops->flags & LPROPS_INDEX)) { in dbg_check_cats()
920 ubifs_err(c, "non-index LEB %d on frdi_idx list (free %d dirty %d flags %d)", in dbg_check_cats()
921 lprops->lnum, lprops->free, lprops->dirty, in dbg_check_cats()
922 lprops->flags); in dbg_check_cats()
923 return -EINVAL; in dbg_check_cats()
928 struct ubifs_lpt_heap *heap = &c->lpt_heap[cat - 1]; in dbg_check_cats()
930 for (i = 0; i < heap->cnt; i++) { in dbg_check_cats()
931 lprops = heap->arr[i]; in dbg_check_cats()
933 ubifs_err(c, "null ptr in LPT heap cat %d", cat); in dbg_check_cats()
934 return -EINVAL; in dbg_check_cats()
936 if (lprops->hpos != i) { in dbg_check_cats()
937 ubifs_err(c, "bad ptr in LPT heap cat %d", cat); in dbg_check_cats()
938 return -EINVAL; in dbg_check_cats()
940 if (lprops->flags & LPROPS_TAKEN) { in dbg_check_cats()
941 ubifs_err(c, "taken LEB in LPT heap cat %d", cat); in dbg_check_cats()
942 return -EINVAL; in dbg_check_cats()
950 void dbg_check_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat, in dbg_check_heap() argument
955 if (!dbg_is_chk_gen(c) && !dbg_is_chk_lprops(c)) in dbg_check_heap()
958 for (i = 0; i < heap->cnt; i++) { in dbg_check_heap()
959 struct ubifs_lprops *lprops = heap->arr[i]; in dbg_check_heap()
963 if ((lprops->flags & LPROPS_CAT_MASK) != cat) { in dbg_check_heap()
967 if (lprops->hpos != i) { in dbg_check_heap()
971 lp = ubifs_lpt_lookup(c, lprops->lnum); in dbg_check_heap()
977 ubifs_err(c, "lprops %zx lp %zx lprops->lnum %d lp->lnum %d", in dbg_check_heap()
978 (size_t)lprops, (size_t)lp, lprops->lnum, in dbg_check_heap()
979 lp->lnum); in dbg_check_heap()
984 lp = heap->arr[j]; in dbg_check_heap()
989 if (lp->lnum == lprops->lnum) { in dbg_check_heap()
997 ubifs_err(c, "failed cat %d hpos %d err %d", cat, i, err); in dbg_check_heap()
999 ubifs_dump_heap(c, heap, cat); in dbg_check_heap()
1004 * scan_check_cb - scan callback.
1005 * @c: the UBIFS file-system description object
1015 static int scan_check_cb(struct ubifs_info *c, in scan_check_cb() argument
1022 int cat, lnum = lp->lnum, is_idx = 0, used = 0, free, dirty, ret; in scan_check_cb()
1025 cat = lp->flags & LPROPS_CAT_MASK; in scan_check_cb()
1027 cat = ubifs_categorize_lprops(c, lp); in scan_check_cb()
1028 if (cat != (lp->flags & LPROPS_CAT_MASK)) { in scan_check_cb()
1029 ubifs_err(c, "bad LEB category %d expected %d", in scan_check_cb()
1030 (lp->flags & LPROPS_CAT_MASK), cat); in scan_check_cb()
1031 return -EINVAL; in scan_check_cb()
1041 list = &c->empty_list; in scan_check_cb()
1044 list = &c->freeable_list; in scan_check_cb()
1047 list = &c->frdi_idx_list; in scan_check_cb()
1050 list = &c->uncat_list; in scan_check_cb()
1064 ubifs_err(c, "bad LPT list (category %d)", cat); in scan_check_cb()
1065 return -EINVAL; in scan_check_cb()
1072 struct ubifs_lpt_heap *heap = &c->lpt_heap[cat - 1]; in scan_check_cb()
1074 if ((lp->hpos != -1 && heap->arr[lp->hpos]->lnum != lnum) || in scan_check_cb()
1075 lp != heap->arr[lp->hpos]) { in scan_check_cb()
1076 ubifs_err(c, "bad LPT heap (category %d)", cat); in scan_check_cb()
1077 return -EINVAL; in scan_check_cb()
1083 * may contain garbage - do not scan them. in scan_check_cb()
1085 if (lp->free == c->leb_size) { in scan_check_cb()
1086 lst->empty_lebs += 1; in scan_check_cb()
1087 lst->total_free += c->leb_size; in scan_check_cb()
1088 lst->total_dark += ubifs_calc_dark(c, c->leb_size); in scan_check_cb()
1091 if (lp->free + lp->dirty == c->leb_size && in scan_check_cb()
1092 !(lp->flags & LPROPS_INDEX)) { in scan_check_cb()
1093 lst->total_free += lp->free; in scan_check_cb()
1094 lst->total_dirty += lp->dirty; in scan_check_cb()
1095 lst->total_dark += ubifs_calc_dark(c, c->leb_size); in scan_check_cb()
1099 buf = __vmalloc(c->leb_size, GFP_NOFS); in scan_check_cb()
1101 return -ENOMEM; in scan_check_cb()
1103 sleb = ubifs_scan(c, lnum, 0, buf, 0); in scan_check_cb()
1106 if (ret == -EUCLEAN) { in scan_check_cb()
1107 ubifs_dump_lprops(c); in scan_check_cb()
1108 ubifs_dump_budg(c, &c->bi); in scan_check_cb()
1113 is_idx = -1; in scan_check_cb()
1114 list_for_each_entry(snod, &sleb->nodes, list) { in scan_check_cb()
1119 if (is_idx == -1) in scan_check_cb()
1120 is_idx = (snod->type == UBIFS_IDX_NODE) ? 1 : 0; in scan_check_cb()
1122 if (is_idx && snod->type != UBIFS_IDX_NODE) { in scan_check_cb()
1123 ubifs_err(c, "indexing node in data LEB %d:%d", in scan_check_cb()
1124 lnum, snod->offs); in scan_check_cb()
1128 if (snod->type == UBIFS_IDX_NODE) { in scan_check_cb()
1129 struct ubifs_idx_node *idx = snod->node; in scan_check_cb()
1131 key_read(c, ubifs_idx_key(c, idx), &snod->key); in scan_check_cb()
1132 level = le16_to_cpu(idx->level); in scan_check_cb()
1135 found = ubifs_tnc_has_node(c, &snod->key, level, lnum, in scan_check_cb()
1136 snod->offs, is_idx); in scan_check_cb()
1140 used += ALIGN(snod->len, 8); in scan_check_cb()
1144 free = c->leb_size - sleb->endpt; in scan_check_cb()
1145 dirty = sleb->endpt - used; in scan_check_cb()
1147 if (free > c->leb_size || free < 0 || dirty > c->leb_size || in scan_check_cb()
1149 ubifs_err(c, "bad calculated accounting for LEB %d: free %d, dirty %d", in scan_check_cb()
1154 if (lp->free + lp->dirty == c->leb_size && in scan_check_cb()
1155 free + dirty == c->leb_size) in scan_check_cb()
1156 if ((is_idx && !(lp->flags & LPROPS_INDEX)) || in scan_check_cb()
1157 (!is_idx && free == c->leb_size) || in scan_check_cb()
1158 lp->free == c->leb_size) { in scan_check_cb()
1166 free = lp->free; in scan_check_cb()
1167 dirty = lp->dirty; in scan_check_cb()
1171 if (is_idx && lp->free + lp->dirty == free + dirty && in scan_check_cb()
1172 lnum != c->ihead_lnum) { in scan_check_cb()
1176 * is because the in-the-gaps method may use free space or in scan_check_cb()
1177 * create free space (as a side-effect of using ubi_leb_change in scan_check_cb()
1181 * write to the free space at the end of an index LEB - except in scan_check_cb()
1182 * by the in-the-gaps method for which it is not a problem. in scan_check_cb()
1184 free = lp->free; in scan_check_cb()
1185 dirty = lp->dirty; in scan_check_cb()
1188 if (lp->free != free || lp->dirty != dirty) in scan_check_cb()
1191 if (is_idx && !(lp->flags & LPROPS_INDEX)) { in scan_check_cb()
1192 if (free == c->leb_size) in scan_check_cb()
1196 ubifs_err(c, "indexing node without indexing flag"); in scan_check_cb()
1201 if (!is_idx && (lp->flags & LPROPS_INDEX)) { in scan_check_cb()
1202 ubifs_err(c, "data node with indexing flag"); in scan_check_cb()
1206 if (free == c->leb_size) in scan_check_cb()
1207 lst->empty_lebs += 1; in scan_check_cb()
1210 lst->idx_lebs += 1; in scan_check_cb()
1212 if (!(lp->flags & LPROPS_INDEX)) in scan_check_cb()
1213 lst->total_used += c->leb_size - free - dirty; in scan_check_cb()
1214 lst->total_free += free; in scan_check_cb()
1215 lst->total_dirty += dirty; in scan_check_cb()
1217 if (!(lp->flags & LPROPS_INDEX)) { in scan_check_cb()
1220 if (spc < c->dead_wm) in scan_check_cb()
1221 lst->total_dead += spc; in scan_check_cb()
1223 lst->total_dark += ubifs_calc_dark(c, spc); in scan_check_cb()
1231 ubifs_err(c, "bad accounting of LEB %d: free %d, dirty %d flags %#x, should be free %d, dirty %d", in scan_check_cb()
1232 lnum, lp->free, lp->dirty, lp->flags, free, dirty); in scan_check_cb()
1233 ubifs_dump_leb(c, lnum); in scan_check_cb()
1236 ret = -EINVAL; in scan_check_cb()
1243 * dbg_check_lprops - check all LEB properties.
1244 * @c: UBIFS file-system description object
1247 * It returns zero if everything is fine, %-EINVAL if there is an inconsistency
1253 int dbg_check_lprops(struct ubifs_info *c) in dbg_check_lprops() argument
1258 if (!dbg_is_chk_lprops(c)) in dbg_check_lprops()
1265 for (i = 0; i < c->jhead_cnt; i++) { in dbg_check_lprops()
1266 err = ubifs_wbuf_sync(&c->jheads[i].wbuf); in dbg_check_lprops()
1272 err = ubifs_lpt_scan_nolock(c, c->main_first, c->leb_cnt - 1, in dbg_check_lprops()
1274 if (err && err != -ENOSPC) in dbg_check_lprops()
1277 if (lst.empty_lebs != c->lst.empty_lebs || in dbg_check_lprops()
1278 lst.idx_lebs != c->lst.idx_lebs || in dbg_check_lprops()
1279 lst.total_free != c->lst.total_free || in dbg_check_lprops()
1280 lst.total_dirty != c->lst.total_dirty || in dbg_check_lprops()
1281 lst.total_used != c->lst.total_used) { in dbg_check_lprops()
1282 ubifs_err(c, "bad overall accounting"); in dbg_check_lprops()
1283 …ubifs_err(c, "calculated: empty_lebs %d, idx_lebs %d, total_free %lld, total_dirty %lld, total_use… in dbg_check_lprops()
1286 …ubifs_err(c, "read from lprops: empty_lebs %d, idx_lebs %d, total_free %lld, total_dirty %lld, tot… in dbg_check_lprops()
1287 c->lst.empty_lebs, c->lst.idx_lebs, c->lst.total_free, in dbg_check_lprops()
1288 c->lst.total_dirty, c->lst.total_used); in dbg_check_lprops()
1289 err = -EINVAL; in dbg_check_lprops()
1293 if (lst.total_dead != c->lst.total_dead || in dbg_check_lprops()
1294 lst.total_dark != c->lst.total_dark) { in dbg_check_lprops()
1295 ubifs_err(c, "bad dead/dark space accounting"); in dbg_check_lprops()
1296 ubifs_err(c, "calculated: total_dead %lld, total_dark %lld", in dbg_check_lprops()
1298 ubifs_err(c, "read from lprops: total_dead %lld, total_dark %lld", in dbg_check_lprops()
1299 c->lst.total_dead, c->lst.total_dark); in dbg_check_lprops()
1300 err = -EINVAL; in dbg_check_lprops()
1304 err = dbg_check_cats(c); in dbg_check_lprops()