19eefe2a2SStefan Roese /* 29eefe2a2SStefan Roese * This file is part of UBIFS. 39eefe2a2SStefan Roese * 49eefe2a2SStefan Roese * Copyright (C) 2006-2008 Nokia Corporation. 59eefe2a2SStefan Roese * 6ff94bc40SHeiko Schocher * SPDX-License-Identifier: GPL-2.0+ 79eefe2a2SStefan Roese * 89eefe2a2SStefan Roese * Authors: Adrian Hunter 99eefe2a2SStefan Roese * Artem Bityutskiy (Битюцкий Артём) 109eefe2a2SStefan Roese */ 119eefe2a2SStefan Roese 129eefe2a2SStefan Roese /* 139eefe2a2SStefan Roese * This file implements commit-related functionality of the LEB properties 149eefe2a2SStefan Roese * subsystem. 159eefe2a2SStefan Roese */ 169eefe2a2SStefan Roese 17ff94bc40SHeiko Schocher #ifndef __UBOOT__ 18ff94bc40SHeiko Schocher #include <linux/crc16.h> 19ff94bc40SHeiko Schocher #include <linux/slab.h> 20ff94bc40SHeiko Schocher #include <linux/random.h> 21ff94bc40SHeiko Schocher #else 22ff94bc40SHeiko Schocher #include <linux/compat.h> 23ff94bc40SHeiko Schocher #include <linux/err.h> 249eefe2a2SStefan Roese #include "crc16.h" 25ff94bc40SHeiko Schocher #endif 269eefe2a2SStefan Roese #include "ubifs.h" 279eefe2a2SStefan Roese 28ff94bc40SHeiko Schocher #ifndef __UBOOT__ 29ff94bc40SHeiko Schocher static int dbg_populate_lsave(struct ubifs_info *c); 30ff94bc40SHeiko Schocher #endif 31ff94bc40SHeiko Schocher 32ff94bc40SHeiko Schocher /** 33ff94bc40SHeiko Schocher * first_dirty_cnode - find first dirty cnode. 34ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 35ff94bc40SHeiko Schocher * @nnode: nnode at which to start 36ff94bc40SHeiko Schocher * 37ff94bc40SHeiko Schocher * This function returns the first dirty cnode or %NULL if there is not one. 38ff94bc40SHeiko Schocher */ 39ff94bc40SHeiko Schocher static struct ubifs_cnode *first_dirty_cnode(struct ubifs_nnode *nnode) 40ff94bc40SHeiko Schocher { 41ff94bc40SHeiko Schocher ubifs_assert(nnode); 42ff94bc40SHeiko Schocher while (1) { 43ff94bc40SHeiko Schocher int i, cont = 0; 44ff94bc40SHeiko Schocher 45ff94bc40SHeiko Schocher for (i = 0; i < UBIFS_LPT_FANOUT; i++) { 46ff94bc40SHeiko Schocher struct ubifs_cnode *cnode; 47ff94bc40SHeiko Schocher 48ff94bc40SHeiko Schocher cnode = nnode->nbranch[i].cnode; 49ff94bc40SHeiko Schocher if (cnode && 50ff94bc40SHeiko Schocher test_bit(DIRTY_CNODE, &cnode->flags)) { 51ff94bc40SHeiko Schocher if (cnode->level == 0) 52ff94bc40SHeiko Schocher return cnode; 53ff94bc40SHeiko Schocher nnode = (struct ubifs_nnode *)cnode; 54ff94bc40SHeiko Schocher cont = 1; 55ff94bc40SHeiko Schocher break; 56ff94bc40SHeiko Schocher } 57ff94bc40SHeiko Schocher } 58ff94bc40SHeiko Schocher if (!cont) 59ff94bc40SHeiko Schocher return (struct ubifs_cnode *)nnode; 60ff94bc40SHeiko Schocher } 61ff94bc40SHeiko Schocher } 62ff94bc40SHeiko Schocher 63ff94bc40SHeiko Schocher /** 64ff94bc40SHeiko Schocher * next_dirty_cnode - find next dirty cnode. 65ff94bc40SHeiko Schocher * @cnode: cnode from which to begin searching 66ff94bc40SHeiko Schocher * 67ff94bc40SHeiko Schocher * This function returns the next dirty cnode or %NULL if there is not one. 68ff94bc40SHeiko Schocher */ 69ff94bc40SHeiko Schocher static struct ubifs_cnode *next_dirty_cnode(struct ubifs_cnode *cnode) 70ff94bc40SHeiko Schocher { 71ff94bc40SHeiko Schocher struct ubifs_nnode *nnode; 72ff94bc40SHeiko Schocher int i; 73ff94bc40SHeiko Schocher 74ff94bc40SHeiko Schocher ubifs_assert(cnode); 75ff94bc40SHeiko Schocher nnode = cnode->parent; 76ff94bc40SHeiko Schocher if (!nnode) 77ff94bc40SHeiko Schocher return NULL; 78ff94bc40SHeiko Schocher for (i = cnode->iip + 1; i < UBIFS_LPT_FANOUT; i++) { 79ff94bc40SHeiko Schocher cnode = nnode->nbranch[i].cnode; 80ff94bc40SHeiko Schocher if (cnode && test_bit(DIRTY_CNODE, &cnode->flags)) { 81ff94bc40SHeiko Schocher if (cnode->level == 0) 82ff94bc40SHeiko Schocher return cnode; /* cnode is a pnode */ 83ff94bc40SHeiko Schocher /* cnode is a nnode */ 84ff94bc40SHeiko Schocher return first_dirty_cnode((struct ubifs_nnode *)cnode); 85ff94bc40SHeiko Schocher } 86ff94bc40SHeiko Schocher } 87ff94bc40SHeiko Schocher return (struct ubifs_cnode *)nnode; 88ff94bc40SHeiko Schocher } 89ff94bc40SHeiko Schocher 90ff94bc40SHeiko Schocher /** 91ff94bc40SHeiko Schocher * get_cnodes_to_commit - create list of dirty cnodes to commit. 92ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 93ff94bc40SHeiko Schocher * 94ff94bc40SHeiko Schocher * This function returns the number of cnodes to commit. 95ff94bc40SHeiko Schocher */ 96ff94bc40SHeiko Schocher static int get_cnodes_to_commit(struct ubifs_info *c) 97ff94bc40SHeiko Schocher { 98ff94bc40SHeiko Schocher struct ubifs_cnode *cnode, *cnext; 99ff94bc40SHeiko Schocher int cnt = 0; 100ff94bc40SHeiko Schocher 101ff94bc40SHeiko Schocher if (!c->nroot) 102ff94bc40SHeiko Schocher return 0; 103ff94bc40SHeiko Schocher 104ff94bc40SHeiko Schocher if (!test_bit(DIRTY_CNODE, &c->nroot->flags)) 105ff94bc40SHeiko Schocher return 0; 106ff94bc40SHeiko Schocher 107ff94bc40SHeiko Schocher c->lpt_cnext = first_dirty_cnode(c->nroot); 108ff94bc40SHeiko Schocher cnode = c->lpt_cnext; 109ff94bc40SHeiko Schocher if (!cnode) 110ff94bc40SHeiko Schocher return 0; 111ff94bc40SHeiko Schocher cnt += 1; 112ff94bc40SHeiko Schocher while (1) { 113ff94bc40SHeiko Schocher ubifs_assert(!test_bit(COW_CNODE, &cnode->flags)); 114ff94bc40SHeiko Schocher __set_bit(COW_CNODE, &cnode->flags); 115ff94bc40SHeiko Schocher cnext = next_dirty_cnode(cnode); 116ff94bc40SHeiko Schocher if (!cnext) { 117ff94bc40SHeiko Schocher cnode->cnext = c->lpt_cnext; 118ff94bc40SHeiko Schocher break; 119ff94bc40SHeiko Schocher } 120ff94bc40SHeiko Schocher cnode->cnext = cnext; 121ff94bc40SHeiko Schocher cnode = cnext; 122ff94bc40SHeiko Schocher cnt += 1; 123ff94bc40SHeiko Schocher } 124ff94bc40SHeiko Schocher dbg_cmt("committing %d cnodes", cnt); 125ff94bc40SHeiko Schocher dbg_lp("committing %d cnodes", cnt); 126ff94bc40SHeiko Schocher ubifs_assert(cnt == c->dirty_nn_cnt + c->dirty_pn_cnt); 127ff94bc40SHeiko Schocher return cnt; 128ff94bc40SHeiko Schocher } 129ff94bc40SHeiko Schocher 130ff94bc40SHeiko Schocher /** 131ff94bc40SHeiko Schocher * upd_ltab - update LPT LEB properties. 132ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 133ff94bc40SHeiko Schocher * @lnum: LEB number 134ff94bc40SHeiko Schocher * @free: amount of free space 135ff94bc40SHeiko Schocher * @dirty: amount of dirty space to add 136ff94bc40SHeiko Schocher */ 137ff94bc40SHeiko Schocher static void upd_ltab(struct ubifs_info *c, int lnum, int free, int dirty) 138ff94bc40SHeiko Schocher { 139ff94bc40SHeiko Schocher dbg_lp("LEB %d free %d dirty %d to %d +%d", 140ff94bc40SHeiko Schocher lnum, c->ltab[lnum - c->lpt_first].free, 141ff94bc40SHeiko Schocher c->ltab[lnum - c->lpt_first].dirty, free, dirty); 142ff94bc40SHeiko Schocher ubifs_assert(lnum >= c->lpt_first && lnum <= c->lpt_last); 143ff94bc40SHeiko Schocher c->ltab[lnum - c->lpt_first].free = free; 144ff94bc40SHeiko Schocher c->ltab[lnum - c->lpt_first].dirty += dirty; 145ff94bc40SHeiko Schocher } 146ff94bc40SHeiko Schocher 147ff94bc40SHeiko Schocher /** 148ff94bc40SHeiko Schocher * alloc_lpt_leb - allocate an LPT LEB that is empty. 149ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 150ff94bc40SHeiko Schocher * @lnum: LEB number is passed and returned here 151ff94bc40SHeiko Schocher * 152ff94bc40SHeiko Schocher * This function finds the next empty LEB in the ltab starting from @lnum. If a 153ff94bc40SHeiko Schocher * an empty LEB is found it is returned in @lnum and the function returns %0. 154ff94bc40SHeiko Schocher * Otherwise the function returns -ENOSPC. Note however, that LPT is designed 155ff94bc40SHeiko Schocher * never to run out of space. 156ff94bc40SHeiko Schocher */ 157ff94bc40SHeiko Schocher static int alloc_lpt_leb(struct ubifs_info *c, int *lnum) 158ff94bc40SHeiko Schocher { 159ff94bc40SHeiko Schocher int i, n; 160ff94bc40SHeiko Schocher 161ff94bc40SHeiko Schocher n = *lnum - c->lpt_first + 1; 162ff94bc40SHeiko Schocher for (i = n; i < c->lpt_lebs; i++) { 163ff94bc40SHeiko Schocher if (c->ltab[i].tgc || c->ltab[i].cmt) 164ff94bc40SHeiko Schocher continue; 165ff94bc40SHeiko Schocher if (c->ltab[i].free == c->leb_size) { 166ff94bc40SHeiko Schocher c->ltab[i].cmt = 1; 167ff94bc40SHeiko Schocher *lnum = i + c->lpt_first; 168ff94bc40SHeiko Schocher return 0; 169ff94bc40SHeiko Schocher } 170ff94bc40SHeiko Schocher } 171ff94bc40SHeiko Schocher 172ff94bc40SHeiko Schocher for (i = 0; i < n; i++) { 173ff94bc40SHeiko Schocher if (c->ltab[i].tgc || c->ltab[i].cmt) 174ff94bc40SHeiko Schocher continue; 175ff94bc40SHeiko Schocher if (c->ltab[i].free == c->leb_size) { 176ff94bc40SHeiko Schocher c->ltab[i].cmt = 1; 177ff94bc40SHeiko Schocher *lnum = i + c->lpt_first; 178ff94bc40SHeiko Schocher return 0; 179ff94bc40SHeiko Schocher } 180ff94bc40SHeiko Schocher } 181ff94bc40SHeiko Schocher return -ENOSPC; 182ff94bc40SHeiko Schocher } 183ff94bc40SHeiko Schocher 184ff94bc40SHeiko Schocher /** 185ff94bc40SHeiko Schocher * layout_cnodes - layout cnodes for commit. 186ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 187ff94bc40SHeiko Schocher * 188ff94bc40SHeiko Schocher * This function returns %0 on success and a negative error code on failure. 189ff94bc40SHeiko Schocher */ 190ff94bc40SHeiko Schocher static int layout_cnodes(struct ubifs_info *c) 191ff94bc40SHeiko Schocher { 192ff94bc40SHeiko Schocher int lnum, offs, len, alen, done_lsave, done_ltab, err; 193ff94bc40SHeiko Schocher struct ubifs_cnode *cnode; 194ff94bc40SHeiko Schocher 195ff94bc40SHeiko Schocher err = dbg_chk_lpt_sz(c, 0, 0); 196ff94bc40SHeiko Schocher if (err) 197ff94bc40SHeiko Schocher return err; 198ff94bc40SHeiko Schocher cnode = c->lpt_cnext; 199ff94bc40SHeiko Schocher if (!cnode) 200ff94bc40SHeiko Schocher return 0; 201ff94bc40SHeiko Schocher lnum = c->nhead_lnum; 202ff94bc40SHeiko Schocher offs = c->nhead_offs; 203ff94bc40SHeiko Schocher /* Try to place lsave and ltab nicely */ 204ff94bc40SHeiko Schocher done_lsave = !c->big_lpt; 205ff94bc40SHeiko Schocher done_ltab = 0; 206ff94bc40SHeiko Schocher if (!done_lsave && offs + c->lsave_sz <= c->leb_size) { 207ff94bc40SHeiko Schocher done_lsave = 1; 208ff94bc40SHeiko Schocher c->lsave_lnum = lnum; 209ff94bc40SHeiko Schocher c->lsave_offs = offs; 210ff94bc40SHeiko Schocher offs += c->lsave_sz; 211ff94bc40SHeiko Schocher dbg_chk_lpt_sz(c, 1, c->lsave_sz); 212ff94bc40SHeiko Schocher } 213ff94bc40SHeiko Schocher 214ff94bc40SHeiko Schocher if (offs + c->ltab_sz <= c->leb_size) { 215ff94bc40SHeiko Schocher done_ltab = 1; 216ff94bc40SHeiko Schocher c->ltab_lnum = lnum; 217ff94bc40SHeiko Schocher c->ltab_offs = offs; 218ff94bc40SHeiko Schocher offs += c->ltab_sz; 219ff94bc40SHeiko Schocher dbg_chk_lpt_sz(c, 1, c->ltab_sz); 220ff94bc40SHeiko Schocher } 221ff94bc40SHeiko Schocher 222ff94bc40SHeiko Schocher do { 223ff94bc40SHeiko Schocher if (cnode->level) { 224ff94bc40SHeiko Schocher len = c->nnode_sz; 225ff94bc40SHeiko Schocher c->dirty_nn_cnt -= 1; 226ff94bc40SHeiko Schocher } else { 227ff94bc40SHeiko Schocher len = c->pnode_sz; 228ff94bc40SHeiko Schocher c->dirty_pn_cnt -= 1; 229ff94bc40SHeiko Schocher } 230ff94bc40SHeiko Schocher while (offs + len > c->leb_size) { 231ff94bc40SHeiko Schocher alen = ALIGN(offs, c->min_io_size); 232ff94bc40SHeiko Schocher upd_ltab(c, lnum, c->leb_size - alen, alen - offs); 233ff94bc40SHeiko Schocher dbg_chk_lpt_sz(c, 2, c->leb_size - offs); 234ff94bc40SHeiko Schocher err = alloc_lpt_leb(c, &lnum); 235ff94bc40SHeiko Schocher if (err) 236ff94bc40SHeiko Schocher goto no_space; 237ff94bc40SHeiko Schocher offs = 0; 238ff94bc40SHeiko Schocher ubifs_assert(lnum >= c->lpt_first && 239ff94bc40SHeiko Schocher lnum <= c->lpt_last); 240ff94bc40SHeiko Schocher /* Try to place lsave and ltab nicely */ 241ff94bc40SHeiko Schocher if (!done_lsave) { 242ff94bc40SHeiko Schocher done_lsave = 1; 243ff94bc40SHeiko Schocher c->lsave_lnum = lnum; 244ff94bc40SHeiko Schocher c->lsave_offs = offs; 245ff94bc40SHeiko Schocher offs += c->lsave_sz; 246ff94bc40SHeiko Schocher dbg_chk_lpt_sz(c, 1, c->lsave_sz); 247ff94bc40SHeiko Schocher continue; 248ff94bc40SHeiko Schocher } 249ff94bc40SHeiko Schocher if (!done_ltab) { 250ff94bc40SHeiko Schocher done_ltab = 1; 251ff94bc40SHeiko Schocher c->ltab_lnum = lnum; 252ff94bc40SHeiko Schocher c->ltab_offs = offs; 253ff94bc40SHeiko Schocher offs += c->ltab_sz; 254ff94bc40SHeiko Schocher dbg_chk_lpt_sz(c, 1, c->ltab_sz); 255ff94bc40SHeiko Schocher continue; 256ff94bc40SHeiko Schocher } 257ff94bc40SHeiko Schocher break; 258ff94bc40SHeiko Schocher } 259ff94bc40SHeiko Schocher if (cnode->parent) { 260ff94bc40SHeiko Schocher cnode->parent->nbranch[cnode->iip].lnum = lnum; 261ff94bc40SHeiko Schocher cnode->parent->nbranch[cnode->iip].offs = offs; 262ff94bc40SHeiko Schocher } else { 263ff94bc40SHeiko Schocher c->lpt_lnum = lnum; 264ff94bc40SHeiko Schocher c->lpt_offs = offs; 265ff94bc40SHeiko Schocher } 266ff94bc40SHeiko Schocher offs += len; 267ff94bc40SHeiko Schocher dbg_chk_lpt_sz(c, 1, len); 268ff94bc40SHeiko Schocher cnode = cnode->cnext; 269ff94bc40SHeiko Schocher } while (cnode && cnode != c->lpt_cnext); 270ff94bc40SHeiko Schocher 271ff94bc40SHeiko Schocher /* Make sure to place LPT's save table */ 272ff94bc40SHeiko Schocher if (!done_lsave) { 273ff94bc40SHeiko Schocher if (offs + c->lsave_sz > c->leb_size) { 274ff94bc40SHeiko Schocher alen = ALIGN(offs, c->min_io_size); 275ff94bc40SHeiko Schocher upd_ltab(c, lnum, c->leb_size - alen, alen - offs); 276ff94bc40SHeiko Schocher dbg_chk_lpt_sz(c, 2, c->leb_size - offs); 277ff94bc40SHeiko Schocher err = alloc_lpt_leb(c, &lnum); 278ff94bc40SHeiko Schocher if (err) 279ff94bc40SHeiko Schocher goto no_space; 280ff94bc40SHeiko Schocher offs = 0; 281ff94bc40SHeiko Schocher ubifs_assert(lnum >= c->lpt_first && 282ff94bc40SHeiko Schocher lnum <= c->lpt_last); 283ff94bc40SHeiko Schocher } 284ff94bc40SHeiko Schocher done_lsave = 1; 285ff94bc40SHeiko Schocher c->lsave_lnum = lnum; 286ff94bc40SHeiko Schocher c->lsave_offs = offs; 287ff94bc40SHeiko Schocher offs += c->lsave_sz; 288ff94bc40SHeiko Schocher dbg_chk_lpt_sz(c, 1, c->lsave_sz); 289ff94bc40SHeiko Schocher } 290ff94bc40SHeiko Schocher 291ff94bc40SHeiko Schocher /* Make sure to place LPT's own lprops table */ 292ff94bc40SHeiko Schocher if (!done_ltab) { 293ff94bc40SHeiko Schocher if (offs + c->ltab_sz > c->leb_size) { 294ff94bc40SHeiko Schocher alen = ALIGN(offs, c->min_io_size); 295ff94bc40SHeiko Schocher upd_ltab(c, lnum, c->leb_size - alen, alen - offs); 296ff94bc40SHeiko Schocher dbg_chk_lpt_sz(c, 2, c->leb_size - offs); 297ff94bc40SHeiko Schocher err = alloc_lpt_leb(c, &lnum); 298ff94bc40SHeiko Schocher if (err) 299ff94bc40SHeiko Schocher goto no_space; 300ff94bc40SHeiko Schocher offs = 0; 301ff94bc40SHeiko Schocher ubifs_assert(lnum >= c->lpt_first && 302ff94bc40SHeiko Schocher lnum <= c->lpt_last); 303ff94bc40SHeiko Schocher } 304ff94bc40SHeiko Schocher c->ltab_lnum = lnum; 305ff94bc40SHeiko Schocher c->ltab_offs = offs; 306ff94bc40SHeiko Schocher offs += c->ltab_sz; 307ff94bc40SHeiko Schocher dbg_chk_lpt_sz(c, 1, c->ltab_sz); 308ff94bc40SHeiko Schocher } 309ff94bc40SHeiko Schocher 310ff94bc40SHeiko Schocher alen = ALIGN(offs, c->min_io_size); 311ff94bc40SHeiko Schocher upd_ltab(c, lnum, c->leb_size - alen, alen - offs); 312ff94bc40SHeiko Schocher dbg_chk_lpt_sz(c, 4, alen - offs); 313ff94bc40SHeiko Schocher err = dbg_chk_lpt_sz(c, 3, alen); 314ff94bc40SHeiko Schocher if (err) 315ff94bc40SHeiko Schocher return err; 316ff94bc40SHeiko Schocher return 0; 317ff94bc40SHeiko Schocher 318ff94bc40SHeiko Schocher no_space: 319*0195a7bbSHeiko Schocher ubifs_err(c, "LPT out of space at LEB %d:%d needing %d, done_ltab %d, done_lsave %d", 320ff94bc40SHeiko Schocher lnum, offs, len, done_ltab, done_lsave); 321ff94bc40SHeiko Schocher ubifs_dump_lpt_info(c); 322ff94bc40SHeiko Schocher ubifs_dump_lpt_lebs(c); 323ff94bc40SHeiko Schocher dump_stack(); 324ff94bc40SHeiko Schocher return err; 325ff94bc40SHeiko Schocher } 326ff94bc40SHeiko Schocher 327ff94bc40SHeiko Schocher #ifndef __UBOOT__ 328ff94bc40SHeiko Schocher /** 329ff94bc40SHeiko Schocher * realloc_lpt_leb - allocate an LPT LEB that is empty. 330ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 331ff94bc40SHeiko Schocher * @lnum: LEB number is passed and returned here 332ff94bc40SHeiko Schocher * 333ff94bc40SHeiko Schocher * This function duplicates exactly the results of the function alloc_lpt_leb. 334ff94bc40SHeiko Schocher * It is used during end commit to reallocate the same LEB numbers that were 335ff94bc40SHeiko Schocher * allocated by alloc_lpt_leb during start commit. 336ff94bc40SHeiko Schocher * 337ff94bc40SHeiko Schocher * This function finds the next LEB that was allocated by the alloc_lpt_leb 338ff94bc40SHeiko Schocher * function starting from @lnum. If a LEB is found it is returned in @lnum and 339ff94bc40SHeiko Schocher * the function returns %0. Otherwise the function returns -ENOSPC. 340ff94bc40SHeiko Schocher * Note however, that LPT is designed never to run out of space. 341ff94bc40SHeiko Schocher */ 342ff94bc40SHeiko Schocher static int realloc_lpt_leb(struct ubifs_info *c, int *lnum) 343ff94bc40SHeiko Schocher { 344ff94bc40SHeiko Schocher int i, n; 345ff94bc40SHeiko Schocher 346ff94bc40SHeiko Schocher n = *lnum - c->lpt_first + 1; 347ff94bc40SHeiko Schocher for (i = n; i < c->lpt_lebs; i++) 348ff94bc40SHeiko Schocher if (c->ltab[i].cmt) { 349ff94bc40SHeiko Schocher c->ltab[i].cmt = 0; 350ff94bc40SHeiko Schocher *lnum = i + c->lpt_first; 351ff94bc40SHeiko Schocher return 0; 352ff94bc40SHeiko Schocher } 353ff94bc40SHeiko Schocher 354ff94bc40SHeiko Schocher for (i = 0; i < n; i++) 355ff94bc40SHeiko Schocher if (c->ltab[i].cmt) { 356ff94bc40SHeiko Schocher c->ltab[i].cmt = 0; 357ff94bc40SHeiko Schocher *lnum = i + c->lpt_first; 358ff94bc40SHeiko Schocher return 0; 359ff94bc40SHeiko Schocher } 360ff94bc40SHeiko Schocher return -ENOSPC; 361ff94bc40SHeiko Schocher } 362ff94bc40SHeiko Schocher 363ff94bc40SHeiko Schocher /** 364ff94bc40SHeiko Schocher * write_cnodes - write cnodes for commit. 365ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 366ff94bc40SHeiko Schocher * 367ff94bc40SHeiko Schocher * This function returns %0 on success and a negative error code on failure. 368ff94bc40SHeiko Schocher */ 369ff94bc40SHeiko Schocher static int write_cnodes(struct ubifs_info *c) 370ff94bc40SHeiko Schocher { 371ff94bc40SHeiko Schocher int lnum, offs, len, from, err, wlen, alen, done_ltab, done_lsave; 372ff94bc40SHeiko Schocher struct ubifs_cnode *cnode; 373ff94bc40SHeiko Schocher void *buf = c->lpt_buf; 374ff94bc40SHeiko Schocher 375ff94bc40SHeiko Schocher cnode = c->lpt_cnext; 376ff94bc40SHeiko Schocher if (!cnode) 377ff94bc40SHeiko Schocher return 0; 378ff94bc40SHeiko Schocher lnum = c->nhead_lnum; 379ff94bc40SHeiko Schocher offs = c->nhead_offs; 380ff94bc40SHeiko Schocher from = offs; 381ff94bc40SHeiko Schocher /* Ensure empty LEB is unmapped */ 382ff94bc40SHeiko Schocher if (offs == 0) { 383ff94bc40SHeiko Schocher err = ubifs_leb_unmap(c, lnum); 384ff94bc40SHeiko Schocher if (err) 385ff94bc40SHeiko Schocher return err; 386ff94bc40SHeiko Schocher } 387ff94bc40SHeiko Schocher /* Try to place lsave and ltab nicely */ 388ff94bc40SHeiko Schocher done_lsave = !c->big_lpt; 389ff94bc40SHeiko Schocher done_ltab = 0; 390ff94bc40SHeiko Schocher if (!done_lsave && offs + c->lsave_sz <= c->leb_size) { 391ff94bc40SHeiko Schocher done_lsave = 1; 392ff94bc40SHeiko Schocher ubifs_pack_lsave(c, buf + offs, c->lsave); 393ff94bc40SHeiko Schocher offs += c->lsave_sz; 394ff94bc40SHeiko Schocher dbg_chk_lpt_sz(c, 1, c->lsave_sz); 395ff94bc40SHeiko Schocher } 396ff94bc40SHeiko Schocher 397ff94bc40SHeiko Schocher if (offs + c->ltab_sz <= c->leb_size) { 398ff94bc40SHeiko Schocher done_ltab = 1; 399ff94bc40SHeiko Schocher ubifs_pack_ltab(c, buf + offs, c->ltab_cmt); 400ff94bc40SHeiko Schocher offs += c->ltab_sz; 401ff94bc40SHeiko Schocher dbg_chk_lpt_sz(c, 1, c->ltab_sz); 402ff94bc40SHeiko Schocher } 403ff94bc40SHeiko Schocher 404ff94bc40SHeiko Schocher /* Loop for each cnode */ 405ff94bc40SHeiko Schocher do { 406ff94bc40SHeiko Schocher if (cnode->level) 407ff94bc40SHeiko Schocher len = c->nnode_sz; 408ff94bc40SHeiko Schocher else 409ff94bc40SHeiko Schocher len = c->pnode_sz; 410ff94bc40SHeiko Schocher while (offs + len > c->leb_size) { 411ff94bc40SHeiko Schocher wlen = offs - from; 412ff94bc40SHeiko Schocher if (wlen) { 413ff94bc40SHeiko Schocher alen = ALIGN(wlen, c->min_io_size); 414ff94bc40SHeiko Schocher memset(buf + offs, 0xff, alen - wlen); 415ff94bc40SHeiko Schocher err = ubifs_leb_write(c, lnum, buf + from, from, 416ff94bc40SHeiko Schocher alen); 417ff94bc40SHeiko Schocher if (err) 418ff94bc40SHeiko Schocher return err; 419ff94bc40SHeiko Schocher } 420ff94bc40SHeiko Schocher dbg_chk_lpt_sz(c, 2, c->leb_size - offs); 421ff94bc40SHeiko Schocher err = realloc_lpt_leb(c, &lnum); 422ff94bc40SHeiko Schocher if (err) 423ff94bc40SHeiko Schocher goto no_space; 424ff94bc40SHeiko Schocher offs = from = 0; 425ff94bc40SHeiko Schocher ubifs_assert(lnum >= c->lpt_first && 426ff94bc40SHeiko Schocher lnum <= c->lpt_last); 427ff94bc40SHeiko Schocher err = ubifs_leb_unmap(c, lnum); 428ff94bc40SHeiko Schocher if (err) 429ff94bc40SHeiko Schocher return err; 430ff94bc40SHeiko Schocher /* Try to place lsave and ltab nicely */ 431ff94bc40SHeiko Schocher if (!done_lsave) { 432ff94bc40SHeiko Schocher done_lsave = 1; 433ff94bc40SHeiko Schocher ubifs_pack_lsave(c, buf + offs, c->lsave); 434ff94bc40SHeiko Schocher offs += c->lsave_sz; 435ff94bc40SHeiko Schocher dbg_chk_lpt_sz(c, 1, c->lsave_sz); 436ff94bc40SHeiko Schocher continue; 437ff94bc40SHeiko Schocher } 438ff94bc40SHeiko Schocher if (!done_ltab) { 439ff94bc40SHeiko Schocher done_ltab = 1; 440ff94bc40SHeiko Schocher ubifs_pack_ltab(c, buf + offs, c->ltab_cmt); 441ff94bc40SHeiko Schocher offs += c->ltab_sz; 442ff94bc40SHeiko Schocher dbg_chk_lpt_sz(c, 1, c->ltab_sz); 443ff94bc40SHeiko Schocher continue; 444ff94bc40SHeiko Schocher } 445ff94bc40SHeiko Schocher break; 446ff94bc40SHeiko Schocher } 447ff94bc40SHeiko Schocher if (cnode->level) 448ff94bc40SHeiko Schocher ubifs_pack_nnode(c, buf + offs, 449ff94bc40SHeiko Schocher (struct ubifs_nnode *)cnode); 450ff94bc40SHeiko Schocher else 451ff94bc40SHeiko Schocher ubifs_pack_pnode(c, buf + offs, 452ff94bc40SHeiko Schocher (struct ubifs_pnode *)cnode); 453ff94bc40SHeiko Schocher /* 454ff94bc40SHeiko Schocher * The reason for the barriers is the same as in case of TNC. 455ff94bc40SHeiko Schocher * See comment in 'write_index()'. 'dirty_cow_nnode()' and 456ff94bc40SHeiko Schocher * 'dirty_cow_pnode()' are the functions for which this is 457ff94bc40SHeiko Schocher * important. 458ff94bc40SHeiko Schocher */ 459ff94bc40SHeiko Schocher clear_bit(DIRTY_CNODE, &cnode->flags); 460*0195a7bbSHeiko Schocher smp_mb__before_atomic(); 461ff94bc40SHeiko Schocher clear_bit(COW_CNODE, &cnode->flags); 462*0195a7bbSHeiko Schocher smp_mb__after_atomic(); 463ff94bc40SHeiko Schocher offs += len; 464ff94bc40SHeiko Schocher dbg_chk_lpt_sz(c, 1, len); 465ff94bc40SHeiko Schocher cnode = cnode->cnext; 466ff94bc40SHeiko Schocher } while (cnode && cnode != c->lpt_cnext); 467ff94bc40SHeiko Schocher 468ff94bc40SHeiko Schocher /* Make sure to place LPT's save table */ 469ff94bc40SHeiko Schocher if (!done_lsave) { 470ff94bc40SHeiko Schocher if (offs + c->lsave_sz > c->leb_size) { 471ff94bc40SHeiko Schocher wlen = offs - from; 472ff94bc40SHeiko Schocher alen = ALIGN(wlen, c->min_io_size); 473ff94bc40SHeiko Schocher memset(buf + offs, 0xff, alen - wlen); 474ff94bc40SHeiko Schocher err = ubifs_leb_write(c, lnum, buf + from, from, alen); 475ff94bc40SHeiko Schocher if (err) 476ff94bc40SHeiko Schocher return err; 477ff94bc40SHeiko Schocher dbg_chk_lpt_sz(c, 2, c->leb_size - offs); 478ff94bc40SHeiko Schocher err = realloc_lpt_leb(c, &lnum); 479ff94bc40SHeiko Schocher if (err) 480ff94bc40SHeiko Schocher goto no_space; 481ff94bc40SHeiko Schocher offs = from = 0; 482ff94bc40SHeiko Schocher ubifs_assert(lnum >= c->lpt_first && 483ff94bc40SHeiko Schocher lnum <= c->lpt_last); 484ff94bc40SHeiko Schocher err = ubifs_leb_unmap(c, lnum); 485ff94bc40SHeiko Schocher if (err) 486ff94bc40SHeiko Schocher return err; 487ff94bc40SHeiko Schocher } 488ff94bc40SHeiko Schocher done_lsave = 1; 489ff94bc40SHeiko Schocher ubifs_pack_lsave(c, buf + offs, c->lsave); 490ff94bc40SHeiko Schocher offs += c->lsave_sz; 491ff94bc40SHeiko Schocher dbg_chk_lpt_sz(c, 1, c->lsave_sz); 492ff94bc40SHeiko Schocher } 493ff94bc40SHeiko Schocher 494ff94bc40SHeiko Schocher /* Make sure to place LPT's own lprops table */ 495ff94bc40SHeiko Schocher if (!done_ltab) { 496ff94bc40SHeiko Schocher if (offs + c->ltab_sz > c->leb_size) { 497ff94bc40SHeiko Schocher wlen = offs - from; 498ff94bc40SHeiko Schocher alen = ALIGN(wlen, c->min_io_size); 499ff94bc40SHeiko Schocher memset(buf + offs, 0xff, alen - wlen); 500ff94bc40SHeiko Schocher err = ubifs_leb_write(c, lnum, buf + from, from, alen); 501ff94bc40SHeiko Schocher if (err) 502ff94bc40SHeiko Schocher return err; 503ff94bc40SHeiko Schocher dbg_chk_lpt_sz(c, 2, c->leb_size - offs); 504ff94bc40SHeiko Schocher err = realloc_lpt_leb(c, &lnum); 505ff94bc40SHeiko Schocher if (err) 506ff94bc40SHeiko Schocher goto no_space; 507ff94bc40SHeiko Schocher offs = from = 0; 508ff94bc40SHeiko Schocher ubifs_assert(lnum >= c->lpt_first && 509ff94bc40SHeiko Schocher lnum <= c->lpt_last); 510ff94bc40SHeiko Schocher err = ubifs_leb_unmap(c, lnum); 511ff94bc40SHeiko Schocher if (err) 512ff94bc40SHeiko Schocher return err; 513ff94bc40SHeiko Schocher } 514ff94bc40SHeiko Schocher ubifs_pack_ltab(c, buf + offs, c->ltab_cmt); 515ff94bc40SHeiko Schocher offs += c->ltab_sz; 516ff94bc40SHeiko Schocher dbg_chk_lpt_sz(c, 1, c->ltab_sz); 517ff94bc40SHeiko Schocher } 518ff94bc40SHeiko Schocher 519ff94bc40SHeiko Schocher /* Write remaining data in buffer */ 520ff94bc40SHeiko Schocher wlen = offs - from; 521ff94bc40SHeiko Schocher alen = ALIGN(wlen, c->min_io_size); 522ff94bc40SHeiko Schocher memset(buf + offs, 0xff, alen - wlen); 523ff94bc40SHeiko Schocher err = ubifs_leb_write(c, lnum, buf + from, from, alen); 524ff94bc40SHeiko Schocher if (err) 525ff94bc40SHeiko Schocher return err; 526ff94bc40SHeiko Schocher 527ff94bc40SHeiko Schocher dbg_chk_lpt_sz(c, 4, alen - wlen); 528ff94bc40SHeiko Schocher err = dbg_chk_lpt_sz(c, 3, ALIGN(offs, c->min_io_size)); 529ff94bc40SHeiko Schocher if (err) 530ff94bc40SHeiko Schocher return err; 531ff94bc40SHeiko Schocher 532ff94bc40SHeiko Schocher c->nhead_lnum = lnum; 533ff94bc40SHeiko Schocher c->nhead_offs = ALIGN(offs, c->min_io_size); 534ff94bc40SHeiko Schocher 535ff94bc40SHeiko Schocher dbg_lp("LPT root is at %d:%d", c->lpt_lnum, c->lpt_offs); 536ff94bc40SHeiko Schocher dbg_lp("LPT head is at %d:%d", c->nhead_lnum, c->nhead_offs); 537ff94bc40SHeiko Schocher dbg_lp("LPT ltab is at %d:%d", c->ltab_lnum, c->ltab_offs); 538ff94bc40SHeiko Schocher if (c->big_lpt) 539ff94bc40SHeiko Schocher dbg_lp("LPT lsave is at %d:%d", c->lsave_lnum, c->lsave_offs); 540ff94bc40SHeiko Schocher 541ff94bc40SHeiko Schocher return 0; 542ff94bc40SHeiko Schocher 543ff94bc40SHeiko Schocher no_space: 544*0195a7bbSHeiko Schocher ubifs_err(c, "LPT out of space mismatch at LEB %d:%d needing %d, done_ltab %d, done_lsave %d", 545ff94bc40SHeiko Schocher lnum, offs, len, done_ltab, done_lsave); 546ff94bc40SHeiko Schocher ubifs_dump_lpt_info(c); 547ff94bc40SHeiko Schocher ubifs_dump_lpt_lebs(c); 548ff94bc40SHeiko Schocher dump_stack(); 549ff94bc40SHeiko Schocher return err; 550ff94bc40SHeiko Schocher } 551ff94bc40SHeiko Schocher #endif 552ff94bc40SHeiko Schocher 553ff94bc40SHeiko Schocher /** 554ff94bc40SHeiko Schocher * next_pnode_to_dirty - find next pnode to dirty. 555ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 556ff94bc40SHeiko Schocher * @pnode: pnode 557ff94bc40SHeiko Schocher * 558ff94bc40SHeiko Schocher * This function returns the next pnode to dirty or %NULL if there are no more 559ff94bc40SHeiko Schocher * pnodes. Note that pnodes that have never been written (lnum == 0) are 560ff94bc40SHeiko Schocher * skipped. 561ff94bc40SHeiko Schocher */ 562ff94bc40SHeiko Schocher static struct ubifs_pnode *next_pnode_to_dirty(struct ubifs_info *c, 563ff94bc40SHeiko Schocher struct ubifs_pnode *pnode) 564ff94bc40SHeiko Schocher { 565ff94bc40SHeiko Schocher struct ubifs_nnode *nnode; 566ff94bc40SHeiko Schocher int iip; 567ff94bc40SHeiko Schocher 568ff94bc40SHeiko Schocher /* Try to go right */ 569ff94bc40SHeiko Schocher nnode = pnode->parent; 570ff94bc40SHeiko Schocher for (iip = pnode->iip + 1; iip < UBIFS_LPT_FANOUT; iip++) { 571ff94bc40SHeiko Schocher if (nnode->nbranch[iip].lnum) 572ff94bc40SHeiko Schocher return ubifs_get_pnode(c, nnode, iip); 573ff94bc40SHeiko Schocher } 574ff94bc40SHeiko Schocher 575ff94bc40SHeiko Schocher /* Go up while can't go right */ 576ff94bc40SHeiko Schocher do { 577ff94bc40SHeiko Schocher iip = nnode->iip + 1; 578ff94bc40SHeiko Schocher nnode = nnode->parent; 579ff94bc40SHeiko Schocher if (!nnode) 580ff94bc40SHeiko Schocher return NULL; 581ff94bc40SHeiko Schocher for (; iip < UBIFS_LPT_FANOUT; iip++) { 582ff94bc40SHeiko Schocher if (nnode->nbranch[iip].lnum) 583ff94bc40SHeiko Schocher break; 584ff94bc40SHeiko Schocher } 585ff94bc40SHeiko Schocher } while (iip >= UBIFS_LPT_FANOUT); 586ff94bc40SHeiko Schocher 587ff94bc40SHeiko Schocher /* Go right */ 588ff94bc40SHeiko Schocher nnode = ubifs_get_nnode(c, nnode, iip); 589ff94bc40SHeiko Schocher if (IS_ERR(nnode)) 590ff94bc40SHeiko Schocher return (void *)nnode; 591ff94bc40SHeiko Schocher 592ff94bc40SHeiko Schocher /* Go down to level 1 */ 593ff94bc40SHeiko Schocher while (nnode->level > 1) { 594ff94bc40SHeiko Schocher for (iip = 0; iip < UBIFS_LPT_FANOUT; iip++) { 595ff94bc40SHeiko Schocher if (nnode->nbranch[iip].lnum) 596ff94bc40SHeiko Schocher break; 597ff94bc40SHeiko Schocher } 598ff94bc40SHeiko Schocher if (iip >= UBIFS_LPT_FANOUT) { 599ff94bc40SHeiko Schocher /* 600ff94bc40SHeiko Schocher * Should not happen, but we need to keep going 601ff94bc40SHeiko Schocher * if it does. 602ff94bc40SHeiko Schocher */ 603ff94bc40SHeiko Schocher iip = 0; 604ff94bc40SHeiko Schocher } 605ff94bc40SHeiko Schocher nnode = ubifs_get_nnode(c, nnode, iip); 606ff94bc40SHeiko Schocher if (IS_ERR(nnode)) 607ff94bc40SHeiko Schocher return (void *)nnode; 608ff94bc40SHeiko Schocher } 609ff94bc40SHeiko Schocher 610ff94bc40SHeiko Schocher for (iip = 0; iip < UBIFS_LPT_FANOUT; iip++) 611ff94bc40SHeiko Schocher if (nnode->nbranch[iip].lnum) 612ff94bc40SHeiko Schocher break; 613ff94bc40SHeiko Schocher if (iip >= UBIFS_LPT_FANOUT) 614ff94bc40SHeiko Schocher /* Should not happen, but we need to keep going if it does */ 615ff94bc40SHeiko Schocher iip = 0; 616ff94bc40SHeiko Schocher return ubifs_get_pnode(c, nnode, iip); 617ff94bc40SHeiko Schocher } 618ff94bc40SHeiko Schocher 619ff94bc40SHeiko Schocher /** 620ff94bc40SHeiko Schocher * pnode_lookup - lookup a pnode in the LPT. 621ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 622ff94bc40SHeiko Schocher * @i: pnode number (0 to main_lebs - 1) 623ff94bc40SHeiko Schocher * 624ff94bc40SHeiko Schocher * This function returns a pointer to the pnode on success or a negative 625ff94bc40SHeiko Schocher * error code on failure. 626ff94bc40SHeiko Schocher */ 627ff94bc40SHeiko Schocher static struct ubifs_pnode *pnode_lookup(struct ubifs_info *c, int i) 628ff94bc40SHeiko Schocher { 629ff94bc40SHeiko Schocher int err, h, iip, shft; 630ff94bc40SHeiko Schocher struct ubifs_nnode *nnode; 631ff94bc40SHeiko Schocher 632ff94bc40SHeiko Schocher if (!c->nroot) { 633ff94bc40SHeiko Schocher err = ubifs_read_nnode(c, NULL, 0); 634ff94bc40SHeiko Schocher if (err) 635ff94bc40SHeiko Schocher return ERR_PTR(err); 636ff94bc40SHeiko Schocher } 637ff94bc40SHeiko Schocher i <<= UBIFS_LPT_FANOUT_SHIFT; 638ff94bc40SHeiko Schocher nnode = c->nroot; 639ff94bc40SHeiko Schocher shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT; 640ff94bc40SHeiko Schocher for (h = 1; h < c->lpt_hght; h++) { 641ff94bc40SHeiko Schocher iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); 642ff94bc40SHeiko Schocher shft -= UBIFS_LPT_FANOUT_SHIFT; 643ff94bc40SHeiko Schocher nnode = ubifs_get_nnode(c, nnode, iip); 644ff94bc40SHeiko Schocher if (IS_ERR(nnode)) 645ff94bc40SHeiko Schocher return ERR_CAST(nnode); 646ff94bc40SHeiko Schocher } 647ff94bc40SHeiko Schocher iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); 648ff94bc40SHeiko Schocher return ubifs_get_pnode(c, nnode, iip); 649ff94bc40SHeiko Schocher } 650ff94bc40SHeiko Schocher 651ff94bc40SHeiko Schocher /** 652ff94bc40SHeiko Schocher * add_pnode_dirt - add dirty space to LPT LEB properties. 653ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 654ff94bc40SHeiko Schocher * @pnode: pnode for which to add dirt 655ff94bc40SHeiko Schocher */ 656ff94bc40SHeiko Schocher static void add_pnode_dirt(struct ubifs_info *c, struct ubifs_pnode *pnode) 657ff94bc40SHeiko Schocher { 658ff94bc40SHeiko Schocher ubifs_add_lpt_dirt(c, pnode->parent->nbranch[pnode->iip].lnum, 659ff94bc40SHeiko Schocher c->pnode_sz); 660ff94bc40SHeiko Schocher } 661ff94bc40SHeiko Schocher 662ff94bc40SHeiko Schocher /** 663ff94bc40SHeiko Schocher * do_make_pnode_dirty - mark a pnode dirty. 664ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 665ff94bc40SHeiko Schocher * @pnode: pnode to mark dirty 666ff94bc40SHeiko Schocher */ 667ff94bc40SHeiko Schocher static void do_make_pnode_dirty(struct ubifs_info *c, struct ubifs_pnode *pnode) 668ff94bc40SHeiko Schocher { 669ff94bc40SHeiko Schocher /* Assumes cnext list is empty i.e. not called during commit */ 670ff94bc40SHeiko Schocher if (!test_and_set_bit(DIRTY_CNODE, &pnode->flags)) { 671ff94bc40SHeiko Schocher struct ubifs_nnode *nnode; 672ff94bc40SHeiko Schocher 673ff94bc40SHeiko Schocher c->dirty_pn_cnt += 1; 674ff94bc40SHeiko Schocher add_pnode_dirt(c, pnode); 675ff94bc40SHeiko Schocher /* Mark parent and ancestors dirty too */ 676ff94bc40SHeiko Schocher nnode = pnode->parent; 677ff94bc40SHeiko Schocher while (nnode) { 678ff94bc40SHeiko Schocher if (!test_and_set_bit(DIRTY_CNODE, &nnode->flags)) { 679ff94bc40SHeiko Schocher c->dirty_nn_cnt += 1; 680ff94bc40SHeiko Schocher ubifs_add_nnode_dirt(c, nnode); 681ff94bc40SHeiko Schocher nnode = nnode->parent; 682ff94bc40SHeiko Schocher } else 683ff94bc40SHeiko Schocher break; 684ff94bc40SHeiko Schocher } 685ff94bc40SHeiko Schocher } 686ff94bc40SHeiko Schocher } 687ff94bc40SHeiko Schocher 688ff94bc40SHeiko Schocher /** 689ff94bc40SHeiko Schocher * make_tree_dirty - mark the entire LEB properties tree dirty. 690ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 691ff94bc40SHeiko Schocher * 692ff94bc40SHeiko Schocher * This function is used by the "small" LPT model to cause the entire LEB 693ff94bc40SHeiko Schocher * properties tree to be written. The "small" LPT model does not use LPT 694ff94bc40SHeiko Schocher * garbage collection because it is more efficient to write the entire tree 695ff94bc40SHeiko Schocher * (because it is small). 696ff94bc40SHeiko Schocher * 697ff94bc40SHeiko Schocher * This function returns %0 on success and a negative error code on failure. 698ff94bc40SHeiko Schocher */ 699ff94bc40SHeiko Schocher static int make_tree_dirty(struct ubifs_info *c) 700ff94bc40SHeiko Schocher { 701ff94bc40SHeiko Schocher struct ubifs_pnode *pnode; 702ff94bc40SHeiko Schocher 703ff94bc40SHeiko Schocher pnode = pnode_lookup(c, 0); 704ff94bc40SHeiko Schocher if (IS_ERR(pnode)) 705ff94bc40SHeiko Schocher return PTR_ERR(pnode); 706ff94bc40SHeiko Schocher 707ff94bc40SHeiko Schocher while (pnode) { 708ff94bc40SHeiko Schocher do_make_pnode_dirty(c, pnode); 709ff94bc40SHeiko Schocher pnode = next_pnode_to_dirty(c, pnode); 710ff94bc40SHeiko Schocher if (IS_ERR(pnode)) 711ff94bc40SHeiko Schocher return PTR_ERR(pnode); 712ff94bc40SHeiko Schocher } 713ff94bc40SHeiko Schocher return 0; 714ff94bc40SHeiko Schocher } 715ff94bc40SHeiko Schocher 716ff94bc40SHeiko Schocher /** 717ff94bc40SHeiko Schocher * need_write_all - determine if the LPT area is running out of free space. 718ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 719ff94bc40SHeiko Schocher * 720ff94bc40SHeiko Schocher * This function returns %1 if the LPT area is running out of free space and %0 721ff94bc40SHeiko Schocher * if it is not. 722ff94bc40SHeiko Schocher */ 723ff94bc40SHeiko Schocher static int need_write_all(struct ubifs_info *c) 724ff94bc40SHeiko Schocher { 725ff94bc40SHeiko Schocher long long free = 0; 726ff94bc40SHeiko Schocher int i; 727ff94bc40SHeiko Schocher 728ff94bc40SHeiko Schocher for (i = 0; i < c->lpt_lebs; i++) { 729ff94bc40SHeiko Schocher if (i + c->lpt_first == c->nhead_lnum) 730ff94bc40SHeiko Schocher free += c->leb_size - c->nhead_offs; 731ff94bc40SHeiko Schocher else if (c->ltab[i].free == c->leb_size) 732ff94bc40SHeiko Schocher free += c->leb_size; 733ff94bc40SHeiko Schocher else if (c->ltab[i].free + c->ltab[i].dirty == c->leb_size) 734ff94bc40SHeiko Schocher free += c->leb_size; 735ff94bc40SHeiko Schocher } 736ff94bc40SHeiko Schocher /* Less than twice the size left */ 737ff94bc40SHeiko Schocher if (free <= c->lpt_sz * 2) 738ff94bc40SHeiko Schocher return 1; 739ff94bc40SHeiko Schocher return 0; 740ff94bc40SHeiko Schocher } 741ff94bc40SHeiko Schocher 742ff94bc40SHeiko Schocher /** 743ff94bc40SHeiko Schocher * lpt_tgc_start - start trivial garbage collection of LPT LEBs. 744ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 745ff94bc40SHeiko Schocher * 746ff94bc40SHeiko Schocher * LPT trivial garbage collection is where a LPT LEB contains only dirty and 747ff94bc40SHeiko Schocher * free space and so may be reused as soon as the next commit is completed. 748ff94bc40SHeiko Schocher * This function is called during start commit to mark LPT LEBs for trivial GC. 749ff94bc40SHeiko Schocher */ 750ff94bc40SHeiko Schocher static void lpt_tgc_start(struct ubifs_info *c) 751ff94bc40SHeiko Schocher { 752ff94bc40SHeiko Schocher int i; 753ff94bc40SHeiko Schocher 754ff94bc40SHeiko Schocher for (i = 0; i < c->lpt_lebs; i++) { 755ff94bc40SHeiko Schocher if (i + c->lpt_first == c->nhead_lnum) 756ff94bc40SHeiko Schocher continue; 757ff94bc40SHeiko Schocher if (c->ltab[i].dirty > 0 && 758ff94bc40SHeiko Schocher c->ltab[i].free + c->ltab[i].dirty == c->leb_size) { 759ff94bc40SHeiko Schocher c->ltab[i].tgc = 1; 760ff94bc40SHeiko Schocher c->ltab[i].free = c->leb_size; 761ff94bc40SHeiko Schocher c->ltab[i].dirty = 0; 762ff94bc40SHeiko Schocher dbg_lp("LEB %d", i + c->lpt_first); 763ff94bc40SHeiko Schocher } 764ff94bc40SHeiko Schocher } 765ff94bc40SHeiko Schocher } 766ff94bc40SHeiko Schocher 767ff94bc40SHeiko Schocher /** 768ff94bc40SHeiko Schocher * lpt_tgc_end - end trivial garbage collection of LPT LEBs. 769ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 770ff94bc40SHeiko Schocher * 771ff94bc40SHeiko Schocher * LPT trivial garbage collection is where a LPT LEB contains only dirty and 772ff94bc40SHeiko Schocher * free space and so may be reused as soon as the next commit is completed. 773ff94bc40SHeiko Schocher * This function is called after the commit is completed (master node has been 774ff94bc40SHeiko Schocher * written) and un-maps LPT LEBs that were marked for trivial GC. 775ff94bc40SHeiko Schocher */ 776ff94bc40SHeiko Schocher static int lpt_tgc_end(struct ubifs_info *c) 777ff94bc40SHeiko Schocher { 778ff94bc40SHeiko Schocher int i, err; 779ff94bc40SHeiko Schocher 780ff94bc40SHeiko Schocher for (i = 0; i < c->lpt_lebs; i++) 781ff94bc40SHeiko Schocher if (c->ltab[i].tgc) { 782ff94bc40SHeiko Schocher err = ubifs_leb_unmap(c, i + c->lpt_first); 783ff94bc40SHeiko Schocher if (err) 784ff94bc40SHeiko Schocher return err; 785ff94bc40SHeiko Schocher c->ltab[i].tgc = 0; 786ff94bc40SHeiko Schocher dbg_lp("LEB %d", i + c->lpt_first); 787ff94bc40SHeiko Schocher } 788ff94bc40SHeiko Schocher return 0; 789ff94bc40SHeiko Schocher } 790ff94bc40SHeiko Schocher 791ff94bc40SHeiko Schocher /** 792ff94bc40SHeiko Schocher * populate_lsave - fill the lsave array with important LEB numbers. 793ff94bc40SHeiko Schocher * @c: the UBIFS file-system description object 794ff94bc40SHeiko Schocher * 795ff94bc40SHeiko Schocher * This function is only called for the "big" model. It records a small number 796ff94bc40SHeiko Schocher * of LEB numbers of important LEBs. Important LEBs are ones that are (from 797ff94bc40SHeiko Schocher * most important to least important): empty, freeable, freeable index, dirty 798ff94bc40SHeiko Schocher * index, dirty or free. Upon mount, we read this list of LEB numbers and bring 799ff94bc40SHeiko Schocher * their pnodes into memory. That will stop us from having to scan the LPT 800ff94bc40SHeiko Schocher * straight away. For the "small" model we assume that scanning the LPT is no 801ff94bc40SHeiko Schocher * big deal. 802ff94bc40SHeiko Schocher */ 803ff94bc40SHeiko Schocher static void populate_lsave(struct ubifs_info *c) 804ff94bc40SHeiko Schocher { 805ff94bc40SHeiko Schocher struct ubifs_lprops *lprops; 806ff94bc40SHeiko Schocher struct ubifs_lpt_heap *heap; 807ff94bc40SHeiko Schocher int i, cnt = 0; 808ff94bc40SHeiko Schocher 809ff94bc40SHeiko Schocher ubifs_assert(c->big_lpt); 810ff94bc40SHeiko Schocher if (!(c->lpt_drty_flgs & LSAVE_DIRTY)) { 811ff94bc40SHeiko Schocher c->lpt_drty_flgs |= LSAVE_DIRTY; 812ff94bc40SHeiko Schocher ubifs_add_lpt_dirt(c, c->lsave_lnum, c->lsave_sz); 813ff94bc40SHeiko Schocher } 814ff94bc40SHeiko Schocher 815ff94bc40SHeiko Schocher #ifndef __UBOOT__ 816ff94bc40SHeiko Schocher if (dbg_populate_lsave(c)) 817ff94bc40SHeiko Schocher return; 818ff94bc40SHeiko Schocher #endif 819ff94bc40SHeiko Schocher 820ff94bc40SHeiko Schocher list_for_each_entry(lprops, &c->empty_list, list) { 821ff94bc40SHeiko Schocher c->lsave[cnt++] = lprops->lnum; 822ff94bc40SHeiko Schocher if (cnt >= c->lsave_cnt) 823ff94bc40SHeiko Schocher return; 824ff94bc40SHeiko Schocher } 825ff94bc40SHeiko Schocher list_for_each_entry(lprops, &c->freeable_list, list) { 826ff94bc40SHeiko Schocher c->lsave[cnt++] = lprops->lnum; 827ff94bc40SHeiko Schocher if (cnt >= c->lsave_cnt) 828ff94bc40SHeiko Schocher return; 829ff94bc40SHeiko Schocher } 830ff94bc40SHeiko Schocher list_for_each_entry(lprops, &c->frdi_idx_list, list) { 831ff94bc40SHeiko Schocher c->lsave[cnt++] = lprops->lnum; 832ff94bc40SHeiko Schocher if (cnt >= c->lsave_cnt) 833ff94bc40SHeiko Schocher return; 834ff94bc40SHeiko Schocher } 835ff94bc40SHeiko Schocher heap = &c->lpt_heap[LPROPS_DIRTY_IDX - 1]; 836ff94bc40SHeiko Schocher for (i = 0; i < heap->cnt; i++) { 837ff94bc40SHeiko Schocher c->lsave[cnt++] = heap->arr[i]->lnum; 838ff94bc40SHeiko Schocher if (cnt >= c->lsave_cnt) 839ff94bc40SHeiko Schocher return; 840ff94bc40SHeiko Schocher } 841ff94bc40SHeiko Schocher heap = &c->lpt_heap[LPROPS_DIRTY - 1]; 842ff94bc40SHeiko Schocher for (i = 0; i < heap->cnt; i++) { 843ff94bc40SHeiko Schocher c->lsave[cnt++] = heap->arr[i]->lnum; 844ff94bc40SHeiko Schocher if (cnt >= c->lsave_cnt) 845ff94bc40SHeiko Schocher return; 846ff94bc40SHeiko Schocher } 847ff94bc40SHeiko Schocher heap = &c->lpt_heap[LPROPS_FREE - 1]; 848ff94bc40SHeiko Schocher for (i = 0; i < heap->cnt; i++) { 849ff94bc40SHeiko Schocher c->lsave[cnt++] = heap->arr[i]->lnum; 850ff94bc40SHeiko Schocher if (cnt >= c->lsave_cnt) 851ff94bc40SHeiko Schocher return; 852ff94bc40SHeiko Schocher } 853ff94bc40SHeiko Schocher /* Fill it up completely */ 854ff94bc40SHeiko Schocher while (cnt < c->lsave_cnt) 855ff94bc40SHeiko Schocher c->lsave[cnt++] = c->main_first; 856ff94bc40SHeiko Schocher } 857ff94bc40SHeiko Schocher 858ff94bc40SHeiko Schocher /** 859ff94bc40SHeiko Schocher * nnode_lookup - lookup a nnode in the LPT. 860ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 861ff94bc40SHeiko Schocher * @i: nnode number 862ff94bc40SHeiko Schocher * 863ff94bc40SHeiko Schocher * This function returns a pointer to the nnode on success or a negative 864ff94bc40SHeiko Schocher * error code on failure. 865ff94bc40SHeiko Schocher */ 866ff94bc40SHeiko Schocher static struct ubifs_nnode *nnode_lookup(struct ubifs_info *c, int i) 867ff94bc40SHeiko Schocher { 868ff94bc40SHeiko Schocher int err, iip; 869ff94bc40SHeiko Schocher struct ubifs_nnode *nnode; 870ff94bc40SHeiko Schocher 871ff94bc40SHeiko Schocher if (!c->nroot) { 872ff94bc40SHeiko Schocher err = ubifs_read_nnode(c, NULL, 0); 873ff94bc40SHeiko Schocher if (err) 874ff94bc40SHeiko Schocher return ERR_PTR(err); 875ff94bc40SHeiko Schocher } 876ff94bc40SHeiko Schocher nnode = c->nroot; 877ff94bc40SHeiko Schocher while (1) { 878ff94bc40SHeiko Schocher iip = i & (UBIFS_LPT_FANOUT - 1); 879ff94bc40SHeiko Schocher i >>= UBIFS_LPT_FANOUT_SHIFT; 880ff94bc40SHeiko Schocher if (!i) 881ff94bc40SHeiko Schocher break; 882ff94bc40SHeiko Schocher nnode = ubifs_get_nnode(c, nnode, iip); 883ff94bc40SHeiko Schocher if (IS_ERR(nnode)) 884ff94bc40SHeiko Schocher return nnode; 885ff94bc40SHeiko Schocher } 886ff94bc40SHeiko Schocher return nnode; 887ff94bc40SHeiko Schocher } 888ff94bc40SHeiko Schocher 889ff94bc40SHeiko Schocher /** 890ff94bc40SHeiko Schocher * make_nnode_dirty - find a nnode and, if found, make it dirty. 891ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 892ff94bc40SHeiko Schocher * @node_num: nnode number of nnode to make dirty 893ff94bc40SHeiko Schocher * @lnum: LEB number where nnode was written 894ff94bc40SHeiko Schocher * @offs: offset where nnode was written 895ff94bc40SHeiko Schocher * 896ff94bc40SHeiko Schocher * This function is used by LPT garbage collection. LPT garbage collection is 897ff94bc40SHeiko Schocher * used only for the "big" LPT model (c->big_lpt == 1). Garbage collection 898ff94bc40SHeiko Schocher * simply involves marking all the nodes in the LEB being garbage-collected as 899ff94bc40SHeiko Schocher * dirty. The dirty nodes are written next commit, after which the LEB is free 900ff94bc40SHeiko Schocher * to be reused. 901ff94bc40SHeiko Schocher * 902ff94bc40SHeiko Schocher * This function returns %0 on success and a negative error code on failure. 903ff94bc40SHeiko Schocher */ 904ff94bc40SHeiko Schocher static int make_nnode_dirty(struct ubifs_info *c, int node_num, int lnum, 905ff94bc40SHeiko Schocher int offs) 906ff94bc40SHeiko Schocher { 907ff94bc40SHeiko Schocher struct ubifs_nnode *nnode; 908ff94bc40SHeiko Schocher 909ff94bc40SHeiko Schocher nnode = nnode_lookup(c, node_num); 910ff94bc40SHeiko Schocher if (IS_ERR(nnode)) 911ff94bc40SHeiko Schocher return PTR_ERR(nnode); 912ff94bc40SHeiko Schocher if (nnode->parent) { 913ff94bc40SHeiko Schocher struct ubifs_nbranch *branch; 914ff94bc40SHeiko Schocher 915ff94bc40SHeiko Schocher branch = &nnode->parent->nbranch[nnode->iip]; 916ff94bc40SHeiko Schocher if (branch->lnum != lnum || branch->offs != offs) 917ff94bc40SHeiko Schocher return 0; /* nnode is obsolete */ 918ff94bc40SHeiko Schocher } else if (c->lpt_lnum != lnum || c->lpt_offs != offs) 919ff94bc40SHeiko Schocher return 0; /* nnode is obsolete */ 920ff94bc40SHeiko Schocher /* Assumes cnext list is empty i.e. not called during commit */ 921ff94bc40SHeiko Schocher if (!test_and_set_bit(DIRTY_CNODE, &nnode->flags)) { 922ff94bc40SHeiko Schocher c->dirty_nn_cnt += 1; 923ff94bc40SHeiko Schocher ubifs_add_nnode_dirt(c, nnode); 924ff94bc40SHeiko Schocher /* Mark parent and ancestors dirty too */ 925ff94bc40SHeiko Schocher nnode = nnode->parent; 926ff94bc40SHeiko Schocher while (nnode) { 927ff94bc40SHeiko Schocher if (!test_and_set_bit(DIRTY_CNODE, &nnode->flags)) { 928ff94bc40SHeiko Schocher c->dirty_nn_cnt += 1; 929ff94bc40SHeiko Schocher ubifs_add_nnode_dirt(c, nnode); 930ff94bc40SHeiko Schocher nnode = nnode->parent; 931ff94bc40SHeiko Schocher } else 932ff94bc40SHeiko Schocher break; 933ff94bc40SHeiko Schocher } 934ff94bc40SHeiko Schocher } 935ff94bc40SHeiko Schocher return 0; 936ff94bc40SHeiko Schocher } 937ff94bc40SHeiko Schocher 938ff94bc40SHeiko Schocher /** 939ff94bc40SHeiko Schocher * make_pnode_dirty - find a pnode and, if found, make it dirty. 940ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 941ff94bc40SHeiko Schocher * @node_num: pnode number of pnode to make dirty 942ff94bc40SHeiko Schocher * @lnum: LEB number where pnode was written 943ff94bc40SHeiko Schocher * @offs: offset where pnode was written 944ff94bc40SHeiko Schocher * 945ff94bc40SHeiko Schocher * This function is used by LPT garbage collection. LPT garbage collection is 946ff94bc40SHeiko Schocher * used only for the "big" LPT model (c->big_lpt == 1). Garbage collection 947ff94bc40SHeiko Schocher * simply involves marking all the nodes in the LEB being garbage-collected as 948ff94bc40SHeiko Schocher * dirty. The dirty nodes are written next commit, after which the LEB is free 949ff94bc40SHeiko Schocher * to be reused. 950ff94bc40SHeiko Schocher * 951ff94bc40SHeiko Schocher * This function returns %0 on success and a negative error code on failure. 952ff94bc40SHeiko Schocher */ 953ff94bc40SHeiko Schocher static int make_pnode_dirty(struct ubifs_info *c, int node_num, int lnum, 954ff94bc40SHeiko Schocher int offs) 955ff94bc40SHeiko Schocher { 956ff94bc40SHeiko Schocher struct ubifs_pnode *pnode; 957ff94bc40SHeiko Schocher struct ubifs_nbranch *branch; 958ff94bc40SHeiko Schocher 959ff94bc40SHeiko Schocher pnode = pnode_lookup(c, node_num); 960ff94bc40SHeiko Schocher if (IS_ERR(pnode)) 961ff94bc40SHeiko Schocher return PTR_ERR(pnode); 962ff94bc40SHeiko Schocher branch = &pnode->parent->nbranch[pnode->iip]; 963ff94bc40SHeiko Schocher if (branch->lnum != lnum || branch->offs != offs) 964ff94bc40SHeiko Schocher return 0; 965ff94bc40SHeiko Schocher do_make_pnode_dirty(c, pnode); 966ff94bc40SHeiko Schocher return 0; 967ff94bc40SHeiko Schocher } 968ff94bc40SHeiko Schocher 969ff94bc40SHeiko Schocher /** 970ff94bc40SHeiko Schocher * make_ltab_dirty - make ltab node dirty. 971ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 972ff94bc40SHeiko Schocher * @lnum: LEB number where ltab was written 973ff94bc40SHeiko Schocher * @offs: offset where ltab was written 974ff94bc40SHeiko Schocher * 975ff94bc40SHeiko Schocher * This function is used by LPT garbage collection. LPT garbage collection is 976ff94bc40SHeiko Schocher * used only for the "big" LPT model (c->big_lpt == 1). Garbage collection 977ff94bc40SHeiko Schocher * simply involves marking all the nodes in the LEB being garbage-collected as 978ff94bc40SHeiko Schocher * dirty. The dirty nodes are written next commit, after which the LEB is free 979ff94bc40SHeiko Schocher * to be reused. 980ff94bc40SHeiko Schocher * 981ff94bc40SHeiko Schocher * This function returns %0 on success and a negative error code on failure. 982ff94bc40SHeiko Schocher */ 983ff94bc40SHeiko Schocher static int make_ltab_dirty(struct ubifs_info *c, int lnum, int offs) 984ff94bc40SHeiko Schocher { 985ff94bc40SHeiko Schocher if (lnum != c->ltab_lnum || offs != c->ltab_offs) 986ff94bc40SHeiko Schocher return 0; /* This ltab node is obsolete */ 987ff94bc40SHeiko Schocher if (!(c->lpt_drty_flgs & LTAB_DIRTY)) { 988ff94bc40SHeiko Schocher c->lpt_drty_flgs |= LTAB_DIRTY; 989ff94bc40SHeiko Schocher ubifs_add_lpt_dirt(c, c->ltab_lnum, c->ltab_sz); 990ff94bc40SHeiko Schocher } 991ff94bc40SHeiko Schocher return 0; 992ff94bc40SHeiko Schocher } 993ff94bc40SHeiko Schocher 994ff94bc40SHeiko Schocher /** 995ff94bc40SHeiko Schocher * make_lsave_dirty - make lsave node dirty. 996ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 997ff94bc40SHeiko Schocher * @lnum: LEB number where lsave was written 998ff94bc40SHeiko Schocher * @offs: offset where lsave was written 999ff94bc40SHeiko Schocher * 1000ff94bc40SHeiko Schocher * This function is used by LPT garbage collection. LPT garbage collection is 1001ff94bc40SHeiko Schocher * used only for the "big" LPT model (c->big_lpt == 1). Garbage collection 1002ff94bc40SHeiko Schocher * simply involves marking all the nodes in the LEB being garbage-collected as 1003ff94bc40SHeiko Schocher * dirty. The dirty nodes are written next commit, after which the LEB is free 1004ff94bc40SHeiko Schocher * to be reused. 1005ff94bc40SHeiko Schocher * 1006ff94bc40SHeiko Schocher * This function returns %0 on success and a negative error code on failure. 1007ff94bc40SHeiko Schocher */ 1008ff94bc40SHeiko Schocher static int make_lsave_dirty(struct ubifs_info *c, int lnum, int offs) 1009ff94bc40SHeiko Schocher { 1010ff94bc40SHeiko Schocher if (lnum != c->lsave_lnum || offs != c->lsave_offs) 1011ff94bc40SHeiko Schocher return 0; /* This lsave node is obsolete */ 1012ff94bc40SHeiko Schocher if (!(c->lpt_drty_flgs & LSAVE_DIRTY)) { 1013ff94bc40SHeiko Schocher c->lpt_drty_flgs |= LSAVE_DIRTY; 1014ff94bc40SHeiko Schocher ubifs_add_lpt_dirt(c, c->lsave_lnum, c->lsave_sz); 1015ff94bc40SHeiko Schocher } 1016ff94bc40SHeiko Schocher return 0; 1017ff94bc40SHeiko Schocher } 1018ff94bc40SHeiko Schocher 1019ff94bc40SHeiko Schocher /** 1020ff94bc40SHeiko Schocher * make_node_dirty - make node dirty. 1021ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 1022ff94bc40SHeiko Schocher * @node_type: LPT node type 1023ff94bc40SHeiko Schocher * @node_num: node number 1024ff94bc40SHeiko Schocher * @lnum: LEB number where node was written 1025ff94bc40SHeiko Schocher * @offs: offset where node was written 1026ff94bc40SHeiko Schocher * 1027ff94bc40SHeiko Schocher * This function is used by LPT garbage collection. LPT garbage collection is 1028ff94bc40SHeiko Schocher * used only for the "big" LPT model (c->big_lpt == 1). Garbage collection 1029ff94bc40SHeiko Schocher * simply involves marking all the nodes in the LEB being garbage-collected as 1030ff94bc40SHeiko Schocher * dirty. The dirty nodes are written next commit, after which the LEB is free 1031ff94bc40SHeiko Schocher * to be reused. 1032ff94bc40SHeiko Schocher * 1033ff94bc40SHeiko Schocher * This function returns %0 on success and a negative error code on failure. 1034ff94bc40SHeiko Schocher */ 1035ff94bc40SHeiko Schocher static int make_node_dirty(struct ubifs_info *c, int node_type, int node_num, 1036ff94bc40SHeiko Schocher int lnum, int offs) 1037ff94bc40SHeiko Schocher { 1038ff94bc40SHeiko Schocher switch (node_type) { 1039ff94bc40SHeiko Schocher case UBIFS_LPT_NNODE: 1040ff94bc40SHeiko Schocher return make_nnode_dirty(c, node_num, lnum, offs); 1041ff94bc40SHeiko Schocher case UBIFS_LPT_PNODE: 1042ff94bc40SHeiko Schocher return make_pnode_dirty(c, node_num, lnum, offs); 1043ff94bc40SHeiko Schocher case UBIFS_LPT_LTAB: 1044ff94bc40SHeiko Schocher return make_ltab_dirty(c, lnum, offs); 1045ff94bc40SHeiko Schocher case UBIFS_LPT_LSAVE: 1046ff94bc40SHeiko Schocher return make_lsave_dirty(c, lnum, offs); 1047ff94bc40SHeiko Schocher } 1048ff94bc40SHeiko Schocher return -EINVAL; 1049ff94bc40SHeiko Schocher } 1050ff94bc40SHeiko Schocher 1051ff94bc40SHeiko Schocher /** 1052ff94bc40SHeiko Schocher * get_lpt_node_len - return the length of a node based on its type. 1053ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 1054ff94bc40SHeiko Schocher * @node_type: LPT node type 1055ff94bc40SHeiko Schocher */ 1056ff94bc40SHeiko Schocher static int get_lpt_node_len(const struct ubifs_info *c, int node_type) 1057ff94bc40SHeiko Schocher { 1058ff94bc40SHeiko Schocher switch (node_type) { 1059ff94bc40SHeiko Schocher case UBIFS_LPT_NNODE: 1060ff94bc40SHeiko Schocher return c->nnode_sz; 1061ff94bc40SHeiko Schocher case UBIFS_LPT_PNODE: 1062ff94bc40SHeiko Schocher return c->pnode_sz; 1063ff94bc40SHeiko Schocher case UBIFS_LPT_LTAB: 1064ff94bc40SHeiko Schocher return c->ltab_sz; 1065ff94bc40SHeiko Schocher case UBIFS_LPT_LSAVE: 1066ff94bc40SHeiko Schocher return c->lsave_sz; 1067ff94bc40SHeiko Schocher } 1068ff94bc40SHeiko Schocher return 0; 1069ff94bc40SHeiko Schocher } 1070ff94bc40SHeiko Schocher 1071ff94bc40SHeiko Schocher /** 1072ff94bc40SHeiko Schocher * get_pad_len - return the length of padding in a buffer. 1073ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 1074ff94bc40SHeiko Schocher * @buf: buffer 1075ff94bc40SHeiko Schocher * @len: length of buffer 1076ff94bc40SHeiko Schocher */ 1077ff94bc40SHeiko Schocher static int get_pad_len(const struct ubifs_info *c, uint8_t *buf, int len) 1078ff94bc40SHeiko Schocher { 1079ff94bc40SHeiko Schocher int offs, pad_len; 1080ff94bc40SHeiko Schocher 1081ff94bc40SHeiko Schocher if (c->min_io_size == 1) 1082ff94bc40SHeiko Schocher return 0; 1083ff94bc40SHeiko Schocher offs = c->leb_size - len; 1084ff94bc40SHeiko Schocher pad_len = ALIGN(offs, c->min_io_size) - offs; 1085ff94bc40SHeiko Schocher return pad_len; 1086ff94bc40SHeiko Schocher } 1087ff94bc40SHeiko Schocher 1088ff94bc40SHeiko Schocher /** 1089ff94bc40SHeiko Schocher * get_lpt_node_type - return type (and node number) of a node in a buffer. 1090ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 1091ff94bc40SHeiko Schocher * @buf: buffer 1092ff94bc40SHeiko Schocher * @node_num: node number is returned here 1093ff94bc40SHeiko Schocher */ 1094ff94bc40SHeiko Schocher static int get_lpt_node_type(const struct ubifs_info *c, uint8_t *buf, 1095ff94bc40SHeiko Schocher int *node_num) 1096ff94bc40SHeiko Schocher { 1097ff94bc40SHeiko Schocher uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES; 1098ff94bc40SHeiko Schocher int pos = 0, node_type; 1099ff94bc40SHeiko Schocher 1100ff94bc40SHeiko Schocher node_type = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_TYPE_BITS); 1101ff94bc40SHeiko Schocher *node_num = ubifs_unpack_bits(&addr, &pos, c->pcnt_bits); 1102ff94bc40SHeiko Schocher return node_type; 1103ff94bc40SHeiko Schocher } 1104ff94bc40SHeiko Schocher 1105ff94bc40SHeiko Schocher /** 1106ff94bc40SHeiko Schocher * is_a_node - determine if a buffer contains a node. 1107ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 1108ff94bc40SHeiko Schocher * @buf: buffer 1109ff94bc40SHeiko Schocher * @len: length of buffer 1110ff94bc40SHeiko Schocher * 1111ff94bc40SHeiko Schocher * This function returns %1 if the buffer contains a node or %0 if it does not. 1112ff94bc40SHeiko Schocher */ 1113ff94bc40SHeiko Schocher static int is_a_node(const struct ubifs_info *c, uint8_t *buf, int len) 1114ff94bc40SHeiko Schocher { 1115ff94bc40SHeiko Schocher uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES; 1116ff94bc40SHeiko Schocher int pos = 0, node_type, node_len; 1117ff94bc40SHeiko Schocher uint16_t crc, calc_crc; 1118ff94bc40SHeiko Schocher 1119ff94bc40SHeiko Schocher if (len < UBIFS_LPT_CRC_BYTES + (UBIFS_LPT_TYPE_BITS + 7) / 8) 1120ff94bc40SHeiko Schocher return 0; 1121ff94bc40SHeiko Schocher node_type = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_TYPE_BITS); 1122ff94bc40SHeiko Schocher if (node_type == UBIFS_LPT_NOT_A_NODE) 1123ff94bc40SHeiko Schocher return 0; 1124ff94bc40SHeiko Schocher node_len = get_lpt_node_len(c, node_type); 1125ff94bc40SHeiko Schocher if (!node_len || node_len > len) 1126ff94bc40SHeiko Schocher return 0; 1127ff94bc40SHeiko Schocher pos = 0; 1128ff94bc40SHeiko Schocher addr = buf; 1129ff94bc40SHeiko Schocher crc = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_CRC_BITS); 1130ff94bc40SHeiko Schocher calc_crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES, 1131ff94bc40SHeiko Schocher node_len - UBIFS_LPT_CRC_BYTES); 1132ff94bc40SHeiko Schocher if (crc != calc_crc) 1133ff94bc40SHeiko Schocher return 0; 1134ff94bc40SHeiko Schocher return 1; 1135ff94bc40SHeiko Schocher } 1136ff94bc40SHeiko Schocher 1137ff94bc40SHeiko Schocher /** 1138ff94bc40SHeiko Schocher * lpt_gc_lnum - garbage collect a LPT LEB. 1139ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 1140ff94bc40SHeiko Schocher * @lnum: LEB number to garbage collect 1141ff94bc40SHeiko Schocher * 1142ff94bc40SHeiko Schocher * LPT garbage collection is used only for the "big" LPT model 1143ff94bc40SHeiko Schocher * (c->big_lpt == 1). Garbage collection simply involves marking all the nodes 1144ff94bc40SHeiko Schocher * in the LEB being garbage-collected as dirty. The dirty nodes are written 1145ff94bc40SHeiko Schocher * next commit, after which the LEB is free to be reused. 1146ff94bc40SHeiko Schocher * 1147ff94bc40SHeiko Schocher * This function returns %0 on success and a negative error code on failure. 1148ff94bc40SHeiko Schocher */ 1149ff94bc40SHeiko Schocher static int lpt_gc_lnum(struct ubifs_info *c, int lnum) 1150ff94bc40SHeiko Schocher { 1151ff94bc40SHeiko Schocher int err, len = c->leb_size, node_type, node_num, node_len, offs; 1152ff94bc40SHeiko Schocher void *buf = c->lpt_buf; 1153ff94bc40SHeiko Schocher 1154ff94bc40SHeiko Schocher dbg_lp("LEB %d", lnum); 1155ff94bc40SHeiko Schocher 1156ff94bc40SHeiko Schocher err = ubifs_leb_read(c, lnum, buf, 0, c->leb_size, 1); 1157ff94bc40SHeiko Schocher if (err) 1158ff94bc40SHeiko Schocher return err; 1159ff94bc40SHeiko Schocher 1160ff94bc40SHeiko Schocher while (1) { 1161ff94bc40SHeiko Schocher if (!is_a_node(c, buf, len)) { 1162ff94bc40SHeiko Schocher int pad_len; 1163ff94bc40SHeiko Schocher 1164ff94bc40SHeiko Schocher pad_len = get_pad_len(c, buf, len); 1165ff94bc40SHeiko Schocher if (pad_len) { 1166ff94bc40SHeiko Schocher buf += pad_len; 1167ff94bc40SHeiko Schocher len -= pad_len; 1168ff94bc40SHeiko Schocher continue; 1169ff94bc40SHeiko Schocher } 1170ff94bc40SHeiko Schocher return 0; 1171ff94bc40SHeiko Schocher } 1172ff94bc40SHeiko Schocher node_type = get_lpt_node_type(c, buf, &node_num); 1173ff94bc40SHeiko Schocher node_len = get_lpt_node_len(c, node_type); 1174ff94bc40SHeiko Schocher offs = c->leb_size - len; 1175ff94bc40SHeiko Schocher ubifs_assert(node_len != 0); 1176ff94bc40SHeiko Schocher mutex_lock(&c->lp_mutex); 1177ff94bc40SHeiko Schocher err = make_node_dirty(c, node_type, node_num, lnum, offs); 1178ff94bc40SHeiko Schocher mutex_unlock(&c->lp_mutex); 1179ff94bc40SHeiko Schocher if (err) 1180ff94bc40SHeiko Schocher return err; 1181ff94bc40SHeiko Schocher buf += node_len; 1182ff94bc40SHeiko Schocher len -= node_len; 1183ff94bc40SHeiko Schocher } 1184ff94bc40SHeiko Schocher return 0; 1185ff94bc40SHeiko Schocher } 1186ff94bc40SHeiko Schocher 1187ff94bc40SHeiko Schocher /** 1188ff94bc40SHeiko Schocher * lpt_gc - LPT garbage collection. 1189ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 1190ff94bc40SHeiko Schocher * 1191ff94bc40SHeiko Schocher * Select a LPT LEB for LPT garbage collection and call 'lpt_gc_lnum()'. 1192ff94bc40SHeiko Schocher * Returns %0 on success and a negative error code on failure. 1193ff94bc40SHeiko Schocher */ 1194ff94bc40SHeiko Schocher static int lpt_gc(struct ubifs_info *c) 1195ff94bc40SHeiko Schocher { 1196ff94bc40SHeiko Schocher int i, lnum = -1, dirty = 0; 1197ff94bc40SHeiko Schocher 1198ff94bc40SHeiko Schocher mutex_lock(&c->lp_mutex); 1199ff94bc40SHeiko Schocher for (i = 0; i < c->lpt_lebs; i++) { 1200ff94bc40SHeiko Schocher ubifs_assert(!c->ltab[i].tgc); 1201ff94bc40SHeiko Schocher if (i + c->lpt_first == c->nhead_lnum || 1202ff94bc40SHeiko Schocher c->ltab[i].free + c->ltab[i].dirty == c->leb_size) 1203ff94bc40SHeiko Schocher continue; 1204ff94bc40SHeiko Schocher if (c->ltab[i].dirty > dirty) { 1205ff94bc40SHeiko Schocher dirty = c->ltab[i].dirty; 1206ff94bc40SHeiko Schocher lnum = i + c->lpt_first; 1207ff94bc40SHeiko Schocher } 1208ff94bc40SHeiko Schocher } 1209ff94bc40SHeiko Schocher mutex_unlock(&c->lp_mutex); 1210ff94bc40SHeiko Schocher if (lnum == -1) 1211ff94bc40SHeiko Schocher return -ENOSPC; 1212ff94bc40SHeiko Schocher return lpt_gc_lnum(c, lnum); 1213ff94bc40SHeiko Schocher } 1214ff94bc40SHeiko Schocher 1215ff94bc40SHeiko Schocher /** 1216ff94bc40SHeiko Schocher * ubifs_lpt_start_commit - UBIFS commit starts. 1217ff94bc40SHeiko Schocher * @c: the UBIFS file-system description object 1218ff94bc40SHeiko Schocher * 1219ff94bc40SHeiko Schocher * This function has to be called when UBIFS starts the commit operation. 1220ff94bc40SHeiko Schocher * This function "freezes" all currently dirty LEB properties and does not 1221ff94bc40SHeiko Schocher * change them anymore. Further changes are saved and tracked separately 1222ff94bc40SHeiko Schocher * because they are not part of this commit. This function returns zero in case 1223ff94bc40SHeiko Schocher * of success and a negative error code in case of failure. 1224ff94bc40SHeiko Schocher */ 1225ff94bc40SHeiko Schocher int ubifs_lpt_start_commit(struct ubifs_info *c) 1226ff94bc40SHeiko Schocher { 1227ff94bc40SHeiko Schocher int err, cnt; 1228ff94bc40SHeiko Schocher 1229ff94bc40SHeiko Schocher dbg_lp(""); 1230ff94bc40SHeiko Schocher 1231ff94bc40SHeiko Schocher mutex_lock(&c->lp_mutex); 1232ff94bc40SHeiko Schocher err = dbg_chk_lpt_free_spc(c); 1233ff94bc40SHeiko Schocher if (err) 1234ff94bc40SHeiko Schocher goto out; 1235ff94bc40SHeiko Schocher err = dbg_check_ltab(c); 1236ff94bc40SHeiko Schocher if (err) 1237ff94bc40SHeiko Schocher goto out; 1238ff94bc40SHeiko Schocher 1239ff94bc40SHeiko Schocher if (c->check_lpt_free) { 1240ff94bc40SHeiko Schocher /* 1241ff94bc40SHeiko Schocher * We ensure there is enough free space in 1242ff94bc40SHeiko Schocher * ubifs_lpt_post_commit() by marking nodes dirty. That 1243ff94bc40SHeiko Schocher * information is lost when we unmount, so we also need 1244ff94bc40SHeiko Schocher * to check free space once after mounting also. 1245ff94bc40SHeiko Schocher */ 1246ff94bc40SHeiko Schocher c->check_lpt_free = 0; 1247ff94bc40SHeiko Schocher while (need_write_all(c)) { 1248ff94bc40SHeiko Schocher mutex_unlock(&c->lp_mutex); 1249ff94bc40SHeiko Schocher err = lpt_gc(c); 1250ff94bc40SHeiko Schocher if (err) 1251ff94bc40SHeiko Schocher return err; 1252ff94bc40SHeiko Schocher mutex_lock(&c->lp_mutex); 1253ff94bc40SHeiko Schocher } 1254ff94bc40SHeiko Schocher } 1255ff94bc40SHeiko Schocher 1256ff94bc40SHeiko Schocher lpt_tgc_start(c); 1257ff94bc40SHeiko Schocher 1258ff94bc40SHeiko Schocher if (!c->dirty_pn_cnt) { 1259ff94bc40SHeiko Schocher dbg_cmt("no cnodes to commit"); 1260ff94bc40SHeiko Schocher err = 0; 1261ff94bc40SHeiko Schocher goto out; 1262ff94bc40SHeiko Schocher } 1263ff94bc40SHeiko Schocher 1264ff94bc40SHeiko Schocher if (!c->big_lpt && need_write_all(c)) { 1265ff94bc40SHeiko Schocher /* If needed, write everything */ 1266ff94bc40SHeiko Schocher err = make_tree_dirty(c); 1267ff94bc40SHeiko Schocher if (err) 1268ff94bc40SHeiko Schocher goto out; 1269ff94bc40SHeiko Schocher lpt_tgc_start(c); 1270ff94bc40SHeiko Schocher } 1271ff94bc40SHeiko Schocher 1272ff94bc40SHeiko Schocher if (c->big_lpt) 1273ff94bc40SHeiko Schocher populate_lsave(c); 1274ff94bc40SHeiko Schocher 1275ff94bc40SHeiko Schocher cnt = get_cnodes_to_commit(c); 1276ff94bc40SHeiko Schocher ubifs_assert(cnt != 0); 1277ff94bc40SHeiko Schocher 1278ff94bc40SHeiko Schocher err = layout_cnodes(c); 1279ff94bc40SHeiko Schocher if (err) 1280ff94bc40SHeiko Schocher goto out; 1281ff94bc40SHeiko Schocher 1282ff94bc40SHeiko Schocher /* Copy the LPT's own lprops for end commit to write */ 1283ff94bc40SHeiko Schocher memcpy(c->ltab_cmt, c->ltab, 1284ff94bc40SHeiko Schocher sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs); 1285ff94bc40SHeiko Schocher c->lpt_drty_flgs &= ~(LTAB_DIRTY | LSAVE_DIRTY); 1286ff94bc40SHeiko Schocher 1287ff94bc40SHeiko Schocher out: 1288ff94bc40SHeiko Schocher mutex_unlock(&c->lp_mutex); 1289ff94bc40SHeiko Schocher return err; 1290ff94bc40SHeiko Schocher } 1291ff94bc40SHeiko Schocher 12929eefe2a2SStefan Roese /** 12939eefe2a2SStefan Roese * free_obsolete_cnodes - free obsolete cnodes for commit end. 12949eefe2a2SStefan Roese * @c: UBIFS file-system description object 12959eefe2a2SStefan Roese */ 12969eefe2a2SStefan Roese static void free_obsolete_cnodes(struct ubifs_info *c) 12979eefe2a2SStefan Roese { 12989eefe2a2SStefan Roese struct ubifs_cnode *cnode, *cnext; 12999eefe2a2SStefan Roese 13009eefe2a2SStefan Roese cnext = c->lpt_cnext; 13019eefe2a2SStefan Roese if (!cnext) 13029eefe2a2SStefan Roese return; 13039eefe2a2SStefan Roese do { 13049eefe2a2SStefan Roese cnode = cnext; 13059eefe2a2SStefan Roese cnext = cnode->cnext; 13069eefe2a2SStefan Roese if (test_bit(OBSOLETE_CNODE, &cnode->flags)) 13079eefe2a2SStefan Roese kfree(cnode); 13089eefe2a2SStefan Roese else 13099eefe2a2SStefan Roese cnode->cnext = NULL; 13109eefe2a2SStefan Roese } while (cnext != c->lpt_cnext); 13119eefe2a2SStefan Roese c->lpt_cnext = NULL; 13129eefe2a2SStefan Roese } 13139eefe2a2SStefan Roese 1314ff94bc40SHeiko Schocher #ifndef __UBOOT__ 1315ff94bc40SHeiko Schocher /** 1316ff94bc40SHeiko Schocher * ubifs_lpt_end_commit - finish the commit operation. 1317ff94bc40SHeiko Schocher * @c: the UBIFS file-system description object 1318ff94bc40SHeiko Schocher * 1319ff94bc40SHeiko Schocher * This function has to be called when the commit operation finishes. It 1320ff94bc40SHeiko Schocher * flushes the changes which were "frozen" by 'ubifs_lprops_start_commit()' to 1321ff94bc40SHeiko Schocher * the media. Returns zero in case of success and a negative error code in case 1322ff94bc40SHeiko Schocher * of failure. 1323ff94bc40SHeiko Schocher */ 1324ff94bc40SHeiko Schocher int ubifs_lpt_end_commit(struct ubifs_info *c) 1325ff94bc40SHeiko Schocher { 1326ff94bc40SHeiko Schocher int err; 1327ff94bc40SHeiko Schocher 1328ff94bc40SHeiko Schocher dbg_lp(""); 1329ff94bc40SHeiko Schocher 1330ff94bc40SHeiko Schocher if (!c->lpt_cnext) 1331ff94bc40SHeiko Schocher return 0; 1332ff94bc40SHeiko Schocher 1333ff94bc40SHeiko Schocher err = write_cnodes(c); 1334ff94bc40SHeiko Schocher if (err) 1335ff94bc40SHeiko Schocher return err; 1336ff94bc40SHeiko Schocher 1337ff94bc40SHeiko Schocher mutex_lock(&c->lp_mutex); 1338ff94bc40SHeiko Schocher free_obsolete_cnodes(c); 1339ff94bc40SHeiko Schocher mutex_unlock(&c->lp_mutex); 1340ff94bc40SHeiko Schocher 1341ff94bc40SHeiko Schocher return 0; 1342ff94bc40SHeiko Schocher } 1343ff94bc40SHeiko Schocher #endif 1344ff94bc40SHeiko Schocher 1345ff94bc40SHeiko Schocher /** 1346ff94bc40SHeiko Schocher * ubifs_lpt_post_commit - post commit LPT trivial GC and LPT GC. 1347ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 1348ff94bc40SHeiko Schocher * 1349ff94bc40SHeiko Schocher * LPT trivial GC is completed after a commit. Also LPT GC is done after a 1350ff94bc40SHeiko Schocher * commit for the "big" LPT model. 1351ff94bc40SHeiko Schocher */ 1352ff94bc40SHeiko Schocher int ubifs_lpt_post_commit(struct ubifs_info *c) 1353ff94bc40SHeiko Schocher { 1354ff94bc40SHeiko Schocher int err; 1355ff94bc40SHeiko Schocher 1356ff94bc40SHeiko Schocher mutex_lock(&c->lp_mutex); 1357ff94bc40SHeiko Schocher err = lpt_tgc_end(c); 1358ff94bc40SHeiko Schocher if (err) 1359ff94bc40SHeiko Schocher goto out; 1360ff94bc40SHeiko Schocher if (c->big_lpt) 1361ff94bc40SHeiko Schocher while (need_write_all(c)) { 1362ff94bc40SHeiko Schocher mutex_unlock(&c->lp_mutex); 1363ff94bc40SHeiko Schocher err = lpt_gc(c); 1364ff94bc40SHeiko Schocher if (err) 1365ff94bc40SHeiko Schocher return err; 1366ff94bc40SHeiko Schocher mutex_lock(&c->lp_mutex); 1367ff94bc40SHeiko Schocher } 1368ff94bc40SHeiko Schocher out: 1369ff94bc40SHeiko Schocher mutex_unlock(&c->lp_mutex); 1370ff94bc40SHeiko Schocher return err; 1371ff94bc40SHeiko Schocher } 1372ff94bc40SHeiko Schocher 13739eefe2a2SStefan Roese /** 13749eefe2a2SStefan Roese * first_nnode - find the first nnode in memory. 13759eefe2a2SStefan Roese * @c: UBIFS file-system description object 13769eefe2a2SStefan Roese * @hght: height of tree where nnode found is returned here 13779eefe2a2SStefan Roese * 13789eefe2a2SStefan Roese * This function returns a pointer to the nnode found or %NULL if no nnode is 13799eefe2a2SStefan Roese * found. This function is a helper to 'ubifs_lpt_free()'. 13809eefe2a2SStefan Roese */ 13819eefe2a2SStefan Roese static struct ubifs_nnode *first_nnode(struct ubifs_info *c, int *hght) 13829eefe2a2SStefan Roese { 13839eefe2a2SStefan Roese struct ubifs_nnode *nnode; 13849eefe2a2SStefan Roese int h, i, found; 13859eefe2a2SStefan Roese 13869eefe2a2SStefan Roese nnode = c->nroot; 13879eefe2a2SStefan Roese *hght = 0; 13889eefe2a2SStefan Roese if (!nnode) 13899eefe2a2SStefan Roese return NULL; 13909eefe2a2SStefan Roese for (h = 1; h < c->lpt_hght; h++) { 13919eefe2a2SStefan Roese found = 0; 13929eefe2a2SStefan Roese for (i = 0; i < UBIFS_LPT_FANOUT; i++) { 13939eefe2a2SStefan Roese if (nnode->nbranch[i].nnode) { 13949eefe2a2SStefan Roese found = 1; 13959eefe2a2SStefan Roese nnode = nnode->nbranch[i].nnode; 13969eefe2a2SStefan Roese *hght = h; 13979eefe2a2SStefan Roese break; 13989eefe2a2SStefan Roese } 13999eefe2a2SStefan Roese } 14009eefe2a2SStefan Roese if (!found) 14019eefe2a2SStefan Roese break; 14029eefe2a2SStefan Roese } 14039eefe2a2SStefan Roese return nnode; 14049eefe2a2SStefan Roese } 14059eefe2a2SStefan Roese 14069eefe2a2SStefan Roese /** 14079eefe2a2SStefan Roese * next_nnode - find the next nnode in memory. 14089eefe2a2SStefan Roese * @c: UBIFS file-system description object 14099eefe2a2SStefan Roese * @nnode: nnode from which to start. 14109eefe2a2SStefan Roese * @hght: height of tree where nnode is, is passed and returned here 14119eefe2a2SStefan Roese * 14129eefe2a2SStefan Roese * This function returns a pointer to the nnode found or %NULL if no nnode is 14139eefe2a2SStefan Roese * found. This function is a helper to 'ubifs_lpt_free()'. 14149eefe2a2SStefan Roese */ 14159eefe2a2SStefan Roese static struct ubifs_nnode *next_nnode(struct ubifs_info *c, 14169eefe2a2SStefan Roese struct ubifs_nnode *nnode, int *hght) 14179eefe2a2SStefan Roese { 14189eefe2a2SStefan Roese struct ubifs_nnode *parent; 14199eefe2a2SStefan Roese int iip, h, i, found; 14209eefe2a2SStefan Roese 14219eefe2a2SStefan Roese parent = nnode->parent; 14229eefe2a2SStefan Roese if (!parent) 14239eefe2a2SStefan Roese return NULL; 14249eefe2a2SStefan Roese if (nnode->iip == UBIFS_LPT_FANOUT - 1) { 14259eefe2a2SStefan Roese *hght -= 1; 14269eefe2a2SStefan Roese return parent; 14279eefe2a2SStefan Roese } 14289eefe2a2SStefan Roese for (iip = nnode->iip + 1; iip < UBIFS_LPT_FANOUT; iip++) { 14299eefe2a2SStefan Roese nnode = parent->nbranch[iip].nnode; 14309eefe2a2SStefan Roese if (nnode) 14319eefe2a2SStefan Roese break; 14329eefe2a2SStefan Roese } 14339eefe2a2SStefan Roese if (!nnode) { 14349eefe2a2SStefan Roese *hght -= 1; 14359eefe2a2SStefan Roese return parent; 14369eefe2a2SStefan Roese } 14379eefe2a2SStefan Roese for (h = *hght + 1; h < c->lpt_hght; h++) { 14389eefe2a2SStefan Roese found = 0; 14399eefe2a2SStefan Roese for (i = 0; i < UBIFS_LPT_FANOUT; i++) { 14409eefe2a2SStefan Roese if (nnode->nbranch[i].nnode) { 14419eefe2a2SStefan Roese found = 1; 14429eefe2a2SStefan Roese nnode = nnode->nbranch[i].nnode; 14439eefe2a2SStefan Roese *hght = h; 14449eefe2a2SStefan Roese break; 14459eefe2a2SStefan Roese } 14469eefe2a2SStefan Roese } 14479eefe2a2SStefan Roese if (!found) 14489eefe2a2SStefan Roese break; 14499eefe2a2SStefan Roese } 14509eefe2a2SStefan Roese return nnode; 14519eefe2a2SStefan Roese } 14529eefe2a2SStefan Roese 14539eefe2a2SStefan Roese /** 14549eefe2a2SStefan Roese * ubifs_lpt_free - free resources owned by the LPT. 14559eefe2a2SStefan Roese * @c: UBIFS file-system description object 14569eefe2a2SStefan Roese * @wr_only: free only resources used for writing 14579eefe2a2SStefan Roese */ 14589eefe2a2SStefan Roese void ubifs_lpt_free(struct ubifs_info *c, int wr_only) 14599eefe2a2SStefan Roese { 14609eefe2a2SStefan Roese struct ubifs_nnode *nnode; 14619eefe2a2SStefan Roese int i, hght; 14629eefe2a2SStefan Roese 14639eefe2a2SStefan Roese /* Free write-only things first */ 14649eefe2a2SStefan Roese 14659eefe2a2SStefan Roese free_obsolete_cnodes(c); /* Leftover from a failed commit */ 14669eefe2a2SStefan Roese 14679eefe2a2SStefan Roese vfree(c->ltab_cmt); 14689eefe2a2SStefan Roese c->ltab_cmt = NULL; 14699eefe2a2SStefan Roese vfree(c->lpt_buf); 14709eefe2a2SStefan Roese c->lpt_buf = NULL; 14719eefe2a2SStefan Roese kfree(c->lsave); 14729eefe2a2SStefan Roese c->lsave = NULL; 14739eefe2a2SStefan Roese 14749eefe2a2SStefan Roese if (wr_only) 14759eefe2a2SStefan Roese return; 14769eefe2a2SStefan Roese 14779eefe2a2SStefan Roese /* Now free the rest */ 14789eefe2a2SStefan Roese 14799eefe2a2SStefan Roese nnode = first_nnode(c, &hght); 14809eefe2a2SStefan Roese while (nnode) { 14819eefe2a2SStefan Roese for (i = 0; i < UBIFS_LPT_FANOUT; i++) 14829eefe2a2SStefan Roese kfree(nnode->nbranch[i].nnode); 14839eefe2a2SStefan Roese nnode = next_nnode(c, nnode, &hght); 14849eefe2a2SStefan Roese } 14859eefe2a2SStefan Roese for (i = 0; i < LPROPS_HEAP_CNT; i++) 14869eefe2a2SStefan Roese kfree(c->lpt_heap[i].arr); 14879eefe2a2SStefan Roese kfree(c->dirty_idx.arr); 14889eefe2a2SStefan Roese kfree(c->nroot); 14899eefe2a2SStefan Roese vfree(c->ltab); 14909eefe2a2SStefan Roese kfree(c->lpt_nod_buf); 14919eefe2a2SStefan Roese } 1492ff94bc40SHeiko Schocher 1493ff94bc40SHeiko Schocher #ifndef __UBOOT__ 1494ff94bc40SHeiko Schocher /* 1495ff94bc40SHeiko Schocher * Everything below is related to debugging. 1496ff94bc40SHeiko Schocher */ 1497ff94bc40SHeiko Schocher 1498ff94bc40SHeiko Schocher /** 1499ff94bc40SHeiko Schocher * dbg_is_all_ff - determine if a buffer contains only 0xFF bytes. 1500ff94bc40SHeiko Schocher * @buf: buffer 1501ff94bc40SHeiko Schocher * @len: buffer length 1502ff94bc40SHeiko Schocher */ 1503ff94bc40SHeiko Schocher static int dbg_is_all_ff(uint8_t *buf, int len) 1504ff94bc40SHeiko Schocher { 1505ff94bc40SHeiko Schocher int i; 1506ff94bc40SHeiko Schocher 1507ff94bc40SHeiko Schocher for (i = 0; i < len; i++) 1508ff94bc40SHeiko Schocher if (buf[i] != 0xff) 1509ff94bc40SHeiko Schocher return 0; 1510ff94bc40SHeiko Schocher return 1; 1511ff94bc40SHeiko Schocher } 1512ff94bc40SHeiko Schocher 1513ff94bc40SHeiko Schocher /** 1514ff94bc40SHeiko Schocher * dbg_is_nnode_dirty - determine if a nnode is dirty. 1515ff94bc40SHeiko Schocher * @c: the UBIFS file-system description object 1516ff94bc40SHeiko Schocher * @lnum: LEB number where nnode was written 1517ff94bc40SHeiko Schocher * @offs: offset where nnode was written 1518ff94bc40SHeiko Schocher */ 1519ff94bc40SHeiko Schocher static int dbg_is_nnode_dirty(struct ubifs_info *c, int lnum, int offs) 1520ff94bc40SHeiko Schocher { 1521ff94bc40SHeiko Schocher struct ubifs_nnode *nnode; 1522ff94bc40SHeiko Schocher int hght; 1523ff94bc40SHeiko Schocher 1524ff94bc40SHeiko Schocher /* Entire tree is in memory so first_nnode / next_nnode are OK */ 1525ff94bc40SHeiko Schocher nnode = first_nnode(c, &hght); 1526ff94bc40SHeiko Schocher for (; nnode; nnode = next_nnode(c, nnode, &hght)) { 1527ff94bc40SHeiko Schocher struct ubifs_nbranch *branch; 1528ff94bc40SHeiko Schocher 1529ff94bc40SHeiko Schocher cond_resched(); 1530ff94bc40SHeiko Schocher if (nnode->parent) { 1531ff94bc40SHeiko Schocher branch = &nnode->parent->nbranch[nnode->iip]; 1532ff94bc40SHeiko Schocher if (branch->lnum != lnum || branch->offs != offs) 1533ff94bc40SHeiko Schocher continue; 1534ff94bc40SHeiko Schocher if (test_bit(DIRTY_CNODE, &nnode->flags)) 1535ff94bc40SHeiko Schocher return 1; 1536ff94bc40SHeiko Schocher return 0; 1537ff94bc40SHeiko Schocher } else { 1538ff94bc40SHeiko Schocher if (c->lpt_lnum != lnum || c->lpt_offs != offs) 1539ff94bc40SHeiko Schocher continue; 1540ff94bc40SHeiko Schocher if (test_bit(DIRTY_CNODE, &nnode->flags)) 1541ff94bc40SHeiko Schocher return 1; 1542ff94bc40SHeiko Schocher return 0; 1543ff94bc40SHeiko Schocher } 1544ff94bc40SHeiko Schocher } 1545ff94bc40SHeiko Schocher return 1; 1546ff94bc40SHeiko Schocher } 1547ff94bc40SHeiko Schocher 1548ff94bc40SHeiko Schocher /** 1549ff94bc40SHeiko Schocher * dbg_is_pnode_dirty - determine if a pnode is dirty. 1550ff94bc40SHeiko Schocher * @c: the UBIFS file-system description object 1551ff94bc40SHeiko Schocher * @lnum: LEB number where pnode was written 1552ff94bc40SHeiko Schocher * @offs: offset where pnode was written 1553ff94bc40SHeiko Schocher */ 1554ff94bc40SHeiko Schocher static int dbg_is_pnode_dirty(struct ubifs_info *c, int lnum, int offs) 1555ff94bc40SHeiko Schocher { 1556ff94bc40SHeiko Schocher int i, cnt; 1557ff94bc40SHeiko Schocher 1558ff94bc40SHeiko Schocher cnt = DIV_ROUND_UP(c->main_lebs, UBIFS_LPT_FANOUT); 1559ff94bc40SHeiko Schocher for (i = 0; i < cnt; i++) { 1560ff94bc40SHeiko Schocher struct ubifs_pnode *pnode; 1561ff94bc40SHeiko Schocher struct ubifs_nbranch *branch; 1562ff94bc40SHeiko Schocher 1563ff94bc40SHeiko Schocher cond_resched(); 1564ff94bc40SHeiko Schocher pnode = pnode_lookup(c, i); 1565ff94bc40SHeiko Schocher if (IS_ERR(pnode)) 1566ff94bc40SHeiko Schocher return PTR_ERR(pnode); 1567ff94bc40SHeiko Schocher branch = &pnode->parent->nbranch[pnode->iip]; 1568ff94bc40SHeiko Schocher if (branch->lnum != lnum || branch->offs != offs) 1569ff94bc40SHeiko Schocher continue; 1570ff94bc40SHeiko Schocher if (test_bit(DIRTY_CNODE, &pnode->flags)) 1571ff94bc40SHeiko Schocher return 1; 1572ff94bc40SHeiko Schocher return 0; 1573ff94bc40SHeiko Schocher } 1574ff94bc40SHeiko Schocher return 1; 1575ff94bc40SHeiko Schocher } 1576ff94bc40SHeiko Schocher 1577ff94bc40SHeiko Schocher /** 1578ff94bc40SHeiko Schocher * dbg_is_ltab_dirty - determine if a ltab node is dirty. 1579ff94bc40SHeiko Schocher * @c: the UBIFS file-system description object 1580ff94bc40SHeiko Schocher * @lnum: LEB number where ltab node was written 1581ff94bc40SHeiko Schocher * @offs: offset where ltab node was written 1582ff94bc40SHeiko Schocher */ 1583ff94bc40SHeiko Schocher static int dbg_is_ltab_dirty(struct ubifs_info *c, int lnum, int offs) 1584ff94bc40SHeiko Schocher { 1585ff94bc40SHeiko Schocher if (lnum != c->ltab_lnum || offs != c->ltab_offs) 1586ff94bc40SHeiko Schocher return 1; 1587ff94bc40SHeiko Schocher return (c->lpt_drty_flgs & LTAB_DIRTY) != 0; 1588ff94bc40SHeiko Schocher } 1589ff94bc40SHeiko Schocher 1590ff94bc40SHeiko Schocher /** 1591ff94bc40SHeiko Schocher * dbg_is_lsave_dirty - determine if a lsave node is dirty. 1592ff94bc40SHeiko Schocher * @c: the UBIFS file-system description object 1593ff94bc40SHeiko Schocher * @lnum: LEB number where lsave node was written 1594ff94bc40SHeiko Schocher * @offs: offset where lsave node was written 1595ff94bc40SHeiko Schocher */ 1596ff94bc40SHeiko Schocher static int dbg_is_lsave_dirty(struct ubifs_info *c, int lnum, int offs) 1597ff94bc40SHeiko Schocher { 1598ff94bc40SHeiko Schocher if (lnum != c->lsave_lnum || offs != c->lsave_offs) 1599ff94bc40SHeiko Schocher return 1; 1600ff94bc40SHeiko Schocher return (c->lpt_drty_flgs & LSAVE_DIRTY) != 0; 1601ff94bc40SHeiko Schocher } 1602ff94bc40SHeiko Schocher 1603ff94bc40SHeiko Schocher /** 1604ff94bc40SHeiko Schocher * dbg_is_node_dirty - determine if a node is dirty. 1605ff94bc40SHeiko Schocher * @c: the UBIFS file-system description object 1606ff94bc40SHeiko Schocher * @node_type: node type 1607ff94bc40SHeiko Schocher * @lnum: LEB number where node was written 1608ff94bc40SHeiko Schocher * @offs: offset where node was written 1609ff94bc40SHeiko Schocher */ 1610ff94bc40SHeiko Schocher static int dbg_is_node_dirty(struct ubifs_info *c, int node_type, int lnum, 1611ff94bc40SHeiko Schocher int offs) 1612ff94bc40SHeiko Schocher { 1613ff94bc40SHeiko Schocher switch (node_type) { 1614ff94bc40SHeiko Schocher case UBIFS_LPT_NNODE: 1615ff94bc40SHeiko Schocher return dbg_is_nnode_dirty(c, lnum, offs); 1616ff94bc40SHeiko Schocher case UBIFS_LPT_PNODE: 1617ff94bc40SHeiko Schocher return dbg_is_pnode_dirty(c, lnum, offs); 1618ff94bc40SHeiko Schocher case UBIFS_LPT_LTAB: 1619ff94bc40SHeiko Schocher return dbg_is_ltab_dirty(c, lnum, offs); 1620ff94bc40SHeiko Schocher case UBIFS_LPT_LSAVE: 1621ff94bc40SHeiko Schocher return dbg_is_lsave_dirty(c, lnum, offs); 1622ff94bc40SHeiko Schocher } 1623ff94bc40SHeiko Schocher return 1; 1624ff94bc40SHeiko Schocher } 1625ff94bc40SHeiko Schocher 1626ff94bc40SHeiko Schocher /** 1627ff94bc40SHeiko Schocher * dbg_check_ltab_lnum - check the ltab for a LPT LEB number. 1628ff94bc40SHeiko Schocher * @c: the UBIFS file-system description object 1629ff94bc40SHeiko Schocher * @lnum: LEB number where node was written 1630ff94bc40SHeiko Schocher * @offs: offset where node was written 1631ff94bc40SHeiko Schocher * 1632ff94bc40SHeiko Schocher * This function returns %0 on success and a negative error code on failure. 1633ff94bc40SHeiko Schocher */ 1634ff94bc40SHeiko Schocher static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum) 1635ff94bc40SHeiko Schocher { 1636ff94bc40SHeiko Schocher int err, len = c->leb_size, dirty = 0, node_type, node_num, node_len; 1637ff94bc40SHeiko Schocher int ret; 1638ff94bc40SHeiko Schocher void *buf, *p; 1639ff94bc40SHeiko Schocher 1640ff94bc40SHeiko Schocher if (!dbg_is_chk_lprops(c)) 1641ff94bc40SHeiko Schocher return 0; 1642ff94bc40SHeiko Schocher 1643ff94bc40SHeiko Schocher buf = p = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL); 1644ff94bc40SHeiko Schocher if (!buf) { 1645*0195a7bbSHeiko Schocher ubifs_err(c, "cannot allocate memory for ltab checking"); 1646ff94bc40SHeiko Schocher return 0; 1647ff94bc40SHeiko Schocher } 1648ff94bc40SHeiko Schocher 1649ff94bc40SHeiko Schocher dbg_lp("LEB %d", lnum); 1650ff94bc40SHeiko Schocher 1651ff94bc40SHeiko Schocher err = ubifs_leb_read(c, lnum, buf, 0, c->leb_size, 1); 1652ff94bc40SHeiko Schocher if (err) 1653ff94bc40SHeiko Schocher goto out; 1654ff94bc40SHeiko Schocher 1655ff94bc40SHeiko Schocher while (1) { 1656ff94bc40SHeiko Schocher if (!is_a_node(c, p, len)) { 1657ff94bc40SHeiko Schocher int i, pad_len; 1658ff94bc40SHeiko Schocher 1659ff94bc40SHeiko Schocher pad_len = get_pad_len(c, p, len); 1660ff94bc40SHeiko Schocher if (pad_len) { 1661ff94bc40SHeiko Schocher p += pad_len; 1662ff94bc40SHeiko Schocher len -= pad_len; 1663ff94bc40SHeiko Schocher dirty += pad_len; 1664ff94bc40SHeiko Schocher continue; 1665ff94bc40SHeiko Schocher } 1666ff94bc40SHeiko Schocher if (!dbg_is_all_ff(p, len)) { 1667*0195a7bbSHeiko Schocher ubifs_err(c, "invalid empty space in LEB %d at %d", 1668ff94bc40SHeiko Schocher lnum, c->leb_size - len); 1669ff94bc40SHeiko Schocher err = -EINVAL; 1670ff94bc40SHeiko Schocher } 1671ff94bc40SHeiko Schocher i = lnum - c->lpt_first; 1672ff94bc40SHeiko Schocher if (len != c->ltab[i].free) { 1673*0195a7bbSHeiko Schocher ubifs_err(c, "invalid free space in LEB %d (free %d, expected %d)", 1674ff94bc40SHeiko Schocher lnum, len, c->ltab[i].free); 1675ff94bc40SHeiko Schocher err = -EINVAL; 1676ff94bc40SHeiko Schocher } 1677ff94bc40SHeiko Schocher if (dirty != c->ltab[i].dirty) { 1678*0195a7bbSHeiko Schocher ubifs_err(c, "invalid dirty space in LEB %d (dirty %d, expected %d)", 1679ff94bc40SHeiko Schocher lnum, dirty, c->ltab[i].dirty); 1680ff94bc40SHeiko Schocher err = -EINVAL; 1681ff94bc40SHeiko Schocher } 1682ff94bc40SHeiko Schocher goto out; 1683ff94bc40SHeiko Schocher } 1684ff94bc40SHeiko Schocher node_type = get_lpt_node_type(c, p, &node_num); 1685ff94bc40SHeiko Schocher node_len = get_lpt_node_len(c, node_type); 1686ff94bc40SHeiko Schocher ret = dbg_is_node_dirty(c, node_type, lnum, c->leb_size - len); 1687ff94bc40SHeiko Schocher if (ret == 1) 1688ff94bc40SHeiko Schocher dirty += node_len; 1689ff94bc40SHeiko Schocher p += node_len; 1690ff94bc40SHeiko Schocher len -= node_len; 1691ff94bc40SHeiko Schocher } 1692ff94bc40SHeiko Schocher 1693ff94bc40SHeiko Schocher err = 0; 1694ff94bc40SHeiko Schocher out: 1695ff94bc40SHeiko Schocher vfree(buf); 1696ff94bc40SHeiko Schocher return err; 1697ff94bc40SHeiko Schocher } 1698ff94bc40SHeiko Schocher 1699ff94bc40SHeiko Schocher /** 1700ff94bc40SHeiko Schocher * dbg_check_ltab - check the free and dirty space in the ltab. 1701ff94bc40SHeiko Schocher * @c: the UBIFS file-system description object 1702ff94bc40SHeiko Schocher * 1703ff94bc40SHeiko Schocher * This function returns %0 on success and a negative error code on failure. 1704ff94bc40SHeiko Schocher */ 1705ff94bc40SHeiko Schocher int dbg_check_ltab(struct ubifs_info *c) 1706ff94bc40SHeiko Schocher { 1707ff94bc40SHeiko Schocher int lnum, err, i, cnt; 1708ff94bc40SHeiko Schocher 1709ff94bc40SHeiko Schocher if (!dbg_is_chk_lprops(c)) 1710ff94bc40SHeiko Schocher return 0; 1711ff94bc40SHeiko Schocher 1712ff94bc40SHeiko Schocher /* Bring the entire tree into memory */ 1713ff94bc40SHeiko Schocher cnt = DIV_ROUND_UP(c->main_lebs, UBIFS_LPT_FANOUT); 1714ff94bc40SHeiko Schocher for (i = 0; i < cnt; i++) { 1715ff94bc40SHeiko Schocher struct ubifs_pnode *pnode; 1716ff94bc40SHeiko Schocher 1717ff94bc40SHeiko Schocher pnode = pnode_lookup(c, i); 1718ff94bc40SHeiko Schocher if (IS_ERR(pnode)) 1719ff94bc40SHeiko Schocher return PTR_ERR(pnode); 1720ff94bc40SHeiko Schocher cond_resched(); 1721ff94bc40SHeiko Schocher } 1722ff94bc40SHeiko Schocher 1723ff94bc40SHeiko Schocher /* Check nodes */ 1724ff94bc40SHeiko Schocher err = dbg_check_lpt_nodes(c, (struct ubifs_cnode *)c->nroot, 0, 0); 1725ff94bc40SHeiko Schocher if (err) 1726ff94bc40SHeiko Schocher return err; 1727ff94bc40SHeiko Schocher 1728ff94bc40SHeiko Schocher /* Check each LEB */ 1729ff94bc40SHeiko Schocher for (lnum = c->lpt_first; lnum <= c->lpt_last; lnum++) { 1730ff94bc40SHeiko Schocher err = dbg_check_ltab_lnum(c, lnum); 1731ff94bc40SHeiko Schocher if (err) { 1732*0195a7bbSHeiko Schocher ubifs_err(c, "failed at LEB %d", lnum); 1733ff94bc40SHeiko Schocher return err; 1734ff94bc40SHeiko Schocher } 1735ff94bc40SHeiko Schocher } 1736ff94bc40SHeiko Schocher 1737ff94bc40SHeiko Schocher dbg_lp("succeeded"); 1738ff94bc40SHeiko Schocher return 0; 1739ff94bc40SHeiko Schocher } 1740ff94bc40SHeiko Schocher 1741ff94bc40SHeiko Schocher /** 1742ff94bc40SHeiko Schocher * dbg_chk_lpt_free_spc - check LPT free space is enough to write entire LPT. 1743ff94bc40SHeiko Schocher * @c: the UBIFS file-system description object 1744ff94bc40SHeiko Schocher * 1745ff94bc40SHeiko Schocher * This function returns %0 on success and a negative error code on failure. 1746ff94bc40SHeiko Schocher */ 1747ff94bc40SHeiko Schocher int dbg_chk_lpt_free_spc(struct ubifs_info *c) 1748ff94bc40SHeiko Schocher { 1749ff94bc40SHeiko Schocher long long free = 0; 1750ff94bc40SHeiko Schocher int i; 1751ff94bc40SHeiko Schocher 1752ff94bc40SHeiko Schocher if (!dbg_is_chk_lprops(c)) 1753ff94bc40SHeiko Schocher return 0; 1754ff94bc40SHeiko Schocher 1755ff94bc40SHeiko Schocher for (i = 0; i < c->lpt_lebs; i++) { 1756ff94bc40SHeiko Schocher if (c->ltab[i].tgc || c->ltab[i].cmt) 1757ff94bc40SHeiko Schocher continue; 1758ff94bc40SHeiko Schocher if (i + c->lpt_first == c->nhead_lnum) 1759ff94bc40SHeiko Schocher free += c->leb_size - c->nhead_offs; 1760ff94bc40SHeiko Schocher else if (c->ltab[i].free == c->leb_size) 1761ff94bc40SHeiko Schocher free += c->leb_size; 1762ff94bc40SHeiko Schocher } 1763ff94bc40SHeiko Schocher if (free < c->lpt_sz) { 1764*0195a7bbSHeiko Schocher ubifs_err(c, "LPT space error: free %lld lpt_sz %lld", 1765ff94bc40SHeiko Schocher free, c->lpt_sz); 1766ff94bc40SHeiko Schocher ubifs_dump_lpt_info(c); 1767ff94bc40SHeiko Schocher ubifs_dump_lpt_lebs(c); 1768ff94bc40SHeiko Schocher dump_stack(); 1769ff94bc40SHeiko Schocher return -EINVAL; 1770ff94bc40SHeiko Schocher } 1771ff94bc40SHeiko Schocher return 0; 1772ff94bc40SHeiko Schocher } 1773ff94bc40SHeiko Schocher 1774ff94bc40SHeiko Schocher /** 1775ff94bc40SHeiko Schocher * dbg_chk_lpt_sz - check LPT does not write more than LPT size. 1776ff94bc40SHeiko Schocher * @c: the UBIFS file-system description object 1777ff94bc40SHeiko Schocher * @action: what to do 1778ff94bc40SHeiko Schocher * @len: length written 1779ff94bc40SHeiko Schocher * 1780ff94bc40SHeiko Schocher * This function returns %0 on success and a negative error code on failure. 1781ff94bc40SHeiko Schocher * The @action argument may be one of: 1782ff94bc40SHeiko Schocher * o %0 - LPT debugging checking starts, initialize debugging variables; 1783ff94bc40SHeiko Schocher * o %1 - wrote an LPT node, increase LPT size by @len bytes; 1784ff94bc40SHeiko Schocher * o %2 - switched to a different LEB and wasted @len bytes; 1785ff94bc40SHeiko Schocher * o %3 - check that we've written the right number of bytes. 1786ff94bc40SHeiko Schocher * o %4 - wasted @len bytes; 1787ff94bc40SHeiko Schocher */ 1788ff94bc40SHeiko Schocher int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len) 1789ff94bc40SHeiko Schocher { 1790ff94bc40SHeiko Schocher struct ubifs_debug_info *d = c->dbg; 1791ff94bc40SHeiko Schocher long long chk_lpt_sz, lpt_sz; 1792ff94bc40SHeiko Schocher int err = 0; 1793ff94bc40SHeiko Schocher 1794ff94bc40SHeiko Schocher if (!dbg_is_chk_lprops(c)) 1795ff94bc40SHeiko Schocher return 0; 1796ff94bc40SHeiko Schocher 1797ff94bc40SHeiko Schocher switch (action) { 1798ff94bc40SHeiko Schocher case 0: 1799ff94bc40SHeiko Schocher d->chk_lpt_sz = 0; 1800ff94bc40SHeiko Schocher d->chk_lpt_sz2 = 0; 1801ff94bc40SHeiko Schocher d->chk_lpt_lebs = 0; 1802ff94bc40SHeiko Schocher d->chk_lpt_wastage = 0; 1803ff94bc40SHeiko Schocher if (c->dirty_pn_cnt > c->pnode_cnt) { 1804*0195a7bbSHeiko Schocher ubifs_err(c, "dirty pnodes %d exceed max %d", 1805ff94bc40SHeiko Schocher c->dirty_pn_cnt, c->pnode_cnt); 1806ff94bc40SHeiko Schocher err = -EINVAL; 1807ff94bc40SHeiko Schocher } 1808ff94bc40SHeiko Schocher if (c->dirty_nn_cnt > c->nnode_cnt) { 1809*0195a7bbSHeiko Schocher ubifs_err(c, "dirty nnodes %d exceed max %d", 1810ff94bc40SHeiko Schocher c->dirty_nn_cnt, c->nnode_cnt); 1811ff94bc40SHeiko Schocher err = -EINVAL; 1812ff94bc40SHeiko Schocher } 1813ff94bc40SHeiko Schocher return err; 1814ff94bc40SHeiko Schocher case 1: 1815ff94bc40SHeiko Schocher d->chk_lpt_sz += len; 1816ff94bc40SHeiko Schocher return 0; 1817ff94bc40SHeiko Schocher case 2: 1818ff94bc40SHeiko Schocher d->chk_lpt_sz += len; 1819ff94bc40SHeiko Schocher d->chk_lpt_wastage += len; 1820ff94bc40SHeiko Schocher d->chk_lpt_lebs += 1; 1821ff94bc40SHeiko Schocher return 0; 1822ff94bc40SHeiko Schocher case 3: 1823ff94bc40SHeiko Schocher chk_lpt_sz = c->leb_size; 1824ff94bc40SHeiko Schocher chk_lpt_sz *= d->chk_lpt_lebs; 1825ff94bc40SHeiko Schocher chk_lpt_sz += len - c->nhead_offs; 1826ff94bc40SHeiko Schocher if (d->chk_lpt_sz != chk_lpt_sz) { 1827*0195a7bbSHeiko Schocher ubifs_err(c, "LPT wrote %lld but space used was %lld", 1828ff94bc40SHeiko Schocher d->chk_lpt_sz, chk_lpt_sz); 1829ff94bc40SHeiko Schocher err = -EINVAL; 1830ff94bc40SHeiko Schocher } 1831ff94bc40SHeiko Schocher if (d->chk_lpt_sz > c->lpt_sz) { 1832*0195a7bbSHeiko Schocher ubifs_err(c, "LPT wrote %lld but lpt_sz is %lld", 1833ff94bc40SHeiko Schocher d->chk_lpt_sz, c->lpt_sz); 1834ff94bc40SHeiko Schocher err = -EINVAL; 1835ff94bc40SHeiko Schocher } 1836ff94bc40SHeiko Schocher if (d->chk_lpt_sz2 && d->chk_lpt_sz != d->chk_lpt_sz2) { 1837*0195a7bbSHeiko Schocher ubifs_err(c, "LPT layout size %lld but wrote %lld", 1838ff94bc40SHeiko Schocher d->chk_lpt_sz, d->chk_lpt_sz2); 1839ff94bc40SHeiko Schocher err = -EINVAL; 1840ff94bc40SHeiko Schocher } 1841ff94bc40SHeiko Schocher if (d->chk_lpt_sz2 && d->new_nhead_offs != len) { 1842*0195a7bbSHeiko Schocher ubifs_err(c, "LPT new nhead offs: expected %d was %d", 1843ff94bc40SHeiko Schocher d->new_nhead_offs, len); 1844ff94bc40SHeiko Schocher err = -EINVAL; 1845ff94bc40SHeiko Schocher } 1846ff94bc40SHeiko Schocher lpt_sz = (long long)c->pnode_cnt * c->pnode_sz; 1847ff94bc40SHeiko Schocher lpt_sz += (long long)c->nnode_cnt * c->nnode_sz; 1848ff94bc40SHeiko Schocher lpt_sz += c->ltab_sz; 1849ff94bc40SHeiko Schocher if (c->big_lpt) 1850ff94bc40SHeiko Schocher lpt_sz += c->lsave_sz; 1851ff94bc40SHeiko Schocher if (d->chk_lpt_sz - d->chk_lpt_wastage > lpt_sz) { 1852*0195a7bbSHeiko Schocher ubifs_err(c, "LPT chk_lpt_sz %lld + waste %lld exceeds %lld", 1853ff94bc40SHeiko Schocher d->chk_lpt_sz, d->chk_lpt_wastage, lpt_sz); 1854ff94bc40SHeiko Schocher err = -EINVAL; 1855ff94bc40SHeiko Schocher } 1856ff94bc40SHeiko Schocher if (err) { 1857ff94bc40SHeiko Schocher ubifs_dump_lpt_info(c); 1858ff94bc40SHeiko Schocher ubifs_dump_lpt_lebs(c); 1859ff94bc40SHeiko Schocher dump_stack(); 1860ff94bc40SHeiko Schocher } 1861ff94bc40SHeiko Schocher d->chk_lpt_sz2 = d->chk_lpt_sz; 1862ff94bc40SHeiko Schocher d->chk_lpt_sz = 0; 1863ff94bc40SHeiko Schocher d->chk_lpt_wastage = 0; 1864ff94bc40SHeiko Schocher d->chk_lpt_lebs = 0; 1865ff94bc40SHeiko Schocher d->new_nhead_offs = len; 1866ff94bc40SHeiko Schocher return err; 1867ff94bc40SHeiko Schocher case 4: 1868ff94bc40SHeiko Schocher d->chk_lpt_sz += len; 1869ff94bc40SHeiko Schocher d->chk_lpt_wastage += len; 1870ff94bc40SHeiko Schocher return 0; 1871ff94bc40SHeiko Schocher default: 1872ff94bc40SHeiko Schocher return -EINVAL; 1873ff94bc40SHeiko Schocher } 1874ff94bc40SHeiko Schocher } 1875ff94bc40SHeiko Schocher 1876ff94bc40SHeiko Schocher /** 1877ff94bc40SHeiko Schocher * ubifs_dump_lpt_leb - dump an LPT LEB. 1878ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 1879ff94bc40SHeiko Schocher * @lnum: LEB number to dump 1880ff94bc40SHeiko Schocher * 1881ff94bc40SHeiko Schocher * This function dumps an LEB from LPT area. Nodes in this area are very 1882ff94bc40SHeiko Schocher * different to nodes in the main area (e.g., they do not have common headers, 1883ff94bc40SHeiko Schocher * they do not have 8-byte alignments, etc), so we have a separate function to 1884ff94bc40SHeiko Schocher * dump LPT area LEBs. Note, LPT has to be locked by the caller. 1885ff94bc40SHeiko Schocher */ 1886ff94bc40SHeiko Schocher static void dump_lpt_leb(const struct ubifs_info *c, int lnum) 1887ff94bc40SHeiko Schocher { 1888ff94bc40SHeiko Schocher int err, len = c->leb_size, node_type, node_num, node_len, offs; 1889ff94bc40SHeiko Schocher void *buf, *p; 1890ff94bc40SHeiko Schocher 1891ff94bc40SHeiko Schocher pr_err("(pid %d) start dumping LEB %d\n", current->pid, lnum); 1892ff94bc40SHeiko Schocher buf = p = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL); 1893ff94bc40SHeiko Schocher if (!buf) { 1894*0195a7bbSHeiko Schocher ubifs_err(c, "cannot allocate memory to dump LPT"); 1895ff94bc40SHeiko Schocher return; 1896ff94bc40SHeiko Schocher } 1897ff94bc40SHeiko Schocher 1898ff94bc40SHeiko Schocher err = ubifs_leb_read(c, lnum, buf, 0, c->leb_size, 1); 1899ff94bc40SHeiko Schocher if (err) 1900ff94bc40SHeiko Schocher goto out; 1901ff94bc40SHeiko Schocher 1902ff94bc40SHeiko Schocher while (1) { 1903ff94bc40SHeiko Schocher offs = c->leb_size - len; 1904ff94bc40SHeiko Schocher if (!is_a_node(c, p, len)) { 1905ff94bc40SHeiko Schocher int pad_len; 1906ff94bc40SHeiko Schocher 1907ff94bc40SHeiko Schocher pad_len = get_pad_len(c, p, len); 1908ff94bc40SHeiko Schocher if (pad_len) { 1909ff94bc40SHeiko Schocher pr_err("LEB %d:%d, pad %d bytes\n", 1910ff94bc40SHeiko Schocher lnum, offs, pad_len); 1911ff94bc40SHeiko Schocher p += pad_len; 1912ff94bc40SHeiko Schocher len -= pad_len; 1913ff94bc40SHeiko Schocher continue; 1914ff94bc40SHeiko Schocher } 1915ff94bc40SHeiko Schocher if (len) 1916ff94bc40SHeiko Schocher pr_err("LEB %d:%d, free %d bytes\n", 1917ff94bc40SHeiko Schocher lnum, offs, len); 1918ff94bc40SHeiko Schocher break; 1919ff94bc40SHeiko Schocher } 1920ff94bc40SHeiko Schocher 1921ff94bc40SHeiko Schocher node_type = get_lpt_node_type(c, p, &node_num); 1922ff94bc40SHeiko Schocher switch (node_type) { 1923ff94bc40SHeiko Schocher case UBIFS_LPT_PNODE: 1924ff94bc40SHeiko Schocher { 1925ff94bc40SHeiko Schocher node_len = c->pnode_sz; 1926ff94bc40SHeiko Schocher if (c->big_lpt) 1927ff94bc40SHeiko Schocher pr_err("LEB %d:%d, pnode num %d\n", 1928ff94bc40SHeiko Schocher lnum, offs, node_num); 1929ff94bc40SHeiko Schocher else 1930ff94bc40SHeiko Schocher pr_err("LEB %d:%d, pnode\n", lnum, offs); 1931ff94bc40SHeiko Schocher break; 1932ff94bc40SHeiko Schocher } 1933ff94bc40SHeiko Schocher case UBIFS_LPT_NNODE: 1934ff94bc40SHeiko Schocher { 1935ff94bc40SHeiko Schocher int i; 1936ff94bc40SHeiko Schocher struct ubifs_nnode nnode; 1937ff94bc40SHeiko Schocher 1938ff94bc40SHeiko Schocher node_len = c->nnode_sz; 1939ff94bc40SHeiko Schocher if (c->big_lpt) 1940ff94bc40SHeiko Schocher pr_err("LEB %d:%d, nnode num %d, ", 1941ff94bc40SHeiko Schocher lnum, offs, node_num); 1942ff94bc40SHeiko Schocher else 1943ff94bc40SHeiko Schocher pr_err("LEB %d:%d, nnode, ", 1944ff94bc40SHeiko Schocher lnum, offs); 1945ff94bc40SHeiko Schocher err = ubifs_unpack_nnode(c, p, &nnode); 1946*0195a7bbSHeiko Schocher if (err) { 1947*0195a7bbSHeiko Schocher pr_err("failed to unpack_node, error %d\n", 1948*0195a7bbSHeiko Schocher err); 1949*0195a7bbSHeiko Schocher break; 1950*0195a7bbSHeiko Schocher } 1951ff94bc40SHeiko Schocher for (i = 0; i < UBIFS_LPT_FANOUT; i++) { 1952ff94bc40SHeiko Schocher pr_cont("%d:%d", nnode.nbranch[i].lnum, 1953ff94bc40SHeiko Schocher nnode.nbranch[i].offs); 1954ff94bc40SHeiko Schocher if (i != UBIFS_LPT_FANOUT - 1) 1955ff94bc40SHeiko Schocher pr_cont(", "); 1956ff94bc40SHeiko Schocher } 1957ff94bc40SHeiko Schocher pr_cont("\n"); 1958ff94bc40SHeiko Schocher break; 1959ff94bc40SHeiko Schocher } 1960ff94bc40SHeiko Schocher case UBIFS_LPT_LTAB: 1961ff94bc40SHeiko Schocher node_len = c->ltab_sz; 1962ff94bc40SHeiko Schocher pr_err("LEB %d:%d, ltab\n", lnum, offs); 1963ff94bc40SHeiko Schocher break; 1964ff94bc40SHeiko Schocher case UBIFS_LPT_LSAVE: 1965ff94bc40SHeiko Schocher node_len = c->lsave_sz; 1966ff94bc40SHeiko Schocher pr_err("LEB %d:%d, lsave len\n", lnum, offs); 1967ff94bc40SHeiko Schocher break; 1968ff94bc40SHeiko Schocher default: 1969*0195a7bbSHeiko Schocher ubifs_err(c, "LPT node type %d not recognized", node_type); 1970ff94bc40SHeiko Schocher goto out; 1971ff94bc40SHeiko Schocher } 1972ff94bc40SHeiko Schocher 1973ff94bc40SHeiko Schocher p += node_len; 1974ff94bc40SHeiko Schocher len -= node_len; 1975ff94bc40SHeiko Schocher } 1976ff94bc40SHeiko Schocher 1977ff94bc40SHeiko Schocher pr_err("(pid %d) finish dumping LEB %d\n", current->pid, lnum); 1978ff94bc40SHeiko Schocher out: 1979ff94bc40SHeiko Schocher vfree(buf); 1980ff94bc40SHeiko Schocher return; 1981ff94bc40SHeiko Schocher } 1982ff94bc40SHeiko Schocher 1983ff94bc40SHeiko Schocher /** 1984ff94bc40SHeiko Schocher * ubifs_dump_lpt_lebs - dump LPT lebs. 1985ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 1986ff94bc40SHeiko Schocher * 1987ff94bc40SHeiko Schocher * This function dumps all LPT LEBs. The caller has to make sure the LPT is 1988ff94bc40SHeiko Schocher * locked. 1989ff94bc40SHeiko Schocher */ 1990ff94bc40SHeiko Schocher void ubifs_dump_lpt_lebs(const struct ubifs_info *c) 1991ff94bc40SHeiko Schocher { 1992ff94bc40SHeiko Schocher int i; 1993ff94bc40SHeiko Schocher 1994ff94bc40SHeiko Schocher pr_err("(pid %d) start dumping all LPT LEBs\n", current->pid); 1995ff94bc40SHeiko Schocher for (i = 0; i < c->lpt_lebs; i++) 1996ff94bc40SHeiko Schocher dump_lpt_leb(c, i + c->lpt_first); 1997ff94bc40SHeiko Schocher pr_err("(pid %d) finish dumping all LPT LEBs\n", current->pid); 1998ff94bc40SHeiko Schocher } 1999ff94bc40SHeiko Schocher 2000ff94bc40SHeiko Schocher /** 2001ff94bc40SHeiko Schocher * dbg_populate_lsave - debugging version of 'populate_lsave()' 2002ff94bc40SHeiko Schocher * @c: UBIFS file-system description object 2003ff94bc40SHeiko Schocher * 2004ff94bc40SHeiko Schocher * This is a debugging version for 'populate_lsave()' which populates lsave 2005ff94bc40SHeiko Schocher * with random LEBs instead of useful LEBs, which is good for test coverage. 2006ff94bc40SHeiko Schocher * Returns zero if lsave has not been populated (this debugging feature is 2007ff94bc40SHeiko Schocher * disabled) an non-zero if lsave has been populated. 2008ff94bc40SHeiko Schocher */ 2009ff94bc40SHeiko Schocher static int dbg_populate_lsave(struct ubifs_info *c) 2010ff94bc40SHeiko Schocher { 2011ff94bc40SHeiko Schocher struct ubifs_lprops *lprops; 2012ff94bc40SHeiko Schocher struct ubifs_lpt_heap *heap; 2013ff94bc40SHeiko Schocher int i; 2014ff94bc40SHeiko Schocher 2015ff94bc40SHeiko Schocher if (!dbg_is_chk_gen(c)) 2016ff94bc40SHeiko Schocher return 0; 2017ff94bc40SHeiko Schocher if (prandom_u32() & 3) 2018ff94bc40SHeiko Schocher return 0; 2019ff94bc40SHeiko Schocher 2020ff94bc40SHeiko Schocher for (i = 0; i < c->lsave_cnt; i++) 2021ff94bc40SHeiko Schocher c->lsave[i] = c->main_first; 2022ff94bc40SHeiko Schocher 2023ff94bc40SHeiko Schocher list_for_each_entry(lprops, &c->empty_list, list) 2024ff94bc40SHeiko Schocher c->lsave[prandom_u32() % c->lsave_cnt] = lprops->lnum; 2025ff94bc40SHeiko Schocher list_for_each_entry(lprops, &c->freeable_list, list) 2026ff94bc40SHeiko Schocher c->lsave[prandom_u32() % c->lsave_cnt] = lprops->lnum; 2027ff94bc40SHeiko Schocher list_for_each_entry(lprops, &c->frdi_idx_list, list) 2028ff94bc40SHeiko Schocher c->lsave[prandom_u32() % c->lsave_cnt] = lprops->lnum; 2029ff94bc40SHeiko Schocher 2030ff94bc40SHeiko Schocher heap = &c->lpt_heap[LPROPS_DIRTY_IDX - 1]; 2031ff94bc40SHeiko Schocher for (i = 0; i < heap->cnt; i++) 2032ff94bc40SHeiko Schocher c->lsave[prandom_u32() % c->lsave_cnt] = heap->arr[i]->lnum; 2033ff94bc40SHeiko Schocher heap = &c->lpt_heap[LPROPS_DIRTY - 1]; 2034ff94bc40SHeiko Schocher for (i = 0; i < heap->cnt; i++) 2035ff94bc40SHeiko Schocher c->lsave[prandom_u32() % c->lsave_cnt] = heap->arr[i]->lnum; 2036ff94bc40SHeiko Schocher heap = &c->lpt_heap[LPROPS_FREE - 1]; 2037ff94bc40SHeiko Schocher for (i = 0; i < heap->cnt; i++) 2038ff94bc40SHeiko Schocher c->lsave[prandom_u32() % c->lsave_cnt] = heap->arr[i]->lnum; 2039ff94bc40SHeiko Schocher 2040ff94bc40SHeiko Schocher return 1; 2041ff94bc40SHeiko Schocher } 2042ff94bc40SHeiko Schocher #endif 2043