1 /* 2 * This file is part of UBIFS. 3 * 4 * Copyright (C) 2006-2008 Nokia Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 as published by 8 * the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 * 15 * You should have received a copy of the GNU General Public License along with 16 * this program; if not, write to the Free Software Foundation, Inc., 51 17 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 * 19 * Authors: Adrian Hunter 20 * Artem Bityutskiy (Битюцкий Артём) 21 */ 22 23 /* 24 * This file implements the functions that access LEB properties and their 25 * categories. LEBs are categorized based on the needs of UBIFS, and the 26 * categories are stored as either heaps or lists to provide a fast way of 27 * finding a LEB in a particular category. For example, UBIFS may need to find 28 * an empty LEB for the journal, or a very dirty LEB for garbage collection. 29 */ 30 31 #include "ubifs.h" 32 33 /** 34 * get_heap_comp_val - get the LEB properties value for heap comparisons. 35 * @lprops: LEB properties 36 * @cat: LEB category 37 */ 38 static int get_heap_comp_val(struct ubifs_lprops *lprops, int cat) 39 { 40 switch (cat) { 41 case LPROPS_FREE: 42 return lprops->free; 43 case LPROPS_DIRTY_IDX: 44 return lprops->free + lprops->dirty; 45 default: 46 return lprops->dirty; 47 } 48 } 49 50 /** 51 * move_up_lpt_heap - move a new heap entry up as far as possible. 52 * @c: UBIFS file-system description object 53 * @heap: LEB category heap 54 * @lprops: LEB properties to move 55 * @cat: LEB category 56 * 57 * New entries to a heap are added at the bottom and then moved up until the 58 * parent's value is greater. In the case of LPT's category heaps, the value 59 * is either the amount of free space or the amount of dirty space, depending 60 * on the category. 61 */ 62 static void move_up_lpt_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, 63 struct ubifs_lprops *lprops, int cat) 64 { 65 int val1, val2, hpos; 66 67 hpos = lprops->hpos; 68 if (!hpos) 69 return; /* Already top of the heap */ 70 val1 = get_heap_comp_val(lprops, cat); 71 /* Compare to parent and, if greater, move up the heap */ 72 do { 73 int ppos = (hpos - 1) / 2; 74 75 val2 = get_heap_comp_val(heap->arr[ppos], cat); 76 if (val2 >= val1) 77 return; 78 /* Greater than parent so move up */ 79 heap->arr[ppos]->hpos = hpos; 80 heap->arr[hpos] = heap->arr[ppos]; 81 heap->arr[ppos] = lprops; 82 lprops->hpos = ppos; 83 hpos = ppos; 84 } while (hpos); 85 } 86 87 /** 88 * adjust_lpt_heap - move a changed heap entry up or down the heap. 89 * @c: UBIFS file-system description object 90 * @heap: LEB category heap 91 * @lprops: LEB properties to move 92 * @hpos: heap position of @lprops 93 * @cat: LEB category 94 * 95 * Changed entries in a heap are moved up or down until the parent's value is 96 * greater. In the case of LPT's category heaps, the value is either the amount 97 * of free space or the amount of dirty space, depending on the category. 98 */ 99 static void adjust_lpt_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, 100 struct ubifs_lprops *lprops, int hpos, int cat) 101 { 102 int val1, val2, val3, cpos; 103 104 val1 = get_heap_comp_val(lprops, cat); 105 /* Compare to parent and, if greater than parent, move up the heap */ 106 if (hpos) { 107 int ppos = (hpos - 1) / 2; 108 109 val2 = get_heap_comp_val(heap->arr[ppos], cat); 110 if (val1 > val2) { 111 /* Greater than parent so move up */ 112 while (1) { 113 heap->arr[ppos]->hpos = hpos; 114 heap->arr[hpos] = heap->arr[ppos]; 115 heap->arr[ppos] = lprops; 116 lprops->hpos = ppos; 117 hpos = ppos; 118 if (!hpos) 119 return; 120 ppos = (hpos - 1) / 2; 121 val2 = get_heap_comp_val(heap->arr[ppos], cat); 122 if (val1 <= val2) 123 return; 124 /* Still greater than parent so keep going */ 125 } 126 } 127 } 128 /* Not greater than parent, so compare to children */ 129 while (1) { 130 /* Compare to left child */ 131 cpos = hpos * 2 + 1; 132 if (cpos >= heap->cnt) 133 return; 134 val2 = get_heap_comp_val(heap->arr[cpos], cat); 135 if (val1 < val2) { 136 /* Less than left child, so promote biggest child */ 137 if (cpos + 1 < heap->cnt) { 138 val3 = get_heap_comp_val(heap->arr[cpos + 1], 139 cat); 140 if (val3 > val2) 141 cpos += 1; /* Right child is bigger */ 142 } 143 heap->arr[cpos]->hpos = hpos; 144 heap->arr[hpos] = heap->arr[cpos]; 145 heap->arr[cpos] = lprops; 146 lprops->hpos = cpos; 147 hpos = cpos; 148 continue; 149 } 150 /* Compare to right child */ 151 cpos += 1; 152 if (cpos >= heap->cnt) 153 return; 154 val3 = get_heap_comp_val(heap->arr[cpos], cat); 155 if (val1 < val3) { 156 /* Less than right child, so promote right child */ 157 heap->arr[cpos]->hpos = hpos; 158 heap->arr[hpos] = heap->arr[cpos]; 159 heap->arr[cpos] = lprops; 160 lprops->hpos = cpos; 161 hpos = cpos; 162 continue; 163 } 164 return; 165 } 166 } 167 168 /** 169 * add_to_lpt_heap - add LEB properties to a LEB category heap. 170 * @c: UBIFS file-system description object 171 * @lprops: LEB properties to add 172 * @cat: LEB category 173 * 174 * This function returns %1 if @lprops is added to the heap for LEB category 175 * @cat, otherwise %0 is returned because the heap is full. 176 */ 177 static int add_to_lpt_heap(struct ubifs_info *c, struct ubifs_lprops *lprops, 178 int cat) 179 { 180 struct ubifs_lpt_heap *heap = &c->lpt_heap[cat - 1]; 181 182 if (heap->cnt >= heap->max_cnt) { 183 const int b = LPT_HEAP_SZ / 2 - 1; 184 int cpos, val1, val2; 185 186 /* Compare to some other LEB on the bottom of heap */ 187 /* Pick a position kind of randomly */ 188 cpos = (((size_t)lprops >> 4) & b) + b; 189 ubifs_assert(cpos >= b); 190 ubifs_assert(cpos < LPT_HEAP_SZ); 191 ubifs_assert(cpos < heap->cnt); 192 193 val1 = get_heap_comp_val(lprops, cat); 194 val2 = get_heap_comp_val(heap->arr[cpos], cat); 195 if (val1 > val2) { 196 struct ubifs_lprops *lp; 197 198 lp = heap->arr[cpos]; 199 lp->flags &= ~LPROPS_CAT_MASK; 200 lp->flags |= LPROPS_UNCAT; 201 list_add(&lp->list, &c->uncat_list); 202 lprops->hpos = cpos; 203 heap->arr[cpos] = lprops; 204 move_up_lpt_heap(c, heap, lprops, cat); 205 dbg_check_heap(c, heap, cat, lprops->hpos); 206 return 1; /* Added to heap */ 207 } 208 dbg_check_heap(c, heap, cat, -1); 209 return 0; /* Not added to heap */ 210 } else { 211 lprops->hpos = heap->cnt++; 212 heap->arr[lprops->hpos] = lprops; 213 move_up_lpt_heap(c, heap, lprops, cat); 214 dbg_check_heap(c, heap, cat, lprops->hpos); 215 return 1; /* Added to heap */ 216 } 217 } 218 219 /** 220 * remove_from_lpt_heap - remove LEB properties from a LEB category heap. 221 * @c: UBIFS file-system description object 222 * @lprops: LEB properties to remove 223 * @cat: LEB category 224 */ 225 static void remove_from_lpt_heap(struct ubifs_info *c, 226 struct ubifs_lprops *lprops, int cat) 227 { 228 struct ubifs_lpt_heap *heap; 229 int hpos = lprops->hpos; 230 231 heap = &c->lpt_heap[cat - 1]; 232 ubifs_assert(hpos >= 0 && hpos < heap->cnt); 233 ubifs_assert(heap->arr[hpos] == lprops); 234 heap->cnt -= 1; 235 if (hpos < heap->cnt) { 236 heap->arr[hpos] = heap->arr[heap->cnt]; 237 heap->arr[hpos]->hpos = hpos; 238 adjust_lpt_heap(c, heap, heap->arr[hpos], hpos, cat); 239 } 240 dbg_check_heap(c, heap, cat, -1); 241 } 242 243 /** 244 * lpt_heap_replace - replace lprops in a category heap. 245 * @c: UBIFS file-system description object 246 * @old_lprops: LEB properties to replace 247 * @new_lprops: LEB properties with which to replace 248 * @cat: LEB category 249 * 250 * During commit it is sometimes necessary to copy a pnode (see dirty_cow_pnode) 251 * and the lprops that the pnode contains. When that happens, references in 252 * the category heaps to those lprops must be updated to point to the new 253 * lprops. This function does that. 254 */ 255 static void lpt_heap_replace(struct ubifs_info *c, 256 struct ubifs_lprops *old_lprops, 257 struct ubifs_lprops *new_lprops, int cat) 258 { 259 struct ubifs_lpt_heap *heap; 260 int hpos = new_lprops->hpos; 261 262 heap = &c->lpt_heap[cat - 1]; 263 heap->arr[hpos] = new_lprops; 264 } 265 266 /** 267 * ubifs_add_to_cat - add LEB properties to a category list or heap. 268 * @c: UBIFS file-system description object 269 * @lprops: LEB properties to add 270 * @cat: LEB category to which to add 271 * 272 * LEB properties are categorized to enable fast find operations. 273 */ 274 void ubifs_add_to_cat(struct ubifs_info *c, struct ubifs_lprops *lprops, 275 int cat) 276 { 277 switch (cat) { 278 case LPROPS_DIRTY: 279 case LPROPS_DIRTY_IDX: 280 case LPROPS_FREE: 281 if (add_to_lpt_heap(c, lprops, cat)) 282 break; 283 /* No more room on heap so make it uncategorized */ 284 cat = LPROPS_UNCAT; 285 /* Fall through */ 286 case LPROPS_UNCAT: 287 list_add(&lprops->list, &c->uncat_list); 288 break; 289 case LPROPS_EMPTY: 290 list_add(&lprops->list, &c->empty_list); 291 break; 292 case LPROPS_FREEABLE: 293 list_add(&lprops->list, &c->freeable_list); 294 c->freeable_cnt += 1; 295 break; 296 case LPROPS_FRDI_IDX: 297 list_add(&lprops->list, &c->frdi_idx_list); 298 break; 299 default: 300 ubifs_assert(0); 301 } 302 lprops->flags &= ~LPROPS_CAT_MASK; 303 lprops->flags |= cat; 304 } 305 306 /** 307 * ubifs_remove_from_cat - remove LEB properties from a category list or heap. 308 * @c: UBIFS file-system description object 309 * @lprops: LEB properties to remove 310 * @cat: LEB category from which to remove 311 * 312 * LEB properties are categorized to enable fast find operations. 313 */ 314 static void ubifs_remove_from_cat(struct ubifs_info *c, 315 struct ubifs_lprops *lprops, int cat) 316 { 317 switch (cat) { 318 case LPROPS_DIRTY: 319 case LPROPS_DIRTY_IDX: 320 case LPROPS_FREE: 321 remove_from_lpt_heap(c, lprops, cat); 322 break; 323 case LPROPS_FREEABLE: 324 c->freeable_cnt -= 1; 325 ubifs_assert(c->freeable_cnt >= 0); 326 /* Fall through */ 327 case LPROPS_UNCAT: 328 case LPROPS_EMPTY: 329 case LPROPS_FRDI_IDX: 330 ubifs_assert(!list_empty(&lprops->list)); 331 list_del(&lprops->list); 332 break; 333 default: 334 ubifs_assert(0); 335 } 336 } 337 338 /** 339 * ubifs_replace_cat - replace lprops in a category list or heap. 340 * @c: UBIFS file-system description object 341 * @old_lprops: LEB properties to replace 342 * @new_lprops: LEB properties with which to replace 343 * 344 * During commit it is sometimes necessary to copy a pnode (see dirty_cow_pnode) 345 * and the lprops that the pnode contains. When that happens, references in 346 * category lists and heaps must be replaced. This function does that. 347 */ 348 void ubifs_replace_cat(struct ubifs_info *c, struct ubifs_lprops *old_lprops, 349 struct ubifs_lprops *new_lprops) 350 { 351 int cat; 352 353 cat = new_lprops->flags & LPROPS_CAT_MASK; 354 switch (cat) { 355 case LPROPS_DIRTY: 356 case LPROPS_DIRTY_IDX: 357 case LPROPS_FREE: 358 lpt_heap_replace(c, old_lprops, new_lprops, cat); 359 break; 360 case LPROPS_UNCAT: 361 case LPROPS_EMPTY: 362 case LPROPS_FREEABLE: 363 case LPROPS_FRDI_IDX: 364 list_replace(&old_lprops->list, &new_lprops->list); 365 break; 366 default: 367 ubifs_assert(0); 368 } 369 } 370 371 /** 372 * ubifs_ensure_cat - ensure LEB properties are categorized. 373 * @c: UBIFS file-system description object 374 * @lprops: LEB properties 375 * 376 * A LEB may have fallen off of the bottom of a heap, and ended up as 377 * uncategorized even though it has enough space for us now. If that is the case 378 * this function will put the LEB back onto a heap. 379 */ 380 void ubifs_ensure_cat(struct ubifs_info *c, struct ubifs_lprops *lprops) 381 { 382 int cat = lprops->flags & LPROPS_CAT_MASK; 383 384 if (cat != LPROPS_UNCAT) 385 return; 386 cat = ubifs_categorize_lprops(c, lprops); 387 if (cat == LPROPS_UNCAT) 388 return; 389 ubifs_remove_from_cat(c, lprops, LPROPS_UNCAT); 390 ubifs_add_to_cat(c, lprops, cat); 391 } 392 393 /** 394 * ubifs_categorize_lprops - categorize LEB properties. 395 * @c: UBIFS file-system description object 396 * @lprops: LEB properties to categorize 397 * 398 * LEB properties are categorized to enable fast find operations. This function 399 * returns the LEB category to which the LEB properties belong. Note however 400 * that if the LEB category is stored as a heap and the heap is full, the 401 * LEB properties may have their category changed to %LPROPS_UNCAT. 402 */ 403 int ubifs_categorize_lprops(const struct ubifs_info *c, 404 const struct ubifs_lprops *lprops) 405 { 406 if (lprops->flags & LPROPS_TAKEN) 407 return LPROPS_UNCAT; 408 409 if (lprops->free == c->leb_size) { 410 ubifs_assert(!(lprops->flags & LPROPS_INDEX)); 411 return LPROPS_EMPTY; 412 } 413 414 if (lprops->free + lprops->dirty == c->leb_size) { 415 if (lprops->flags & LPROPS_INDEX) 416 return LPROPS_FRDI_IDX; 417 else 418 return LPROPS_FREEABLE; 419 } 420 421 if (lprops->flags & LPROPS_INDEX) { 422 if (lprops->dirty + lprops->free >= c->min_idx_node_sz) 423 return LPROPS_DIRTY_IDX; 424 } else { 425 if (lprops->dirty >= c->dead_wm && 426 lprops->dirty > lprops->free) 427 return LPROPS_DIRTY; 428 if (lprops->free > 0) 429 return LPROPS_FREE; 430 } 431 432 return LPROPS_UNCAT; 433 } 434 435 /** 436 * change_category - change LEB properties category. 437 * @c: UBIFS file-system description object 438 * @lprops: LEB properties to recategorize 439 * 440 * LEB properties are categorized to enable fast find operations. When the LEB 441 * properties change they must be recategorized. 442 */ 443 static void change_category(struct ubifs_info *c, struct ubifs_lprops *lprops) 444 { 445 int old_cat = lprops->flags & LPROPS_CAT_MASK; 446 int new_cat = ubifs_categorize_lprops(c, lprops); 447 448 if (old_cat == new_cat) { 449 struct ubifs_lpt_heap *heap = &c->lpt_heap[new_cat - 1]; 450 451 /* lprops on a heap now must be moved up or down */ 452 if (new_cat < 1 || new_cat > LPROPS_HEAP_CNT) 453 return; /* Not on a heap */ 454 heap = &c->lpt_heap[new_cat - 1]; 455 adjust_lpt_heap(c, heap, lprops, lprops->hpos, new_cat); 456 } else { 457 ubifs_remove_from_cat(c, lprops, old_cat); 458 ubifs_add_to_cat(c, lprops, new_cat); 459 } 460 } 461 462 /** 463 * ubifs_get_lprops - get reference to LEB properties. 464 * @c: the UBIFS file-system description object 465 * 466 * This function locks lprops. Lprops have to be unlocked by 467 * 'ubifs_release_lprops()'. 468 */ 469 void ubifs_get_lprops(struct ubifs_info *c) 470 { 471 mutex_lock(&c->lp_mutex); 472 } 473 474 /** 475 * calc_dark - calculate LEB dark space size. 476 * @c: the UBIFS file-system description object 477 * @spc: amount of free and dirty space in the LEB 478 * 479 * This function calculates amount of dark space in an LEB which has @spc bytes 480 * of free and dirty space. Returns the calculations result. 481 * 482 * Dark space is the space which is not always usable - it depends on which 483 * nodes are written in which order. E.g., if an LEB has only 512 free bytes, 484 * it is dark space, because it cannot fit a large data node. So UBIFS cannot 485 * count on this LEB and treat these 512 bytes as usable because it is not true 486 * if, for example, only big chunks of uncompressible data will be written to 487 * the FS. 488 */ 489 static int calc_dark(struct ubifs_info *c, int spc) 490 { 491 ubifs_assert(!(spc & 7)); 492 493 if (spc < c->dark_wm) 494 return spc; 495 496 /* 497 * If we have slightly more space then the dark space watermark, we can 498 * anyway safely assume it we'll be able to write a node of the 499 * smallest size there. 500 */ 501 if (spc - c->dark_wm < MIN_WRITE_SZ) 502 return spc - MIN_WRITE_SZ; 503 504 return c->dark_wm; 505 } 506 507 /** 508 * is_lprops_dirty - determine if LEB properties are dirty. 509 * @c: the UBIFS file-system description object 510 * @lprops: LEB properties to test 511 */ 512 static int is_lprops_dirty(struct ubifs_info *c, struct ubifs_lprops *lprops) 513 { 514 struct ubifs_pnode *pnode; 515 int pos; 516 517 pos = (lprops->lnum - c->main_first) & (UBIFS_LPT_FANOUT - 1); 518 pnode = (struct ubifs_pnode *)container_of(lprops - pos, 519 struct ubifs_pnode, 520 lprops[0]); 521 return !test_bit(COW_ZNODE, &pnode->flags) && 522 test_bit(DIRTY_CNODE, &pnode->flags); 523 } 524 525 /** 526 * ubifs_change_lp - change LEB properties. 527 * @c: the UBIFS file-system description object 528 * @lp: LEB properties to change 529 * @free: new free space amount 530 * @dirty: new dirty space amount 531 * @flags: new flags 532 * @idx_gc_cnt: change to the count of idx_gc list 533 * 534 * This function changes LEB properties. This function does not change a LEB 535 * property (@free, @dirty or @flag) if the value passed is %LPROPS_NC. 536 * 537 * This function returns a pointer to the updated LEB properties on success 538 * and a negative error code on failure. N.B. the LEB properties may have had to 539 * be copied (due to COW) and consequently the pointer returned may not be the 540 * same as the pointer passed. 541 */ 542 const struct ubifs_lprops *ubifs_change_lp(struct ubifs_info *c, 543 const struct ubifs_lprops *lp, 544 int free, int dirty, int flags, 545 int idx_gc_cnt) 546 { 547 /* 548 * This is the only function that is allowed to change lprops, so we 549 * discard the const qualifier. 550 */ 551 struct ubifs_lprops *lprops = (struct ubifs_lprops *)lp; 552 553 dbg_lp("LEB %d, free %d, dirty %d, flags %d", 554 lprops->lnum, free, dirty, flags); 555 556 ubifs_assert(mutex_is_locked(&c->lp_mutex)); 557 ubifs_assert(c->lst.empty_lebs >= 0 && 558 c->lst.empty_lebs <= c->main_lebs); 559 ubifs_assert(c->freeable_cnt >= 0); 560 ubifs_assert(c->freeable_cnt <= c->main_lebs); 561 ubifs_assert(c->lst.taken_empty_lebs >= 0); 562 ubifs_assert(c->lst.taken_empty_lebs <= c->lst.empty_lebs); 563 ubifs_assert(!(c->lst.total_free & 7) && !(c->lst.total_dirty & 7)); 564 ubifs_assert(!(c->lst.total_dead & 7) && !(c->lst.total_dark & 7)); 565 ubifs_assert(!(c->lst.total_used & 7)); 566 ubifs_assert(free == LPROPS_NC || free >= 0); 567 ubifs_assert(dirty == LPROPS_NC || dirty >= 0); 568 569 if (!is_lprops_dirty(c, lprops)) { 570 lprops = ubifs_lpt_lookup_dirty(c, lprops->lnum); 571 if (IS_ERR(lprops)) 572 return lprops; 573 } else 574 ubifs_assert(lprops == ubifs_lpt_lookup_dirty(c, lprops->lnum)); 575 576 ubifs_assert(!(lprops->free & 7) && !(lprops->dirty & 7)); 577 578 spin_lock(&c->space_lock); 579 580 if ((lprops->flags & LPROPS_TAKEN) && lprops->free == c->leb_size) 581 c->lst.taken_empty_lebs -= 1; 582 583 if (!(lprops->flags & LPROPS_INDEX)) { 584 int old_spc; 585 586 old_spc = lprops->free + lprops->dirty; 587 if (old_spc < c->dead_wm) 588 c->lst.total_dead -= old_spc; 589 else 590 c->lst.total_dark -= calc_dark(c, old_spc); 591 592 c->lst.total_used -= c->leb_size - old_spc; 593 } 594 595 if (free != LPROPS_NC) { 596 free = ALIGN(free, 8); 597 c->lst.total_free += free - lprops->free; 598 599 /* Increase or decrease empty LEBs counter if needed */ 600 if (free == c->leb_size) { 601 if (lprops->free != c->leb_size) 602 c->lst.empty_lebs += 1; 603 } else if (lprops->free == c->leb_size) 604 c->lst.empty_lebs -= 1; 605 lprops->free = free; 606 } 607 608 if (dirty != LPROPS_NC) { 609 dirty = ALIGN(dirty, 8); 610 c->lst.total_dirty += dirty - lprops->dirty; 611 lprops->dirty = dirty; 612 } 613 614 if (flags != LPROPS_NC) { 615 /* Take care about indexing LEBs counter if needed */ 616 if ((lprops->flags & LPROPS_INDEX)) { 617 if (!(flags & LPROPS_INDEX)) 618 c->lst.idx_lebs -= 1; 619 } else if (flags & LPROPS_INDEX) 620 c->lst.idx_lebs += 1; 621 lprops->flags = flags; 622 } 623 624 if (!(lprops->flags & LPROPS_INDEX)) { 625 int new_spc; 626 627 new_spc = lprops->free + lprops->dirty; 628 if (new_spc < c->dead_wm) 629 c->lst.total_dead += new_spc; 630 else 631 c->lst.total_dark += calc_dark(c, new_spc); 632 633 c->lst.total_used += c->leb_size - new_spc; 634 } 635 636 if ((lprops->flags & LPROPS_TAKEN) && lprops->free == c->leb_size) 637 c->lst.taken_empty_lebs += 1; 638 639 change_category(c, lprops); 640 641 c->idx_gc_cnt += idx_gc_cnt; 642 643 spin_unlock(&c->space_lock); 644 645 return lprops; 646 } 647 648 /** 649 * ubifs_release_lprops - release lprops lock. 650 * @c: the UBIFS file-system description object 651 * 652 * This function has to be called after each 'ubifs_get_lprops()' call to 653 * unlock lprops. 654 */ 655 void ubifs_release_lprops(struct ubifs_info *c) 656 { 657 ubifs_assert(mutex_is_locked(&c->lp_mutex)); 658 ubifs_assert(c->lst.empty_lebs >= 0 && 659 c->lst.empty_lebs <= c->main_lebs); 660 661 mutex_unlock(&c->lp_mutex); 662 } 663 664 /** 665 * ubifs_get_lp_stats - get lprops statistics. 666 * @c: UBIFS file-system description object 667 * @st: return statistics 668 */ 669 void ubifs_get_lp_stats(struct ubifs_info *c, struct ubifs_lp_stats *st) 670 { 671 spin_lock(&c->space_lock); 672 memcpy(st, &c->lst, sizeof(struct ubifs_lp_stats)); 673 spin_unlock(&c->space_lock); 674 } 675 676 /** 677 * ubifs_change_one_lp - change LEB properties. 678 * @c: the UBIFS file-system description object 679 * @lnum: LEB to change properties for 680 * @free: amount of free space 681 * @dirty: amount of dirty space 682 * @flags_set: flags to set 683 * @flags_clean: flags to clean 684 * @idx_gc_cnt: change to the count of idx_gc list 685 * 686 * This function changes properties of LEB @lnum. It is a helper wrapper over 687 * 'ubifs_change_lp()' which hides lprops get/release. The arguments are the 688 * same as in case of 'ubifs_change_lp()'. Returns zero in case of success and 689 * a negative error code in case of failure. 690 */ 691 int ubifs_change_one_lp(struct ubifs_info *c, int lnum, int free, int dirty, 692 int flags_set, int flags_clean, int idx_gc_cnt) 693 { 694 int err = 0, flags; 695 const struct ubifs_lprops *lp; 696 697 ubifs_get_lprops(c); 698 699 lp = ubifs_lpt_lookup_dirty(c, lnum); 700 if (IS_ERR(lp)) { 701 err = PTR_ERR(lp); 702 goto out; 703 } 704 705 flags = (lp->flags | flags_set) & ~flags_clean; 706 lp = ubifs_change_lp(c, lp, free, dirty, flags, idx_gc_cnt); 707 if (IS_ERR(lp)) 708 err = PTR_ERR(lp); 709 710 out: 711 ubifs_release_lprops(c); 712 return err; 713 } 714 715 /** 716 * ubifs_update_one_lp - update LEB properties. 717 * @c: the UBIFS file-system description object 718 * @lnum: LEB to change properties for 719 * @free: amount of free space 720 * @dirty: amount of dirty space to add 721 * @flags_set: flags to set 722 * @flags_clean: flags to clean 723 * 724 * This function is the same as 'ubifs_change_one_lp()' but @dirty is added to 725 * current dirty space, not substitutes it. 726 */ 727 int ubifs_update_one_lp(struct ubifs_info *c, int lnum, int free, int dirty, 728 int flags_set, int flags_clean) 729 { 730 int err = 0, flags; 731 const struct ubifs_lprops *lp; 732 733 ubifs_get_lprops(c); 734 735 lp = ubifs_lpt_lookup_dirty(c, lnum); 736 if (IS_ERR(lp)) { 737 err = PTR_ERR(lp); 738 goto out; 739 } 740 741 flags = (lp->flags | flags_set) & ~flags_clean; 742 lp = ubifs_change_lp(c, lp, free, lp->dirty + dirty, flags, 0); 743 if (IS_ERR(lp)) 744 err = PTR_ERR(lp); 745 746 out: 747 ubifs_release_lprops(c); 748 return err; 749 } 750 751 /** 752 * ubifs_read_one_lp - read LEB properties. 753 * @c: the UBIFS file-system description object 754 * @lnum: LEB to read properties for 755 * @lp: where to store read properties 756 * 757 * This helper function reads properties of a LEB @lnum and stores them in @lp. 758 * Returns zero in case of success and a negative error code in case of 759 * failure. 760 */ 761 int ubifs_read_one_lp(struct ubifs_info *c, int lnum, struct ubifs_lprops *lp) 762 { 763 int err = 0; 764 const struct ubifs_lprops *lpp; 765 766 ubifs_get_lprops(c); 767 768 lpp = ubifs_lpt_lookup(c, lnum); 769 if (IS_ERR(lpp)) { 770 err = PTR_ERR(lpp); 771 goto out; 772 } 773 774 memcpy(lp, lpp, sizeof(struct ubifs_lprops)); 775 776 out: 777 ubifs_release_lprops(c); 778 return err; 779 } 780 781 /** 782 * ubifs_fast_find_free - try to find a LEB with free space quickly. 783 * @c: the UBIFS file-system description object 784 * 785 * This function returns LEB properties for a LEB with free space or %NULL if 786 * the function is unable to find a LEB quickly. 787 */ 788 const struct ubifs_lprops *ubifs_fast_find_free(struct ubifs_info *c) 789 { 790 struct ubifs_lprops *lprops; 791 struct ubifs_lpt_heap *heap; 792 793 ubifs_assert(mutex_is_locked(&c->lp_mutex)); 794 795 heap = &c->lpt_heap[LPROPS_FREE - 1]; 796 if (heap->cnt == 0) 797 return NULL; 798 799 lprops = heap->arr[0]; 800 ubifs_assert(!(lprops->flags & LPROPS_TAKEN)); 801 ubifs_assert(!(lprops->flags & LPROPS_INDEX)); 802 return lprops; 803 } 804 805 /** 806 * ubifs_fast_find_empty - try to find an empty LEB quickly. 807 * @c: the UBIFS file-system description object 808 * 809 * This function returns LEB properties for an empty LEB or %NULL if the 810 * function is unable to find an empty LEB quickly. 811 */ 812 const struct ubifs_lprops *ubifs_fast_find_empty(struct ubifs_info *c) 813 { 814 struct ubifs_lprops *lprops; 815 816 ubifs_assert(mutex_is_locked(&c->lp_mutex)); 817 818 if (list_empty(&c->empty_list)) 819 return NULL; 820 821 lprops = list_entry(c->empty_list.next, struct ubifs_lprops, list); 822 ubifs_assert(!(lprops->flags & LPROPS_TAKEN)); 823 ubifs_assert(!(lprops->flags & LPROPS_INDEX)); 824 ubifs_assert(lprops->free == c->leb_size); 825 return lprops; 826 } 827 828 /** 829 * ubifs_fast_find_freeable - try to find a freeable LEB quickly. 830 * @c: the UBIFS file-system description object 831 * 832 * This function returns LEB properties for a freeable LEB or %NULL if the 833 * function is unable to find a freeable LEB quickly. 834 */ 835 const struct ubifs_lprops *ubifs_fast_find_freeable(struct ubifs_info *c) 836 { 837 struct ubifs_lprops *lprops; 838 839 ubifs_assert(mutex_is_locked(&c->lp_mutex)); 840 841 if (list_empty(&c->freeable_list)) 842 return NULL; 843 844 lprops = list_entry(c->freeable_list.next, struct ubifs_lprops, list); 845 ubifs_assert(!(lprops->flags & LPROPS_TAKEN)); 846 ubifs_assert(!(lprops->flags & LPROPS_INDEX)); 847 ubifs_assert(lprops->free + lprops->dirty == c->leb_size); 848 ubifs_assert(c->freeable_cnt > 0); 849 return lprops; 850 } 851 852 /** 853 * ubifs_fast_find_frdi_idx - try to find a freeable index LEB quickly. 854 * @c: the UBIFS file-system description object 855 * 856 * This function returns LEB properties for a freeable index LEB or %NULL if the 857 * function is unable to find a freeable index LEB quickly. 858 */ 859 const struct ubifs_lprops *ubifs_fast_find_frdi_idx(struct ubifs_info *c) 860 { 861 struct ubifs_lprops *lprops; 862 863 ubifs_assert(mutex_is_locked(&c->lp_mutex)); 864 865 if (list_empty(&c->frdi_idx_list)) 866 return NULL; 867 868 lprops = list_entry(c->frdi_idx_list.next, struct ubifs_lprops, list); 869 ubifs_assert(!(lprops->flags & LPROPS_TAKEN)); 870 ubifs_assert((lprops->flags & LPROPS_INDEX)); 871 ubifs_assert(lprops->free + lprops->dirty == c->leb_size); 872 return lprops; 873 } 874 875 #ifdef CONFIG_UBIFS_FS_DEBUG 876 877 /** 878 * dbg_check_cats - check category heaps and lists. 879 * @c: UBIFS file-system description object 880 * 881 * This function returns %0 on success and a negative error code on failure. 882 */ 883 int dbg_check_cats(struct ubifs_info *c) 884 { 885 struct ubifs_lprops *lprops; 886 struct list_head *pos; 887 int i, cat; 888 889 if (!(ubifs_chk_flags & (UBIFS_CHK_GEN | UBIFS_CHK_LPROPS))) 890 return 0; 891 892 list_for_each_entry(lprops, &c->empty_list, list) { 893 if (lprops->free != c->leb_size) { 894 ubifs_err("non-empty LEB %d on empty list " 895 "(free %d dirty %d flags %d)", lprops->lnum, 896 lprops->free, lprops->dirty, lprops->flags); 897 return -EINVAL; 898 } 899 if (lprops->flags & LPROPS_TAKEN) { 900 ubifs_err("taken LEB %d on empty list " 901 "(free %d dirty %d flags %d)", lprops->lnum, 902 lprops->free, lprops->dirty, lprops->flags); 903 return -EINVAL; 904 } 905 } 906 907 i = 0; 908 list_for_each_entry(lprops, &c->freeable_list, list) { 909 if (lprops->free + lprops->dirty != c->leb_size) { 910 ubifs_err("non-freeable LEB %d on freeable list " 911 "(free %d dirty %d flags %d)", lprops->lnum, 912 lprops->free, lprops->dirty, lprops->flags); 913 return -EINVAL; 914 } 915 if (lprops->flags & LPROPS_TAKEN) { 916 ubifs_err("taken LEB %d on freeable list " 917 "(free %d dirty %d flags %d)", lprops->lnum, 918 lprops->free, lprops->dirty, lprops->flags); 919 return -EINVAL; 920 } 921 i += 1; 922 } 923 if (i != c->freeable_cnt) { 924 ubifs_err("freeable list count %d expected %d", i, 925 c->freeable_cnt); 926 return -EINVAL; 927 } 928 929 i = 0; 930 list_for_each(pos, &c->idx_gc) 931 i += 1; 932 if (i != c->idx_gc_cnt) { 933 ubifs_err("idx_gc list count %d expected %d", i, 934 c->idx_gc_cnt); 935 return -EINVAL; 936 } 937 938 list_for_each_entry(lprops, &c->frdi_idx_list, list) { 939 if (lprops->free + lprops->dirty != c->leb_size) { 940 ubifs_err("non-freeable LEB %d on frdi_idx list " 941 "(free %d dirty %d flags %d)", lprops->lnum, 942 lprops->free, lprops->dirty, lprops->flags); 943 return -EINVAL; 944 } 945 if (lprops->flags & LPROPS_TAKEN) { 946 ubifs_err("taken LEB %d on frdi_idx list " 947 "(free %d dirty %d flags %d)", lprops->lnum, 948 lprops->free, lprops->dirty, lprops->flags); 949 return -EINVAL; 950 } 951 if (!(lprops->flags & LPROPS_INDEX)) { 952 ubifs_err("non-index LEB %d on frdi_idx list " 953 "(free %d dirty %d flags %d)", lprops->lnum, 954 lprops->free, lprops->dirty, lprops->flags); 955 return -EINVAL; 956 } 957 } 958 959 for (cat = 1; cat <= LPROPS_HEAP_CNT; cat++) { 960 struct ubifs_lpt_heap *heap = &c->lpt_heap[cat - 1]; 961 962 for (i = 0; i < heap->cnt; i++) { 963 lprops = heap->arr[i]; 964 if (!lprops) { 965 ubifs_err("null ptr in LPT heap cat %d", cat); 966 return -EINVAL; 967 } 968 if (lprops->hpos != i) { 969 ubifs_err("bad ptr in LPT heap cat %d", cat); 970 return -EINVAL; 971 } 972 if (lprops->flags & LPROPS_TAKEN) { 973 ubifs_err("taken LEB in LPT heap cat %d", cat); 974 return -EINVAL; 975 } 976 } 977 } 978 979 return 0; 980 } 981 982 void dbg_check_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat, 983 int add_pos) 984 { 985 int i = 0, j, err = 0; 986 987 if (!(ubifs_chk_flags & (UBIFS_CHK_GEN | UBIFS_CHK_LPROPS))) 988 return; 989 990 for (i = 0; i < heap->cnt; i++) { 991 struct ubifs_lprops *lprops = heap->arr[i]; 992 struct ubifs_lprops *lp; 993 994 if (i != add_pos) 995 if ((lprops->flags & LPROPS_CAT_MASK) != cat) { 996 err = 1; 997 goto out; 998 } 999 if (lprops->hpos != i) { 1000 err = 2; 1001 goto out; 1002 } 1003 lp = ubifs_lpt_lookup(c, lprops->lnum); 1004 if (IS_ERR(lp)) { 1005 err = 3; 1006 goto out; 1007 } 1008 if (lprops != lp) { 1009 dbg_msg("lprops %zx lp %zx lprops->lnum %d lp->lnum %d", 1010 (size_t)lprops, (size_t)lp, lprops->lnum, 1011 lp->lnum); 1012 err = 4; 1013 goto out; 1014 } 1015 for (j = 0; j < i; j++) { 1016 lp = heap->arr[j]; 1017 if (lp == lprops) { 1018 err = 5; 1019 goto out; 1020 } 1021 if (lp->lnum == lprops->lnum) { 1022 err = 6; 1023 goto out; 1024 } 1025 } 1026 } 1027 out: 1028 if (err) { 1029 dbg_msg("failed cat %d hpos %d err %d", cat, i, err); 1030 dbg_dump_stack(); 1031 dbg_dump_heap(c, heap, cat); 1032 } 1033 } 1034 1035 /** 1036 * struct scan_check_data - data provided to scan callback function. 1037 * @lst: LEB properties statistics 1038 * @err: error code 1039 */ 1040 struct scan_check_data { 1041 struct ubifs_lp_stats lst; 1042 int err; 1043 }; 1044 1045 /** 1046 * scan_check_cb - scan callback. 1047 * @c: the UBIFS file-system description object 1048 * @lp: LEB properties to scan 1049 * @in_tree: whether the LEB properties are in main memory 1050 * @data: information passed to and from the caller of the scan 1051 * 1052 * This function returns a code that indicates whether the scan should continue 1053 * (%LPT_SCAN_CONTINUE), whether the LEB properties should be added to the tree 1054 * in main memory (%LPT_SCAN_ADD), or whether the scan should stop 1055 * (%LPT_SCAN_STOP). 1056 */ 1057 static int scan_check_cb(struct ubifs_info *c, 1058 const struct ubifs_lprops *lp, int in_tree, 1059 struct scan_check_data *data) 1060 { 1061 struct ubifs_scan_leb *sleb; 1062 struct ubifs_scan_node *snod; 1063 struct ubifs_lp_stats *lst = &data->lst; 1064 int cat, lnum = lp->lnum, is_idx = 0, used = 0, free, dirty; 1065 1066 cat = lp->flags & LPROPS_CAT_MASK; 1067 if (cat != LPROPS_UNCAT) { 1068 cat = ubifs_categorize_lprops(c, lp); 1069 if (cat != (lp->flags & LPROPS_CAT_MASK)) { 1070 ubifs_err("bad LEB category %d expected %d", 1071 (lp->flags & LPROPS_CAT_MASK), cat); 1072 goto out; 1073 } 1074 } 1075 1076 /* Check lp is on its category list (if it has one) */ 1077 if (in_tree) { 1078 struct list_head *list = NULL; 1079 1080 switch (cat) { 1081 case LPROPS_EMPTY: 1082 list = &c->empty_list; 1083 break; 1084 case LPROPS_FREEABLE: 1085 list = &c->freeable_list; 1086 break; 1087 case LPROPS_FRDI_IDX: 1088 list = &c->frdi_idx_list; 1089 break; 1090 case LPROPS_UNCAT: 1091 list = &c->uncat_list; 1092 break; 1093 } 1094 if (list) { 1095 struct ubifs_lprops *lprops; 1096 int found = 0; 1097 1098 list_for_each_entry(lprops, list, list) { 1099 if (lprops == lp) { 1100 found = 1; 1101 break; 1102 } 1103 } 1104 if (!found) { 1105 ubifs_err("bad LPT list (category %d)", cat); 1106 goto out; 1107 } 1108 } 1109 } 1110 1111 /* Check lp is on its category heap (if it has one) */ 1112 if (in_tree && cat > 0 && cat <= LPROPS_HEAP_CNT) { 1113 struct ubifs_lpt_heap *heap = &c->lpt_heap[cat - 1]; 1114 1115 if ((lp->hpos != -1 && heap->arr[lp->hpos]->lnum != lnum) || 1116 lp != heap->arr[lp->hpos]) { 1117 ubifs_err("bad LPT heap (category %d)", cat); 1118 goto out; 1119 } 1120 } 1121 1122 sleb = ubifs_scan(c, lnum, 0, c->dbg_buf); 1123 if (IS_ERR(sleb)) { 1124 /* 1125 * After an unclean unmount, empty and freeable LEBs 1126 * may contain garbage. 1127 */ 1128 if (lp->free == c->leb_size) { 1129 ubifs_err("scan errors were in empty LEB " 1130 "- continuing checking"); 1131 lst->empty_lebs += 1; 1132 lst->total_free += c->leb_size; 1133 lst->total_dark += calc_dark(c, c->leb_size); 1134 return LPT_SCAN_CONTINUE; 1135 } 1136 1137 if (lp->free + lp->dirty == c->leb_size && 1138 !(lp->flags & LPROPS_INDEX)) { 1139 ubifs_err("scan errors were in freeable LEB " 1140 "- continuing checking"); 1141 lst->total_free += lp->free; 1142 lst->total_dirty += lp->dirty; 1143 lst->total_dark += calc_dark(c, c->leb_size); 1144 return LPT_SCAN_CONTINUE; 1145 } 1146 data->err = PTR_ERR(sleb); 1147 return LPT_SCAN_STOP; 1148 } 1149 1150 is_idx = -1; 1151 list_for_each_entry(snod, &sleb->nodes, list) { 1152 int found, level = 0; 1153 1154 cond_resched(); 1155 1156 if (is_idx == -1) 1157 is_idx = (snod->type == UBIFS_IDX_NODE) ? 1 : 0; 1158 1159 if (is_idx && snod->type != UBIFS_IDX_NODE) { 1160 ubifs_err("indexing node in data LEB %d:%d", 1161 lnum, snod->offs); 1162 goto out_destroy; 1163 } 1164 1165 if (snod->type == UBIFS_IDX_NODE) { 1166 struct ubifs_idx_node *idx = snod->node; 1167 1168 key_read(c, ubifs_idx_key(c, idx), &snod->key); 1169 level = le16_to_cpu(idx->level); 1170 } 1171 1172 found = ubifs_tnc_has_node(c, &snod->key, level, lnum, 1173 snod->offs, is_idx); 1174 if (found) { 1175 if (found < 0) 1176 goto out_destroy; 1177 used += ALIGN(snod->len, 8); 1178 } 1179 } 1180 1181 free = c->leb_size - sleb->endpt; 1182 dirty = sleb->endpt - used; 1183 1184 if (free > c->leb_size || free < 0 || dirty > c->leb_size || 1185 dirty < 0) { 1186 ubifs_err("bad calculated accounting for LEB %d: " 1187 "free %d, dirty %d", lnum, free, dirty); 1188 goto out_destroy; 1189 } 1190 1191 if (lp->free + lp->dirty == c->leb_size && 1192 free + dirty == c->leb_size) 1193 if ((is_idx && !(lp->flags & LPROPS_INDEX)) || 1194 (!is_idx && free == c->leb_size) || 1195 lp->free == c->leb_size) { 1196 /* 1197 * Empty or freeable LEBs could contain index 1198 * nodes from an uncompleted commit due to an 1199 * unclean unmount. Or they could be empty for 1200 * the same reason. Or it may simply not have been 1201 * unmapped. 1202 */ 1203 free = lp->free; 1204 dirty = lp->dirty; 1205 is_idx = 0; 1206 } 1207 1208 if (is_idx && lp->free + lp->dirty == free + dirty && 1209 lnum != c->ihead_lnum) { 1210 /* 1211 * After an unclean unmount, an index LEB could have a different 1212 * amount of free space than the value recorded by lprops. That 1213 * is because the in-the-gaps method may use free space or 1214 * create free space (as a side-effect of using ubi_leb_change 1215 * and not writing the whole LEB). The incorrect free space 1216 * value is not a problem because the index is only ever 1217 * allocated empty LEBs, so there will never be an attempt to 1218 * write to the free space at the end of an index LEB - except 1219 * by the in-the-gaps method for which it is not a problem. 1220 */ 1221 free = lp->free; 1222 dirty = lp->dirty; 1223 } 1224 1225 if (lp->free != free || lp->dirty != dirty) 1226 goto out_print; 1227 1228 if (is_idx && !(lp->flags & LPROPS_INDEX)) { 1229 if (free == c->leb_size) 1230 /* Free but not unmapped LEB, it's fine */ 1231 is_idx = 0; 1232 else { 1233 ubifs_err("indexing node without indexing " 1234 "flag"); 1235 goto out_print; 1236 } 1237 } 1238 1239 if (!is_idx && (lp->flags & LPROPS_INDEX)) { 1240 ubifs_err("data node with indexing flag"); 1241 goto out_print; 1242 } 1243 1244 if (free == c->leb_size) 1245 lst->empty_lebs += 1; 1246 1247 if (is_idx) 1248 lst->idx_lebs += 1; 1249 1250 if (!(lp->flags & LPROPS_INDEX)) 1251 lst->total_used += c->leb_size - free - dirty; 1252 lst->total_free += free; 1253 lst->total_dirty += dirty; 1254 1255 if (!(lp->flags & LPROPS_INDEX)) { 1256 int spc = free + dirty; 1257 1258 if (spc < c->dead_wm) 1259 lst->total_dead += spc; 1260 else 1261 lst->total_dark += calc_dark(c, spc); 1262 } 1263 1264 ubifs_scan_destroy(sleb); 1265 1266 return LPT_SCAN_CONTINUE; 1267 1268 out_print: 1269 ubifs_err("bad accounting of LEB %d: free %d, dirty %d flags %#x, " 1270 "should be free %d, dirty %d", 1271 lnum, lp->free, lp->dirty, lp->flags, free, dirty); 1272 dbg_dump_leb(c, lnum); 1273 out_destroy: 1274 ubifs_scan_destroy(sleb); 1275 out: 1276 data->err = -EINVAL; 1277 return LPT_SCAN_STOP; 1278 } 1279 1280 /** 1281 * dbg_check_lprops - check all LEB properties. 1282 * @c: UBIFS file-system description object 1283 * 1284 * This function checks all LEB properties and makes sure they are all correct. 1285 * It returns zero if everything is fine, %-EINVAL if there is an inconsistency 1286 * and other negative error codes in case of other errors. This function is 1287 * called while the file system is locked (because of commit start), so no 1288 * additional locking is required. Note that locking the LPT mutex would cause 1289 * a circular lock dependency with the TNC mutex. 1290 */ 1291 int dbg_check_lprops(struct ubifs_info *c) 1292 { 1293 int i, err; 1294 struct scan_check_data data; 1295 struct ubifs_lp_stats *lst = &data.lst; 1296 1297 if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS)) 1298 return 0; 1299 1300 /* 1301 * As we are going to scan the media, the write buffers have to be 1302 * synchronized. 1303 */ 1304 for (i = 0; i < c->jhead_cnt; i++) { 1305 err = ubifs_wbuf_sync(&c->jheads[i].wbuf); 1306 if (err) 1307 return err; 1308 } 1309 1310 memset(lst, 0, sizeof(struct ubifs_lp_stats)); 1311 1312 data.err = 0; 1313 err = ubifs_lpt_scan_nolock(c, c->main_first, c->leb_cnt - 1, 1314 (ubifs_lpt_scan_callback)scan_check_cb, 1315 &data); 1316 if (err && err != -ENOSPC) 1317 goto out; 1318 if (data.err) { 1319 err = data.err; 1320 goto out; 1321 } 1322 1323 if (lst->empty_lebs != c->lst.empty_lebs || 1324 lst->idx_lebs != c->lst.idx_lebs || 1325 lst->total_free != c->lst.total_free || 1326 lst->total_dirty != c->lst.total_dirty || 1327 lst->total_used != c->lst.total_used) { 1328 ubifs_err("bad overall accounting"); 1329 ubifs_err("calculated: empty_lebs %d, idx_lebs %d, " 1330 "total_free %lld, total_dirty %lld, total_used %lld", 1331 lst->empty_lebs, lst->idx_lebs, lst->total_free, 1332 lst->total_dirty, lst->total_used); 1333 ubifs_err("read from lprops: empty_lebs %d, idx_lebs %d, " 1334 "total_free %lld, total_dirty %lld, total_used %lld", 1335 c->lst.empty_lebs, c->lst.idx_lebs, c->lst.total_free, 1336 c->lst.total_dirty, c->lst.total_used); 1337 err = -EINVAL; 1338 goto out; 1339 } 1340 1341 if (lst->total_dead != c->lst.total_dead || 1342 lst->total_dark != c->lst.total_dark) { 1343 ubifs_err("bad dead/dark space accounting"); 1344 ubifs_err("calculated: total_dead %lld, total_dark %lld", 1345 lst->total_dead, lst->total_dark); 1346 ubifs_err("read from lprops: total_dead %lld, total_dark %lld", 1347 c->lst.total_dead, c->lst.total_dark); 1348 err = -EINVAL; 1349 goto out; 1350 } 1351 1352 err = dbg_check_cats(c); 1353 out: 1354 return err; 1355 } 1356 1357 #endif /* CONFIG_UBIFS_FS_DEBUG */ 1358