12b27bdccSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21e51764aSArtem Bityutskiy /*
31e51764aSArtem Bityutskiy * This file is part of UBIFS.
41e51764aSArtem Bityutskiy *
51e51764aSArtem Bityutskiy * Copyright (C) 2006-2008 Nokia Corporation.
61e51764aSArtem Bityutskiy *
71e51764aSArtem Bityutskiy * Authors: Adrian Hunter
81e51764aSArtem Bityutskiy * Artem Bityutskiy (Битюцкий Артём)
91e51764aSArtem Bityutskiy */
101e51764aSArtem Bityutskiy
111e51764aSArtem Bityutskiy /*
121e51764aSArtem Bityutskiy * This file implements the LEB properties tree (LPT) area. The LPT area
131e51764aSArtem Bityutskiy * contains the LEB properties tree, a table of LPT area eraseblocks (ltab), and
141e51764aSArtem Bityutskiy * (for the "big" model) a table of saved LEB numbers (lsave). The LPT area sits
151e51764aSArtem Bityutskiy * between the log and the orphan area.
161e51764aSArtem Bityutskiy *
171e51764aSArtem Bityutskiy * The LPT area is like a miniature self-contained file system. It is required
181e51764aSArtem Bityutskiy * that it never runs out of space, is fast to access and update, and scales
191e51764aSArtem Bityutskiy * logarithmically. The LEB properties tree is implemented as a wandering tree
201e51764aSArtem Bityutskiy * much like the TNC, and the LPT area has its own garbage collection.
211e51764aSArtem Bityutskiy *
221e51764aSArtem Bityutskiy * The LPT has two slightly different forms called the "small model" and the
231e51764aSArtem Bityutskiy * "big model". The small model is used when the entire LEB properties table
241e51764aSArtem Bityutskiy * can be written into a single eraseblock. In that case, garbage collection
251e51764aSArtem Bityutskiy * consists of just writing the whole table, which therefore makes all other
261e51764aSArtem Bityutskiy * eraseblocks reusable. In the case of the big model, dirty eraseblocks are
2745e12d90SArtem Bityutskiy * selected for garbage collection, which consists of marking the clean nodes in
281e51764aSArtem Bityutskiy * that LEB as dirty, and then only the dirty nodes are written out. Also, in
291e51764aSArtem Bityutskiy * the case of the big model, a table of LEB numbers is saved so that the entire
301e51764aSArtem Bityutskiy * LPT does not to be scanned looking for empty eraseblocks when UBIFS is first
311e51764aSArtem Bityutskiy * mounted.
321e51764aSArtem Bityutskiy */
331e51764aSArtem Bityutskiy
341e51764aSArtem Bityutskiy #include "ubifs.h"
354d61db4fSArtem Bityutskiy #include <linux/crc16.h>
364d61db4fSArtem Bityutskiy #include <linux/math64.h>
375a0e3ad6STejun Heo #include <linux/slab.h>
381e51764aSArtem Bityutskiy
391e51764aSArtem Bityutskiy /**
401e51764aSArtem Bityutskiy * do_calc_lpt_geom - calculate sizes for the LPT area.
411e51764aSArtem Bityutskiy * @c: the UBIFS file-system description object
421e51764aSArtem Bityutskiy *
431e51764aSArtem Bityutskiy * Calculate the sizes of LPT bit fields, nodes, and tree, based on the
441e51764aSArtem Bityutskiy * properties of the flash and whether LPT is "big" (c->big_lpt).
451e51764aSArtem Bityutskiy */
do_calc_lpt_geom(struct ubifs_info * c)461e51764aSArtem Bityutskiy static void do_calc_lpt_geom(struct ubifs_info *c)
471e51764aSArtem Bityutskiy {
481e51764aSArtem Bityutskiy int i, n, bits, per_leb_wastage, max_pnode_cnt;
491e51764aSArtem Bityutskiy long long sz, tot_wastage;
501e51764aSArtem Bityutskiy
511e51764aSArtem Bityutskiy n = c->main_lebs + c->max_leb_cnt - c->leb_cnt;
521e51764aSArtem Bityutskiy max_pnode_cnt = DIV_ROUND_UP(n, UBIFS_LPT_FANOUT);
531e51764aSArtem Bityutskiy
541e51764aSArtem Bityutskiy c->lpt_hght = 1;
551e51764aSArtem Bityutskiy n = UBIFS_LPT_FANOUT;
561e51764aSArtem Bityutskiy while (n < max_pnode_cnt) {
571e51764aSArtem Bityutskiy c->lpt_hght += 1;
581e51764aSArtem Bityutskiy n <<= UBIFS_LPT_FANOUT_SHIFT;
591e51764aSArtem Bityutskiy }
601e51764aSArtem Bityutskiy
611e51764aSArtem Bityutskiy c->pnode_cnt = DIV_ROUND_UP(c->main_lebs, UBIFS_LPT_FANOUT);
621e51764aSArtem Bityutskiy
631e51764aSArtem Bityutskiy n = DIV_ROUND_UP(c->pnode_cnt, UBIFS_LPT_FANOUT);
641e51764aSArtem Bityutskiy c->nnode_cnt = n;
651e51764aSArtem Bityutskiy for (i = 1; i < c->lpt_hght; i++) {
661e51764aSArtem Bityutskiy n = DIV_ROUND_UP(n, UBIFS_LPT_FANOUT);
671e51764aSArtem Bityutskiy c->nnode_cnt += n;
681e51764aSArtem Bityutskiy }
691e51764aSArtem Bityutskiy
701e51764aSArtem Bityutskiy c->space_bits = fls(c->leb_size) - 3;
711e51764aSArtem Bityutskiy c->lpt_lnum_bits = fls(c->lpt_lebs);
721e51764aSArtem Bityutskiy c->lpt_offs_bits = fls(c->leb_size - 1);
731e51764aSArtem Bityutskiy c->lpt_spc_bits = fls(c->leb_size);
741e51764aSArtem Bityutskiy
751e51764aSArtem Bityutskiy n = DIV_ROUND_UP(c->max_leb_cnt, UBIFS_LPT_FANOUT);
761e51764aSArtem Bityutskiy c->pcnt_bits = fls(n - 1);
771e51764aSArtem Bityutskiy
781e51764aSArtem Bityutskiy c->lnum_bits = fls(c->max_leb_cnt - 1);
791e51764aSArtem Bityutskiy
801e51764aSArtem Bityutskiy bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS +
811e51764aSArtem Bityutskiy (c->big_lpt ? c->pcnt_bits : 0) +
821e51764aSArtem Bityutskiy (c->space_bits * 2 + 1) * UBIFS_LPT_FANOUT;
831e51764aSArtem Bityutskiy c->pnode_sz = (bits + 7) / 8;
841e51764aSArtem Bityutskiy
851e51764aSArtem Bityutskiy bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS +
861e51764aSArtem Bityutskiy (c->big_lpt ? c->pcnt_bits : 0) +
871e51764aSArtem Bityutskiy (c->lpt_lnum_bits + c->lpt_offs_bits) * UBIFS_LPT_FANOUT;
881e51764aSArtem Bityutskiy c->nnode_sz = (bits + 7) / 8;
891e51764aSArtem Bityutskiy
901e51764aSArtem Bityutskiy bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS +
911e51764aSArtem Bityutskiy c->lpt_lebs * c->lpt_spc_bits * 2;
921e51764aSArtem Bityutskiy c->ltab_sz = (bits + 7) / 8;
931e51764aSArtem Bityutskiy
941e51764aSArtem Bityutskiy bits = UBIFS_LPT_CRC_BITS + UBIFS_LPT_TYPE_BITS +
951e51764aSArtem Bityutskiy c->lnum_bits * c->lsave_cnt;
961e51764aSArtem Bityutskiy c->lsave_sz = (bits + 7) / 8;
971e51764aSArtem Bityutskiy
981e51764aSArtem Bityutskiy /* Calculate the minimum LPT size */
991e51764aSArtem Bityutskiy c->lpt_sz = (long long)c->pnode_cnt * c->pnode_sz;
1001e51764aSArtem Bityutskiy c->lpt_sz += (long long)c->nnode_cnt * c->nnode_sz;
1011e51764aSArtem Bityutskiy c->lpt_sz += c->ltab_sz;
10273944a6dSAdrian Hunter if (c->big_lpt)
1031e51764aSArtem Bityutskiy c->lpt_sz += c->lsave_sz;
1041e51764aSArtem Bityutskiy
1051e51764aSArtem Bityutskiy /* Add wastage */
1061e51764aSArtem Bityutskiy sz = c->lpt_sz;
1071e51764aSArtem Bityutskiy per_leb_wastage = max_t(int, c->pnode_sz, c->nnode_sz);
1081e51764aSArtem Bityutskiy sz += per_leb_wastage;
1091e51764aSArtem Bityutskiy tot_wastage = per_leb_wastage;
1101e51764aSArtem Bityutskiy while (sz > c->leb_size) {
1111e51764aSArtem Bityutskiy sz += per_leb_wastage;
1121e51764aSArtem Bityutskiy sz -= c->leb_size;
1131e51764aSArtem Bityutskiy tot_wastage += per_leb_wastage;
1141e51764aSArtem Bityutskiy }
1151e51764aSArtem Bityutskiy tot_wastage += ALIGN(sz, c->min_io_size) - sz;
1161e51764aSArtem Bityutskiy c->lpt_sz += tot_wastage;
1171e51764aSArtem Bityutskiy }
1181e51764aSArtem Bityutskiy
1191e51764aSArtem Bityutskiy /**
1201e51764aSArtem Bityutskiy * ubifs_calc_lpt_geom - calculate and check sizes for the LPT area.
1211e51764aSArtem Bityutskiy * @c: the UBIFS file-system description object
1221e51764aSArtem Bityutskiy *
1231e51764aSArtem Bityutskiy * This function returns %0 on success and a negative error code on failure.
1241e51764aSArtem Bityutskiy */
ubifs_calc_lpt_geom(struct ubifs_info * c)1251e51764aSArtem Bityutskiy int ubifs_calc_lpt_geom(struct ubifs_info *c)
1261e51764aSArtem Bityutskiy {
1271e51764aSArtem Bityutskiy int lebs_needed;
1284d61db4fSArtem Bityutskiy long long sz;
1291e51764aSArtem Bityutskiy
1301e51764aSArtem Bityutskiy do_calc_lpt_geom(c);
1311e51764aSArtem Bityutskiy
1321e51764aSArtem Bityutskiy /* Verify that lpt_lebs is big enough */
1331e51764aSArtem Bityutskiy sz = c->lpt_sz * 2; /* Must have at least 2 times the size */
1344d61db4fSArtem Bityutskiy lebs_needed = div_u64(sz + c->leb_size - 1, c->leb_size);
1351e51764aSArtem Bityutskiy if (lebs_needed > c->lpt_lebs) {
136235c362bSSheng Yong ubifs_err(c, "too few LPT LEBs");
1371e51764aSArtem Bityutskiy return -EINVAL;
1381e51764aSArtem Bityutskiy }
1391e51764aSArtem Bityutskiy
1401e51764aSArtem Bityutskiy /* Verify that ltab fits in a single LEB (since ltab is a single node */
1411e51764aSArtem Bityutskiy if (c->ltab_sz > c->leb_size) {
142235c362bSSheng Yong ubifs_err(c, "LPT ltab too big");
1431e51764aSArtem Bityutskiy return -EINVAL;
1441e51764aSArtem Bityutskiy }
1451e51764aSArtem Bityutskiy
1461e51764aSArtem Bityutskiy c->check_lpt_free = c->big_lpt;
1471e51764aSArtem Bityutskiy return 0;
1481e51764aSArtem Bityutskiy }
1491e51764aSArtem Bityutskiy
1501e51764aSArtem Bityutskiy /**
1511e51764aSArtem Bityutskiy * calc_dflt_lpt_geom - calculate default LPT geometry.
1521e51764aSArtem Bityutskiy * @c: the UBIFS file-system description object
1531e51764aSArtem Bityutskiy * @main_lebs: number of main area LEBs is passed and returned here
1541e51764aSArtem Bityutskiy * @big_lpt: whether the LPT area is "big" is returned here
1551e51764aSArtem Bityutskiy *
1561e51764aSArtem Bityutskiy * The size of the LPT area depends on parameters that themselves are dependent
1571e51764aSArtem Bityutskiy * on the size of the LPT area. This function, successively recalculates the LPT
1581e51764aSArtem Bityutskiy * area geometry until the parameters and resultant geometry are consistent.
1591e51764aSArtem Bityutskiy *
1601e51764aSArtem Bityutskiy * This function returns %0 on success and a negative error code on failure.
1611e51764aSArtem Bityutskiy */
calc_dflt_lpt_geom(struct ubifs_info * c,int * main_lebs,int * big_lpt)1621e51764aSArtem Bityutskiy static int calc_dflt_lpt_geom(struct ubifs_info *c, int *main_lebs,
1631e51764aSArtem Bityutskiy int *big_lpt)
1641e51764aSArtem Bityutskiy {
1651e51764aSArtem Bityutskiy int i, lebs_needed;
1664d61db4fSArtem Bityutskiy long long sz;
1671e51764aSArtem Bityutskiy
1681e51764aSArtem Bityutskiy /* Start by assuming the minimum number of LPT LEBs */
1691e51764aSArtem Bityutskiy c->lpt_lebs = UBIFS_MIN_LPT_LEBS;
1701e51764aSArtem Bityutskiy c->main_lebs = *main_lebs - c->lpt_lebs;
1711e51764aSArtem Bityutskiy if (c->main_lebs <= 0)
1721e51764aSArtem Bityutskiy return -EINVAL;
1731e51764aSArtem Bityutskiy
1741e51764aSArtem Bityutskiy /* And assume we will use the small LPT model */
1751e51764aSArtem Bityutskiy c->big_lpt = 0;
1761e51764aSArtem Bityutskiy
1771e51764aSArtem Bityutskiy /*
1781e51764aSArtem Bityutskiy * Calculate the geometry based on assumptions above and then see if it
1791e51764aSArtem Bityutskiy * makes sense
1801e51764aSArtem Bityutskiy */
1811e51764aSArtem Bityutskiy do_calc_lpt_geom(c);
1821e51764aSArtem Bityutskiy
1831e51764aSArtem Bityutskiy /* Small LPT model must have lpt_sz < leb_size */
1841e51764aSArtem Bityutskiy if (c->lpt_sz > c->leb_size) {
1851e51764aSArtem Bityutskiy /* Nope, so try again using big LPT model */
1861e51764aSArtem Bityutskiy c->big_lpt = 1;
1871e51764aSArtem Bityutskiy do_calc_lpt_geom(c);
1881e51764aSArtem Bityutskiy }
1891e51764aSArtem Bityutskiy
1901e51764aSArtem Bityutskiy /* Now check there are enough LPT LEBs */
1911e51764aSArtem Bityutskiy for (i = 0; i < 64 ; i++) {
1921e51764aSArtem Bityutskiy sz = c->lpt_sz * 4; /* Allow 4 times the size */
1934d61db4fSArtem Bityutskiy lebs_needed = div_u64(sz + c->leb_size - 1, c->leb_size);
1941e51764aSArtem Bityutskiy if (lebs_needed > c->lpt_lebs) {
1951e51764aSArtem Bityutskiy /* Not enough LPT LEBs so try again with more */
1961e51764aSArtem Bityutskiy c->lpt_lebs = lebs_needed;
1971e51764aSArtem Bityutskiy c->main_lebs = *main_lebs - c->lpt_lebs;
1981e51764aSArtem Bityutskiy if (c->main_lebs <= 0)
1991e51764aSArtem Bityutskiy return -EINVAL;
2001e51764aSArtem Bityutskiy do_calc_lpt_geom(c);
2011e51764aSArtem Bityutskiy continue;
2021e51764aSArtem Bityutskiy }
2031e51764aSArtem Bityutskiy if (c->ltab_sz > c->leb_size) {
204235c362bSSheng Yong ubifs_err(c, "LPT ltab too big");
2051e51764aSArtem Bityutskiy return -EINVAL;
2061e51764aSArtem Bityutskiy }
2071e51764aSArtem Bityutskiy *main_lebs = c->main_lebs;
2081e51764aSArtem Bityutskiy *big_lpt = c->big_lpt;
2091e51764aSArtem Bityutskiy return 0;
2101e51764aSArtem Bityutskiy }
2111e51764aSArtem Bityutskiy return -EINVAL;
2121e51764aSArtem Bityutskiy }
2131e51764aSArtem Bityutskiy
2141e51764aSArtem Bityutskiy /**
2151e51764aSArtem Bityutskiy * pack_bits - pack bit fields end-to-end.
2166eb61d58SRichard Weinberger * @c: UBIFS file-system description object
2171e51764aSArtem Bityutskiy * @addr: address at which to pack (passed and next address returned)
2181e51764aSArtem Bityutskiy * @pos: bit position at which to pack (passed and next position returned)
2191e51764aSArtem Bityutskiy * @val: value to pack
2201e51764aSArtem Bityutskiy * @nrbits: number of bits of value to pack (1-32)
2211e51764aSArtem Bityutskiy */
pack_bits(const struct ubifs_info * c,uint8_t ** addr,int * pos,uint32_t val,int nrbits)2226eb61d58SRichard Weinberger static void pack_bits(const struct ubifs_info *c, uint8_t **addr, int *pos, uint32_t val, int nrbits)
2231e51764aSArtem Bityutskiy {
2241e51764aSArtem Bityutskiy uint8_t *p = *addr;
2251e51764aSArtem Bityutskiy int b = *pos;
2261e51764aSArtem Bityutskiy
2276eb61d58SRichard Weinberger ubifs_assert(c, nrbits > 0);
2286eb61d58SRichard Weinberger ubifs_assert(c, nrbits <= 32);
2296eb61d58SRichard Weinberger ubifs_assert(c, *pos >= 0);
2306eb61d58SRichard Weinberger ubifs_assert(c, *pos < 8);
2316eb61d58SRichard Weinberger ubifs_assert(c, (val >> nrbits) == 0 || nrbits == 32);
2321e51764aSArtem Bityutskiy if (b) {
2331e51764aSArtem Bityutskiy *p |= ((uint8_t)val) << b;
2341e51764aSArtem Bityutskiy nrbits += b;
2351e51764aSArtem Bityutskiy if (nrbits > 8) {
2361e51764aSArtem Bityutskiy *++p = (uint8_t)(val >>= (8 - b));
2371e51764aSArtem Bityutskiy if (nrbits > 16) {
2381e51764aSArtem Bityutskiy *++p = (uint8_t)(val >>= 8);
2391e51764aSArtem Bityutskiy if (nrbits > 24) {
2401e51764aSArtem Bityutskiy *++p = (uint8_t)(val >>= 8);
2411e51764aSArtem Bityutskiy if (nrbits > 32)
2421e51764aSArtem Bityutskiy *++p = (uint8_t)(val >>= 8);
2431e51764aSArtem Bityutskiy }
2441e51764aSArtem Bityutskiy }
2451e51764aSArtem Bityutskiy }
2461e51764aSArtem Bityutskiy } else {
2471e51764aSArtem Bityutskiy *p = (uint8_t)val;
2481e51764aSArtem Bityutskiy if (nrbits > 8) {
2491e51764aSArtem Bityutskiy *++p = (uint8_t)(val >>= 8);
2501e51764aSArtem Bityutskiy if (nrbits > 16) {
2511e51764aSArtem Bityutskiy *++p = (uint8_t)(val >>= 8);
2521e51764aSArtem Bityutskiy if (nrbits > 24)
2531e51764aSArtem Bityutskiy *++p = (uint8_t)(val >>= 8);
2541e51764aSArtem Bityutskiy }
2551e51764aSArtem Bityutskiy }
2561e51764aSArtem Bityutskiy }
2571e51764aSArtem Bityutskiy b = nrbits & 7;
2581e51764aSArtem Bityutskiy if (b == 0)
2591e51764aSArtem Bityutskiy p++;
2601e51764aSArtem Bityutskiy *addr = p;
2611e51764aSArtem Bityutskiy *pos = b;
2621e51764aSArtem Bityutskiy }
2631e51764aSArtem Bityutskiy
2641e51764aSArtem Bityutskiy /**
2651e51764aSArtem Bityutskiy * ubifs_unpack_bits - unpack bit fields.
2666eb61d58SRichard Weinberger * @c: UBIFS file-system description object
2671e51764aSArtem Bityutskiy * @addr: address at which to unpack (passed and next address returned)
2681e51764aSArtem Bityutskiy * @pos: bit position at which to unpack (passed and next position returned)
2691e51764aSArtem Bityutskiy * @nrbits: number of bits of value to unpack (1-32)
2701e51764aSArtem Bityutskiy *
2711e51764aSArtem Bityutskiy * This functions returns the value unpacked.
2721e51764aSArtem Bityutskiy */
ubifs_unpack_bits(const struct ubifs_info * c,uint8_t ** addr,int * pos,int nrbits)2736eb61d58SRichard Weinberger uint32_t ubifs_unpack_bits(const struct ubifs_info *c, uint8_t **addr, int *pos, int nrbits)
2741e51764aSArtem Bityutskiy {
2751e51764aSArtem Bityutskiy const int k = 32 - nrbits;
2761e51764aSArtem Bityutskiy uint8_t *p = *addr;
2771e51764aSArtem Bityutskiy int b = *pos;
2783f649ab7SKees Cook uint32_t val;
279727d2dc0SAdrian Hunter const int bytes = (nrbits + b + 7) >> 3;
2801e51764aSArtem Bityutskiy
2816eb61d58SRichard Weinberger ubifs_assert(c, nrbits > 0);
2826eb61d58SRichard Weinberger ubifs_assert(c, nrbits <= 32);
2836eb61d58SRichard Weinberger ubifs_assert(c, *pos >= 0);
2846eb61d58SRichard Weinberger ubifs_assert(c, *pos < 8);
2851e51764aSArtem Bityutskiy if (b) {
286727d2dc0SAdrian Hunter switch (bytes) {
287727d2dc0SAdrian Hunter case 2:
288727d2dc0SAdrian Hunter val = p[1];
289727d2dc0SAdrian Hunter break;
290727d2dc0SAdrian Hunter case 3:
291727d2dc0SAdrian Hunter val = p[1] | ((uint32_t)p[2] << 8);
292727d2dc0SAdrian Hunter break;
293727d2dc0SAdrian Hunter case 4:
294727d2dc0SAdrian Hunter val = p[1] | ((uint32_t)p[2] << 8) |
295727d2dc0SAdrian Hunter ((uint32_t)p[3] << 16);
296727d2dc0SAdrian Hunter break;
297727d2dc0SAdrian Hunter case 5:
298727d2dc0SAdrian Hunter val = p[1] | ((uint32_t)p[2] << 8) |
299727d2dc0SAdrian Hunter ((uint32_t)p[3] << 16) |
3001e51764aSArtem Bityutskiy ((uint32_t)p[4] << 24);
301727d2dc0SAdrian Hunter }
3021e51764aSArtem Bityutskiy val <<= (8 - b);
3031e51764aSArtem Bityutskiy val |= *p >> b;
3041e51764aSArtem Bityutskiy nrbits += b;
305727d2dc0SAdrian Hunter } else {
306727d2dc0SAdrian Hunter switch (bytes) {
307727d2dc0SAdrian Hunter case 1:
308727d2dc0SAdrian Hunter val = p[0];
309727d2dc0SAdrian Hunter break;
310727d2dc0SAdrian Hunter case 2:
311727d2dc0SAdrian Hunter val = p[0] | ((uint32_t)p[1] << 8);
312727d2dc0SAdrian Hunter break;
313727d2dc0SAdrian Hunter case 3:
314727d2dc0SAdrian Hunter val = p[0] | ((uint32_t)p[1] << 8) |
315727d2dc0SAdrian Hunter ((uint32_t)p[2] << 16);
316727d2dc0SAdrian Hunter break;
317727d2dc0SAdrian Hunter case 4:
318727d2dc0SAdrian Hunter val = p[0] | ((uint32_t)p[1] << 8) |
319727d2dc0SAdrian Hunter ((uint32_t)p[2] << 16) |
3201e51764aSArtem Bityutskiy ((uint32_t)p[3] << 24);
321727d2dc0SAdrian Hunter break;
322727d2dc0SAdrian Hunter }
323727d2dc0SAdrian Hunter }
3241e51764aSArtem Bityutskiy val <<= k;
3251e51764aSArtem Bityutskiy val >>= k;
3261e51764aSArtem Bityutskiy b = nrbits & 7;
327727d2dc0SAdrian Hunter p += nrbits >> 3;
3281e51764aSArtem Bityutskiy *addr = p;
3291e51764aSArtem Bityutskiy *pos = b;
3306eb61d58SRichard Weinberger ubifs_assert(c, (val >> nrbits) == 0 || nrbits - b == 32);
3311e51764aSArtem Bityutskiy return val;
3321e51764aSArtem Bityutskiy }
3331e51764aSArtem Bityutskiy
3341e51764aSArtem Bityutskiy /**
3351e51764aSArtem Bityutskiy * ubifs_pack_pnode - pack all the bit fields of a pnode.
3361e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
3371e51764aSArtem Bityutskiy * @buf: buffer into which to pack
3381e51764aSArtem Bityutskiy * @pnode: pnode to pack
3391e51764aSArtem Bityutskiy */
ubifs_pack_pnode(struct ubifs_info * c,void * buf,struct ubifs_pnode * pnode)3401e51764aSArtem Bityutskiy void ubifs_pack_pnode(struct ubifs_info *c, void *buf,
3411e51764aSArtem Bityutskiy struct ubifs_pnode *pnode)
3421e51764aSArtem Bityutskiy {
3431e51764aSArtem Bityutskiy uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
3441e51764aSArtem Bityutskiy int i, pos = 0;
3451e51764aSArtem Bityutskiy uint16_t crc;
3461e51764aSArtem Bityutskiy
3476eb61d58SRichard Weinberger pack_bits(c, &addr, &pos, UBIFS_LPT_PNODE, UBIFS_LPT_TYPE_BITS);
3481e51764aSArtem Bityutskiy if (c->big_lpt)
3496eb61d58SRichard Weinberger pack_bits(c, &addr, &pos, pnode->num, c->pcnt_bits);
3501e51764aSArtem Bityutskiy for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
3516eb61d58SRichard Weinberger pack_bits(c, &addr, &pos, pnode->lprops[i].free >> 3,
3521e51764aSArtem Bityutskiy c->space_bits);
3536eb61d58SRichard Weinberger pack_bits(c, &addr, &pos, pnode->lprops[i].dirty >> 3,
3541e51764aSArtem Bityutskiy c->space_bits);
3551e51764aSArtem Bityutskiy if (pnode->lprops[i].flags & LPROPS_INDEX)
3566eb61d58SRichard Weinberger pack_bits(c, &addr, &pos, 1, 1);
3571e51764aSArtem Bityutskiy else
3586eb61d58SRichard Weinberger pack_bits(c, &addr, &pos, 0, 1);
3591e51764aSArtem Bityutskiy }
3601e51764aSArtem Bityutskiy crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
3611e51764aSArtem Bityutskiy c->pnode_sz - UBIFS_LPT_CRC_BYTES);
3621e51764aSArtem Bityutskiy addr = buf;
3631e51764aSArtem Bityutskiy pos = 0;
3646eb61d58SRichard Weinberger pack_bits(c, &addr, &pos, crc, UBIFS_LPT_CRC_BITS);
3651e51764aSArtem Bityutskiy }
3661e51764aSArtem Bityutskiy
3671e51764aSArtem Bityutskiy /**
3681e51764aSArtem Bityutskiy * ubifs_pack_nnode - pack all the bit fields of a nnode.
3691e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
3701e51764aSArtem Bityutskiy * @buf: buffer into which to pack
3711e51764aSArtem Bityutskiy * @nnode: nnode to pack
3721e51764aSArtem Bityutskiy */
ubifs_pack_nnode(struct ubifs_info * c,void * buf,struct ubifs_nnode * nnode)3731e51764aSArtem Bityutskiy void ubifs_pack_nnode(struct ubifs_info *c, void *buf,
3741e51764aSArtem Bityutskiy struct ubifs_nnode *nnode)
3751e51764aSArtem Bityutskiy {
3761e51764aSArtem Bityutskiy uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
3771e51764aSArtem Bityutskiy int i, pos = 0;
3781e51764aSArtem Bityutskiy uint16_t crc;
3791e51764aSArtem Bityutskiy
3806eb61d58SRichard Weinberger pack_bits(c, &addr, &pos, UBIFS_LPT_NNODE, UBIFS_LPT_TYPE_BITS);
3811e51764aSArtem Bityutskiy if (c->big_lpt)
3826eb61d58SRichard Weinberger pack_bits(c, &addr, &pos, nnode->num, c->pcnt_bits);
3831e51764aSArtem Bityutskiy for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
3841e51764aSArtem Bityutskiy int lnum = nnode->nbranch[i].lnum;
3851e51764aSArtem Bityutskiy
3861e51764aSArtem Bityutskiy if (lnum == 0)
3871e51764aSArtem Bityutskiy lnum = c->lpt_last + 1;
3886eb61d58SRichard Weinberger pack_bits(c, &addr, &pos, lnum - c->lpt_first, c->lpt_lnum_bits);
3896eb61d58SRichard Weinberger pack_bits(c, &addr, &pos, nnode->nbranch[i].offs,
3901e51764aSArtem Bityutskiy c->lpt_offs_bits);
3911e51764aSArtem Bityutskiy }
3921e51764aSArtem Bityutskiy crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
3931e51764aSArtem Bityutskiy c->nnode_sz - UBIFS_LPT_CRC_BYTES);
3941e51764aSArtem Bityutskiy addr = buf;
3951e51764aSArtem Bityutskiy pos = 0;
3966eb61d58SRichard Weinberger pack_bits(c, &addr, &pos, crc, UBIFS_LPT_CRC_BITS);
3971e51764aSArtem Bityutskiy }
3981e51764aSArtem Bityutskiy
3991e51764aSArtem Bityutskiy /**
4001e51764aSArtem Bityutskiy * ubifs_pack_ltab - pack the LPT's own lprops table.
4011e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
4021e51764aSArtem Bityutskiy * @buf: buffer into which to pack
4031e51764aSArtem Bityutskiy * @ltab: LPT's own lprops table to pack
4041e51764aSArtem Bityutskiy */
ubifs_pack_ltab(struct ubifs_info * c,void * buf,struct ubifs_lpt_lprops * ltab)4051e51764aSArtem Bityutskiy void ubifs_pack_ltab(struct ubifs_info *c, void *buf,
4061e51764aSArtem Bityutskiy struct ubifs_lpt_lprops *ltab)
4071e51764aSArtem Bityutskiy {
4081e51764aSArtem Bityutskiy uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
4091e51764aSArtem Bityutskiy int i, pos = 0;
4101e51764aSArtem Bityutskiy uint16_t crc;
4111e51764aSArtem Bityutskiy
4126eb61d58SRichard Weinberger pack_bits(c, &addr, &pos, UBIFS_LPT_LTAB, UBIFS_LPT_TYPE_BITS);
4131e51764aSArtem Bityutskiy for (i = 0; i < c->lpt_lebs; i++) {
4146eb61d58SRichard Weinberger pack_bits(c, &addr, &pos, ltab[i].free, c->lpt_spc_bits);
4156eb61d58SRichard Weinberger pack_bits(c, &addr, &pos, ltab[i].dirty, c->lpt_spc_bits);
4161e51764aSArtem Bityutskiy }
4171e51764aSArtem Bityutskiy crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
4181e51764aSArtem Bityutskiy c->ltab_sz - UBIFS_LPT_CRC_BYTES);
4191e51764aSArtem Bityutskiy addr = buf;
4201e51764aSArtem Bityutskiy pos = 0;
4216eb61d58SRichard Weinberger pack_bits(c, &addr, &pos, crc, UBIFS_LPT_CRC_BITS);
4221e51764aSArtem Bityutskiy }
4231e51764aSArtem Bityutskiy
4241e51764aSArtem Bityutskiy /**
4251e51764aSArtem Bityutskiy * ubifs_pack_lsave - pack the LPT's save table.
4261e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
4271e51764aSArtem Bityutskiy * @buf: buffer into which to pack
4281e51764aSArtem Bityutskiy * @lsave: LPT's save table to pack
4291e51764aSArtem Bityutskiy */
ubifs_pack_lsave(struct ubifs_info * c,void * buf,int * lsave)4301e51764aSArtem Bityutskiy void ubifs_pack_lsave(struct ubifs_info *c, void *buf, int *lsave)
4311e51764aSArtem Bityutskiy {
4321e51764aSArtem Bityutskiy uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
4331e51764aSArtem Bityutskiy int i, pos = 0;
4341e51764aSArtem Bityutskiy uint16_t crc;
4351e51764aSArtem Bityutskiy
4366eb61d58SRichard Weinberger pack_bits(c, &addr, &pos, UBIFS_LPT_LSAVE, UBIFS_LPT_TYPE_BITS);
4371e51764aSArtem Bityutskiy for (i = 0; i < c->lsave_cnt; i++)
4386eb61d58SRichard Weinberger pack_bits(c, &addr, &pos, lsave[i], c->lnum_bits);
4391e51764aSArtem Bityutskiy crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
4401e51764aSArtem Bityutskiy c->lsave_sz - UBIFS_LPT_CRC_BYTES);
4411e51764aSArtem Bityutskiy addr = buf;
4421e51764aSArtem Bityutskiy pos = 0;
4436eb61d58SRichard Weinberger pack_bits(c, &addr, &pos, crc, UBIFS_LPT_CRC_BITS);
4441e51764aSArtem Bityutskiy }
4451e51764aSArtem Bityutskiy
4461e51764aSArtem Bityutskiy /**
4471e51764aSArtem Bityutskiy * ubifs_add_lpt_dirt - add dirty space to LPT LEB properties.
4481e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
4491e51764aSArtem Bityutskiy * @lnum: LEB number to which to add dirty space
4501e51764aSArtem Bityutskiy * @dirty: amount of dirty space to add
4511e51764aSArtem Bityutskiy */
ubifs_add_lpt_dirt(struct ubifs_info * c,int lnum,int dirty)4521e51764aSArtem Bityutskiy void ubifs_add_lpt_dirt(struct ubifs_info *c, int lnum, int dirty)
4531e51764aSArtem Bityutskiy {
4541e51764aSArtem Bityutskiy if (!dirty || !lnum)
4551e51764aSArtem Bityutskiy return;
4561e51764aSArtem Bityutskiy dbg_lp("LEB %d add %d to %d",
4571e51764aSArtem Bityutskiy lnum, dirty, c->ltab[lnum - c->lpt_first].dirty);
4586eb61d58SRichard Weinberger ubifs_assert(c, lnum >= c->lpt_first && lnum <= c->lpt_last);
4591e51764aSArtem Bityutskiy c->ltab[lnum - c->lpt_first].dirty += dirty;
4601e51764aSArtem Bityutskiy }
4611e51764aSArtem Bityutskiy
4621e51764aSArtem Bityutskiy /**
4631e51764aSArtem Bityutskiy * set_ltab - set LPT LEB properties.
4641e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
4651e51764aSArtem Bityutskiy * @lnum: LEB number
4661e51764aSArtem Bityutskiy * @free: amount of free space
4671e51764aSArtem Bityutskiy * @dirty: amount of dirty space
4681e51764aSArtem Bityutskiy */
set_ltab(struct ubifs_info * c,int lnum,int free,int dirty)4691e51764aSArtem Bityutskiy static void set_ltab(struct ubifs_info *c, int lnum, int free, int dirty)
4701e51764aSArtem Bityutskiy {
4711e51764aSArtem Bityutskiy dbg_lp("LEB %d free %d dirty %d to %d %d",
4721e51764aSArtem Bityutskiy lnum, c->ltab[lnum - c->lpt_first].free,
4731e51764aSArtem Bityutskiy c->ltab[lnum - c->lpt_first].dirty, free, dirty);
4746eb61d58SRichard Weinberger ubifs_assert(c, lnum >= c->lpt_first && lnum <= c->lpt_last);
4751e51764aSArtem Bityutskiy c->ltab[lnum - c->lpt_first].free = free;
4761e51764aSArtem Bityutskiy c->ltab[lnum - c->lpt_first].dirty = dirty;
4771e51764aSArtem Bityutskiy }
4781e51764aSArtem Bityutskiy
4791e51764aSArtem Bityutskiy /**
4801e51764aSArtem Bityutskiy * ubifs_add_nnode_dirt - add dirty space to LPT LEB properties.
4811e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
4821e51764aSArtem Bityutskiy * @nnode: nnode for which to add dirt
4831e51764aSArtem Bityutskiy */
ubifs_add_nnode_dirt(struct ubifs_info * c,struct ubifs_nnode * nnode)4841e51764aSArtem Bityutskiy void ubifs_add_nnode_dirt(struct ubifs_info *c, struct ubifs_nnode *nnode)
4851e51764aSArtem Bityutskiy {
4861e51764aSArtem Bityutskiy struct ubifs_nnode *np = nnode->parent;
4871e51764aSArtem Bityutskiy
4881e51764aSArtem Bityutskiy if (np)
4891e51764aSArtem Bityutskiy ubifs_add_lpt_dirt(c, np->nbranch[nnode->iip].lnum,
4901e51764aSArtem Bityutskiy c->nnode_sz);
4911e51764aSArtem Bityutskiy else {
4921e51764aSArtem Bityutskiy ubifs_add_lpt_dirt(c, c->lpt_lnum, c->nnode_sz);
4931e51764aSArtem Bityutskiy if (!(c->lpt_drty_flgs & LTAB_DIRTY)) {
4941e51764aSArtem Bityutskiy c->lpt_drty_flgs |= LTAB_DIRTY;
4951e51764aSArtem Bityutskiy ubifs_add_lpt_dirt(c, c->ltab_lnum, c->ltab_sz);
4961e51764aSArtem Bityutskiy }
4971e51764aSArtem Bityutskiy }
4981e51764aSArtem Bityutskiy }
4991e51764aSArtem Bityutskiy
5001e51764aSArtem Bityutskiy /**
5011e51764aSArtem Bityutskiy * add_pnode_dirt - add dirty space to LPT LEB properties.
5021e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
5031e51764aSArtem Bityutskiy * @pnode: pnode for which to add dirt
5041e51764aSArtem Bityutskiy */
add_pnode_dirt(struct ubifs_info * c,struct ubifs_pnode * pnode)5051e51764aSArtem Bityutskiy static void add_pnode_dirt(struct ubifs_info *c, struct ubifs_pnode *pnode)
5061e51764aSArtem Bityutskiy {
5071e51764aSArtem Bityutskiy ubifs_add_lpt_dirt(c, pnode->parent->nbranch[pnode->iip].lnum,
5081e51764aSArtem Bityutskiy c->pnode_sz);
5091e51764aSArtem Bityutskiy }
5101e51764aSArtem Bityutskiy
5111e51764aSArtem Bityutskiy /**
5121e51764aSArtem Bityutskiy * calc_nnode_num - calculate nnode number.
5131e51764aSArtem Bityutskiy * @row: the row in the tree (root is zero)
5141e51764aSArtem Bityutskiy * @col: the column in the row (leftmost is zero)
5151e51764aSArtem Bityutskiy *
5161e51764aSArtem Bityutskiy * The nnode number is a number that uniquely identifies a nnode and can be used
5171e51764aSArtem Bityutskiy * easily to traverse the tree from the root to that nnode.
5181e51764aSArtem Bityutskiy *
5191e51764aSArtem Bityutskiy * This function calculates and returns the nnode number for the nnode at @row
5201e51764aSArtem Bityutskiy * and @col.
5211e51764aSArtem Bityutskiy */
calc_nnode_num(int row,int col)5221e51764aSArtem Bityutskiy static int calc_nnode_num(int row, int col)
5231e51764aSArtem Bityutskiy {
5241e51764aSArtem Bityutskiy int num, bits;
5251e51764aSArtem Bityutskiy
5261e51764aSArtem Bityutskiy num = 1;
5271e51764aSArtem Bityutskiy while (row--) {
5281e51764aSArtem Bityutskiy bits = (col & (UBIFS_LPT_FANOUT - 1));
5291e51764aSArtem Bityutskiy col >>= UBIFS_LPT_FANOUT_SHIFT;
5301e51764aSArtem Bityutskiy num <<= UBIFS_LPT_FANOUT_SHIFT;
5311e51764aSArtem Bityutskiy num |= bits;
5321e51764aSArtem Bityutskiy }
5331e51764aSArtem Bityutskiy return num;
5341e51764aSArtem Bityutskiy }
5351e51764aSArtem Bityutskiy
5361e51764aSArtem Bityutskiy /**
5371e51764aSArtem Bityutskiy * calc_nnode_num_from_parent - calculate nnode number.
5381e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
5391e51764aSArtem Bityutskiy * @parent: parent nnode
5401e51764aSArtem Bityutskiy * @iip: index in parent
5411e51764aSArtem Bityutskiy *
5421e51764aSArtem Bityutskiy * The nnode number is a number that uniquely identifies a nnode and can be used
5431e51764aSArtem Bityutskiy * easily to traverse the tree from the root to that nnode.
5441e51764aSArtem Bityutskiy *
5451e51764aSArtem Bityutskiy * This function calculates and returns the nnode number based on the parent's
5461e51764aSArtem Bityutskiy * nnode number and the index in parent.
5471e51764aSArtem Bityutskiy */
calc_nnode_num_from_parent(const struct ubifs_info * c,struct ubifs_nnode * parent,int iip)5482ba5f7aeSArtem Bityutskiy static int calc_nnode_num_from_parent(const struct ubifs_info *c,
5491e51764aSArtem Bityutskiy struct ubifs_nnode *parent, int iip)
5501e51764aSArtem Bityutskiy {
5511e51764aSArtem Bityutskiy int num, shft;
5521e51764aSArtem Bityutskiy
5531e51764aSArtem Bityutskiy if (!parent)
5541e51764aSArtem Bityutskiy return 1;
5551e51764aSArtem Bityutskiy shft = (c->lpt_hght - parent->level) * UBIFS_LPT_FANOUT_SHIFT;
5561e51764aSArtem Bityutskiy num = parent->num ^ (1 << shft);
5571e51764aSArtem Bityutskiy num |= (UBIFS_LPT_FANOUT + iip) << shft;
5581e51764aSArtem Bityutskiy return num;
5591e51764aSArtem Bityutskiy }
5601e51764aSArtem Bityutskiy
5611e51764aSArtem Bityutskiy /**
5621e51764aSArtem Bityutskiy * calc_pnode_num_from_parent - calculate pnode number.
5631e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
5641e51764aSArtem Bityutskiy * @parent: parent nnode
5651e51764aSArtem Bityutskiy * @iip: index in parent
5661e51764aSArtem Bityutskiy *
5671e51764aSArtem Bityutskiy * The pnode number is a number that uniquely identifies a pnode and can be used
5681e51764aSArtem Bityutskiy * easily to traverse the tree from the root to that pnode.
5691e51764aSArtem Bityutskiy *
5701e51764aSArtem Bityutskiy * This function calculates and returns the pnode number based on the parent's
5711e51764aSArtem Bityutskiy * nnode number and the index in parent.
5721e51764aSArtem Bityutskiy */
calc_pnode_num_from_parent(const struct ubifs_info * c,struct ubifs_nnode * parent,int iip)5732ba5f7aeSArtem Bityutskiy static int calc_pnode_num_from_parent(const struct ubifs_info *c,
5741e51764aSArtem Bityutskiy struct ubifs_nnode *parent, int iip)
5751e51764aSArtem Bityutskiy {
5761e51764aSArtem Bityutskiy int i, n = c->lpt_hght - 1, pnum = parent->num, num = 0;
5771e51764aSArtem Bityutskiy
5781e51764aSArtem Bityutskiy for (i = 0; i < n; i++) {
5791e51764aSArtem Bityutskiy num <<= UBIFS_LPT_FANOUT_SHIFT;
5801e51764aSArtem Bityutskiy num |= pnum & (UBIFS_LPT_FANOUT - 1);
5811e51764aSArtem Bityutskiy pnum >>= UBIFS_LPT_FANOUT_SHIFT;
5821e51764aSArtem Bityutskiy }
5831e51764aSArtem Bityutskiy num <<= UBIFS_LPT_FANOUT_SHIFT;
5841e51764aSArtem Bityutskiy num |= iip;
5851e51764aSArtem Bityutskiy return num;
5861e51764aSArtem Bityutskiy }
5871e51764aSArtem Bityutskiy
5881e51764aSArtem Bityutskiy /**
5891e51764aSArtem Bityutskiy * ubifs_create_dflt_lpt - create default LPT.
5901e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
5911e51764aSArtem Bityutskiy * @main_lebs: number of main area LEBs is passed and returned here
5921e51764aSArtem Bityutskiy * @lpt_first: LEB number of first LPT LEB
5931e51764aSArtem Bityutskiy * @lpt_lebs: number of LEBs for LPT is passed and returned here
5941e51764aSArtem Bityutskiy * @big_lpt: use big LPT model is passed and returned here
595b5b1f083SSascha Hauer * @hash: hash of the LPT is returned here
5961e51764aSArtem Bityutskiy *
5971e51764aSArtem Bityutskiy * This function returns %0 on success and a negative error code on failure.
5981e51764aSArtem Bityutskiy */
ubifs_create_dflt_lpt(struct ubifs_info * c,int * main_lebs,int lpt_first,int * lpt_lebs,int * big_lpt,u8 * hash)5991e51764aSArtem Bityutskiy int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
600b5b1f083SSascha Hauer int *lpt_lebs, int *big_lpt, u8 *hash)
6011e51764aSArtem Bityutskiy {
6021e51764aSArtem Bityutskiy int lnum, err = 0, node_sz, iopos, i, j, cnt, len, alen, row;
6031e51764aSArtem Bityutskiy int blnum, boffs, bsz, bcnt;
6041e51764aSArtem Bityutskiy struct ubifs_pnode *pnode = NULL;
6051e51764aSArtem Bityutskiy struct ubifs_nnode *nnode = NULL;
6061e51764aSArtem Bityutskiy void *buf = NULL, *p;
6071e51764aSArtem Bityutskiy struct ubifs_lpt_lprops *ltab = NULL;
6081e51764aSArtem Bityutskiy int *lsave = NULL;
609b5b1f083SSascha Hauer struct shash_desc *desc;
6101e51764aSArtem Bityutskiy
6111e51764aSArtem Bityutskiy err = calc_dflt_lpt_geom(c, main_lebs, big_lpt);
6121e51764aSArtem Bityutskiy if (err)
6131e51764aSArtem Bityutskiy return err;
6141e51764aSArtem Bityutskiy *lpt_lebs = c->lpt_lebs;
6151e51764aSArtem Bityutskiy
6161e51764aSArtem Bityutskiy /* Needed by 'ubifs_pack_nnode()' and 'set_ltab()' */
6171e51764aSArtem Bityutskiy c->lpt_first = lpt_first;
6181e51764aSArtem Bityutskiy /* Needed by 'set_ltab()' */
6191e51764aSArtem Bityutskiy c->lpt_last = lpt_first + c->lpt_lebs - 1;
6201e51764aSArtem Bityutskiy /* Needed by 'ubifs_pack_lsave()' */
6211e51764aSArtem Bityutskiy c->main_first = c->leb_cnt - *main_lebs;
6221e51764aSArtem Bityutskiy
623b5b1f083SSascha Hauer desc = ubifs_hash_get_desc(c);
624b5b1f083SSascha Hauer if (IS_ERR(desc))
625b5b1f083SSascha Hauer return PTR_ERR(desc);
626b5b1f083SSascha Hauer
6276da2ec56SKees Cook lsave = kmalloc_array(c->lsave_cnt, sizeof(int), GFP_KERNEL);
6281e51764aSArtem Bityutskiy pnode = kzalloc(sizeof(struct ubifs_pnode), GFP_KERNEL);
6291e51764aSArtem Bityutskiy nnode = kzalloc(sizeof(struct ubifs_nnode), GFP_KERNEL);
6301e51764aSArtem Bityutskiy buf = vmalloc(c->leb_size);
63142bc47b3SKees Cook ltab = vmalloc(array_size(sizeof(struct ubifs_lpt_lprops),
63242bc47b3SKees Cook c->lpt_lebs));
6331e51764aSArtem Bityutskiy if (!pnode || !nnode || !buf || !ltab || !lsave) {
6341e51764aSArtem Bityutskiy err = -ENOMEM;
6351e51764aSArtem Bityutskiy goto out;
6361e51764aSArtem Bityutskiy }
6371e51764aSArtem Bityutskiy
6386eb61d58SRichard Weinberger ubifs_assert(c, !c->ltab);
6391e51764aSArtem Bityutskiy c->ltab = ltab; /* Needed by set_ltab */
6401e51764aSArtem Bityutskiy
6411e51764aSArtem Bityutskiy /* Initialize LPT's own lprops */
6421e51764aSArtem Bityutskiy for (i = 0; i < c->lpt_lebs; i++) {
6431e51764aSArtem Bityutskiy ltab[i].free = c->leb_size;
6441e51764aSArtem Bityutskiy ltab[i].dirty = 0;
6451e51764aSArtem Bityutskiy ltab[i].tgc = 0;
6461e51764aSArtem Bityutskiy ltab[i].cmt = 0;
6471e51764aSArtem Bityutskiy }
6481e51764aSArtem Bityutskiy
6491e51764aSArtem Bityutskiy lnum = lpt_first;
6501e51764aSArtem Bityutskiy p = buf;
6511e51764aSArtem Bityutskiy /* Number of leaf nodes (pnodes) */
6521e51764aSArtem Bityutskiy cnt = c->pnode_cnt;
6531e51764aSArtem Bityutskiy
6541e51764aSArtem Bityutskiy /*
6551e51764aSArtem Bityutskiy * The first pnode contains the LEB properties for the LEBs that contain
6561e51764aSArtem Bityutskiy * the root inode node and the root index node of the index tree.
6571e51764aSArtem Bityutskiy */
6581e51764aSArtem Bityutskiy node_sz = ALIGN(ubifs_idx_node_sz(c, 1), 8);
6591e51764aSArtem Bityutskiy iopos = ALIGN(node_sz, c->min_io_size);
6601e51764aSArtem Bityutskiy pnode->lprops[0].free = c->leb_size - iopos;
6611e51764aSArtem Bityutskiy pnode->lprops[0].dirty = iopos - node_sz;
6621e51764aSArtem Bityutskiy pnode->lprops[0].flags = LPROPS_INDEX;
6631e51764aSArtem Bityutskiy
6641e51764aSArtem Bityutskiy node_sz = UBIFS_INO_NODE_SZ;
6651e51764aSArtem Bityutskiy iopos = ALIGN(node_sz, c->min_io_size);
6661e51764aSArtem Bityutskiy pnode->lprops[1].free = c->leb_size - iopos;
6671e51764aSArtem Bityutskiy pnode->lprops[1].dirty = iopos - node_sz;
6681e51764aSArtem Bityutskiy
6691e51764aSArtem Bityutskiy for (i = 2; i < UBIFS_LPT_FANOUT; i++)
6701e51764aSArtem Bityutskiy pnode->lprops[i].free = c->leb_size;
6711e51764aSArtem Bityutskiy
6721e51764aSArtem Bityutskiy /* Add first pnode */
6731e51764aSArtem Bityutskiy ubifs_pack_pnode(c, p, pnode);
674b5b1f083SSascha Hauer err = ubifs_shash_update(c, desc, p, c->pnode_sz);
675b5b1f083SSascha Hauer if (err)
676b5b1f083SSascha Hauer goto out;
677b5b1f083SSascha Hauer
6781e51764aSArtem Bityutskiy p += c->pnode_sz;
6791e51764aSArtem Bityutskiy len = c->pnode_sz;
6801e51764aSArtem Bityutskiy pnode->num += 1;
6811e51764aSArtem Bityutskiy
6821e51764aSArtem Bityutskiy /* Reset pnode values for remaining pnodes */
6831e51764aSArtem Bityutskiy pnode->lprops[0].free = c->leb_size;
6841e51764aSArtem Bityutskiy pnode->lprops[0].dirty = 0;
6851e51764aSArtem Bityutskiy pnode->lprops[0].flags = 0;
6861e51764aSArtem Bityutskiy
6871e51764aSArtem Bityutskiy pnode->lprops[1].free = c->leb_size;
6881e51764aSArtem Bityutskiy pnode->lprops[1].dirty = 0;
6891e51764aSArtem Bityutskiy
6901e51764aSArtem Bityutskiy /*
6911e51764aSArtem Bityutskiy * To calculate the internal node branches, we keep information about
6921e51764aSArtem Bityutskiy * the level below.
6931e51764aSArtem Bityutskiy */
6941e51764aSArtem Bityutskiy blnum = lnum; /* LEB number of level below */
6951e51764aSArtem Bityutskiy boffs = 0; /* Offset of level below */
6961e51764aSArtem Bityutskiy bcnt = cnt; /* Number of nodes in level below */
6971e51764aSArtem Bityutskiy bsz = c->pnode_sz; /* Size of nodes in level below */
6981e51764aSArtem Bityutskiy
6991e51764aSArtem Bityutskiy /* Add all remaining pnodes */
7001e51764aSArtem Bityutskiy for (i = 1; i < cnt; i++) {
7011e51764aSArtem Bityutskiy if (len + c->pnode_sz > c->leb_size) {
7021e51764aSArtem Bityutskiy alen = ALIGN(len, c->min_io_size);
7031e51764aSArtem Bityutskiy set_ltab(c, lnum, c->leb_size - alen, alen - len);
7041e51764aSArtem Bityutskiy memset(p, 0xff, alen - len);
705b36a261eSRichard Weinberger err = ubifs_leb_change(c, lnum++, buf, alen);
7061e51764aSArtem Bityutskiy if (err)
7071e51764aSArtem Bityutskiy goto out;
7081e51764aSArtem Bityutskiy p = buf;
7091e51764aSArtem Bityutskiy len = 0;
7101e51764aSArtem Bityutskiy }
7111e51764aSArtem Bityutskiy ubifs_pack_pnode(c, p, pnode);
712b5b1f083SSascha Hauer err = ubifs_shash_update(c, desc, p, c->pnode_sz);
713b5b1f083SSascha Hauer if (err)
714b5b1f083SSascha Hauer goto out;
715b5b1f083SSascha Hauer
7161e51764aSArtem Bityutskiy p += c->pnode_sz;
7171e51764aSArtem Bityutskiy len += c->pnode_sz;
7181e51764aSArtem Bityutskiy /*
7191e51764aSArtem Bityutskiy * pnodes are simply numbered left to right starting at zero,
7201e51764aSArtem Bityutskiy * which means the pnode number can be used easily to traverse
7211e51764aSArtem Bityutskiy * down the tree to the corresponding pnode.
7221e51764aSArtem Bityutskiy */
7231e51764aSArtem Bityutskiy pnode->num += 1;
7241e51764aSArtem Bityutskiy }
7251e51764aSArtem Bityutskiy
7261e51764aSArtem Bityutskiy row = 0;
7271e51764aSArtem Bityutskiy for (i = UBIFS_LPT_FANOUT; cnt > i; i <<= UBIFS_LPT_FANOUT_SHIFT)
7281e51764aSArtem Bityutskiy row += 1;
7291e51764aSArtem Bityutskiy /* Add all nnodes, one level at a time */
7301e51764aSArtem Bityutskiy while (1) {
7311e51764aSArtem Bityutskiy /* Number of internal nodes (nnodes) at next level */
7321e51764aSArtem Bityutskiy cnt = DIV_ROUND_UP(cnt, UBIFS_LPT_FANOUT);
7331e51764aSArtem Bityutskiy for (i = 0; i < cnt; i++) {
7341e51764aSArtem Bityutskiy if (len + c->nnode_sz > c->leb_size) {
7351e51764aSArtem Bityutskiy alen = ALIGN(len, c->min_io_size);
7361e51764aSArtem Bityutskiy set_ltab(c, lnum, c->leb_size - alen,
7371e51764aSArtem Bityutskiy alen - len);
7381e51764aSArtem Bityutskiy memset(p, 0xff, alen - len);
739b36a261eSRichard Weinberger err = ubifs_leb_change(c, lnum++, buf, alen);
7401e51764aSArtem Bityutskiy if (err)
7411e51764aSArtem Bityutskiy goto out;
7421e51764aSArtem Bityutskiy p = buf;
7431e51764aSArtem Bityutskiy len = 0;
7441e51764aSArtem Bityutskiy }
7451e51764aSArtem Bityutskiy /* Only 1 nnode at this level, so it is the root */
7461e51764aSArtem Bityutskiy if (cnt == 1) {
7471e51764aSArtem Bityutskiy c->lpt_lnum = lnum;
7481e51764aSArtem Bityutskiy c->lpt_offs = len;
7491e51764aSArtem Bityutskiy }
7501e51764aSArtem Bityutskiy /* Set branches to the level below */
7511e51764aSArtem Bityutskiy for (j = 0; j < UBIFS_LPT_FANOUT; j++) {
7521e51764aSArtem Bityutskiy if (bcnt) {
7531e51764aSArtem Bityutskiy if (boffs + bsz > c->leb_size) {
7541e51764aSArtem Bityutskiy blnum += 1;
7551e51764aSArtem Bityutskiy boffs = 0;
7561e51764aSArtem Bityutskiy }
7571e51764aSArtem Bityutskiy nnode->nbranch[j].lnum = blnum;
7581e51764aSArtem Bityutskiy nnode->nbranch[j].offs = boffs;
7591e51764aSArtem Bityutskiy boffs += bsz;
7601e51764aSArtem Bityutskiy bcnt--;
7611e51764aSArtem Bityutskiy } else {
7621e51764aSArtem Bityutskiy nnode->nbranch[j].lnum = 0;
7631e51764aSArtem Bityutskiy nnode->nbranch[j].offs = 0;
7641e51764aSArtem Bityutskiy }
7651e51764aSArtem Bityutskiy }
7661e51764aSArtem Bityutskiy nnode->num = calc_nnode_num(row, i);
7671e51764aSArtem Bityutskiy ubifs_pack_nnode(c, p, nnode);
7681e51764aSArtem Bityutskiy p += c->nnode_sz;
7691e51764aSArtem Bityutskiy len += c->nnode_sz;
7701e51764aSArtem Bityutskiy }
7711e51764aSArtem Bityutskiy /* Only 1 nnode at this level, so it is the root */
7721e51764aSArtem Bityutskiy if (cnt == 1)
7731e51764aSArtem Bityutskiy break;
7741e51764aSArtem Bityutskiy /* Update the information about the level below */
7751e51764aSArtem Bityutskiy bcnt = cnt;
7761e51764aSArtem Bityutskiy bsz = c->nnode_sz;
7771e51764aSArtem Bityutskiy row -= 1;
7781e51764aSArtem Bityutskiy }
7791e51764aSArtem Bityutskiy
7801e51764aSArtem Bityutskiy if (*big_lpt) {
7811e51764aSArtem Bityutskiy /* Need to add LPT's save table */
7821e51764aSArtem Bityutskiy if (len + c->lsave_sz > c->leb_size) {
7831e51764aSArtem Bityutskiy alen = ALIGN(len, c->min_io_size);
7841e51764aSArtem Bityutskiy set_ltab(c, lnum, c->leb_size - alen, alen - len);
7851e51764aSArtem Bityutskiy memset(p, 0xff, alen - len);
786b36a261eSRichard Weinberger err = ubifs_leb_change(c, lnum++, buf, alen);
7871e51764aSArtem Bityutskiy if (err)
7881e51764aSArtem Bityutskiy goto out;
7891e51764aSArtem Bityutskiy p = buf;
7901e51764aSArtem Bityutskiy len = 0;
7911e51764aSArtem Bityutskiy }
7921e51764aSArtem Bityutskiy
7931e51764aSArtem Bityutskiy c->lsave_lnum = lnum;
7941e51764aSArtem Bityutskiy c->lsave_offs = len;
7951e51764aSArtem Bityutskiy
7961e51764aSArtem Bityutskiy for (i = 0; i < c->lsave_cnt && i < *main_lebs; i++)
7971e51764aSArtem Bityutskiy lsave[i] = c->main_first + i;
7981e51764aSArtem Bityutskiy for (; i < c->lsave_cnt; i++)
7991e51764aSArtem Bityutskiy lsave[i] = c->main_first;
8001e51764aSArtem Bityutskiy
8011e51764aSArtem Bityutskiy ubifs_pack_lsave(c, p, lsave);
8021e51764aSArtem Bityutskiy p += c->lsave_sz;
8031e51764aSArtem Bityutskiy len += c->lsave_sz;
8041e51764aSArtem Bityutskiy }
8051e51764aSArtem Bityutskiy
8061e51764aSArtem Bityutskiy /* Need to add LPT's own LEB properties table */
8071e51764aSArtem Bityutskiy if (len + c->ltab_sz > c->leb_size) {
8081e51764aSArtem Bityutskiy alen = ALIGN(len, c->min_io_size);
8091e51764aSArtem Bityutskiy set_ltab(c, lnum, c->leb_size - alen, alen - len);
8101e51764aSArtem Bityutskiy memset(p, 0xff, alen - len);
811b36a261eSRichard Weinberger err = ubifs_leb_change(c, lnum++, buf, alen);
8121e51764aSArtem Bityutskiy if (err)
8131e51764aSArtem Bityutskiy goto out;
8141e51764aSArtem Bityutskiy p = buf;
8151e51764aSArtem Bityutskiy len = 0;
8161e51764aSArtem Bityutskiy }
8171e51764aSArtem Bityutskiy
8181e51764aSArtem Bityutskiy c->ltab_lnum = lnum;
8191e51764aSArtem Bityutskiy c->ltab_offs = len;
8201e51764aSArtem Bityutskiy
8211e51764aSArtem Bityutskiy /* Update ltab before packing it */
8221e51764aSArtem Bityutskiy len += c->ltab_sz;
8231e51764aSArtem Bityutskiy alen = ALIGN(len, c->min_io_size);
8241e51764aSArtem Bityutskiy set_ltab(c, lnum, c->leb_size - alen, alen - len);
8251e51764aSArtem Bityutskiy
8261e51764aSArtem Bityutskiy ubifs_pack_ltab(c, p, ltab);
8271e51764aSArtem Bityutskiy p += c->ltab_sz;
8281e51764aSArtem Bityutskiy
8291e51764aSArtem Bityutskiy /* Write remaining buffer */
8301e51764aSArtem Bityutskiy memset(p, 0xff, alen - len);
831b36a261eSRichard Weinberger err = ubifs_leb_change(c, lnum, buf, alen);
8321e51764aSArtem Bityutskiy if (err)
8331e51764aSArtem Bityutskiy goto out;
8341e51764aSArtem Bityutskiy
835b5b1f083SSascha Hauer err = ubifs_shash_final(c, desc, hash);
836b5b1f083SSascha Hauer if (err)
837b5b1f083SSascha Hauer goto out;
838b5b1f083SSascha Hauer
8391e51764aSArtem Bityutskiy c->nhead_lnum = lnum;
8401e51764aSArtem Bityutskiy c->nhead_offs = ALIGN(len, c->min_io_size);
8411e51764aSArtem Bityutskiy
8421e51764aSArtem Bityutskiy dbg_lp("space_bits %d", c->space_bits);
8431e51764aSArtem Bityutskiy dbg_lp("lpt_lnum_bits %d", c->lpt_lnum_bits);
8441e51764aSArtem Bityutskiy dbg_lp("lpt_offs_bits %d", c->lpt_offs_bits);
8451e51764aSArtem Bityutskiy dbg_lp("lpt_spc_bits %d", c->lpt_spc_bits);
8461e51764aSArtem Bityutskiy dbg_lp("pcnt_bits %d", c->pcnt_bits);
8471e51764aSArtem Bityutskiy dbg_lp("lnum_bits %d", c->lnum_bits);
8481e51764aSArtem Bityutskiy dbg_lp("pnode_sz %d", c->pnode_sz);
8491e51764aSArtem Bityutskiy dbg_lp("nnode_sz %d", c->nnode_sz);
8501e51764aSArtem Bityutskiy dbg_lp("ltab_sz %d", c->ltab_sz);
8511e51764aSArtem Bityutskiy dbg_lp("lsave_sz %d", c->lsave_sz);
8521e51764aSArtem Bityutskiy dbg_lp("lsave_cnt %d", c->lsave_cnt);
8531e51764aSArtem Bityutskiy dbg_lp("lpt_hght %d", c->lpt_hght);
854*f2124007SChengsong Ke dbg_lp("big_lpt %u", c->big_lpt);
8551e51764aSArtem Bityutskiy dbg_lp("LPT root is at %d:%d", c->lpt_lnum, c->lpt_offs);
8561e51764aSArtem Bityutskiy dbg_lp("LPT head is at %d:%d", c->nhead_lnum, c->nhead_offs);
8571e51764aSArtem Bityutskiy dbg_lp("LPT ltab is at %d:%d", c->ltab_lnum, c->ltab_offs);
8581e51764aSArtem Bityutskiy if (c->big_lpt)
8591e51764aSArtem Bityutskiy dbg_lp("LPT lsave is at %d:%d", c->lsave_lnum, c->lsave_offs);
8601e51764aSArtem Bityutskiy out:
8611e51764aSArtem Bityutskiy c->ltab = NULL;
862b5b1f083SSascha Hauer kfree(desc);
8631e51764aSArtem Bityutskiy kfree(lsave);
8641e51764aSArtem Bityutskiy vfree(ltab);
8651e51764aSArtem Bityutskiy vfree(buf);
8661e51764aSArtem Bityutskiy kfree(nnode);
8671e51764aSArtem Bityutskiy kfree(pnode);
8681e51764aSArtem Bityutskiy return err;
8691e51764aSArtem Bityutskiy }
8701e51764aSArtem Bityutskiy
8711e51764aSArtem Bityutskiy /**
8721e51764aSArtem Bityutskiy * update_cats - add LEB properties of a pnode to LEB category lists and heaps.
8731e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
8741e51764aSArtem Bityutskiy * @pnode: pnode
8751e51764aSArtem Bityutskiy *
8761e51764aSArtem Bityutskiy * When a pnode is loaded into memory, the LEB properties it contains are added,
8771e51764aSArtem Bityutskiy * by this function, to the LEB category lists and heaps.
8781e51764aSArtem Bityutskiy */
update_cats(struct ubifs_info * c,struct ubifs_pnode * pnode)8791e51764aSArtem Bityutskiy static void update_cats(struct ubifs_info *c, struct ubifs_pnode *pnode)
8801e51764aSArtem Bityutskiy {
8811e51764aSArtem Bityutskiy int i;
8821e51764aSArtem Bityutskiy
8831e51764aSArtem Bityutskiy for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
8841e51764aSArtem Bityutskiy int cat = pnode->lprops[i].flags & LPROPS_CAT_MASK;
8851e51764aSArtem Bityutskiy int lnum = pnode->lprops[i].lnum;
8861e51764aSArtem Bityutskiy
8871e51764aSArtem Bityutskiy if (!lnum)
8881e51764aSArtem Bityutskiy return;
8891e51764aSArtem Bityutskiy ubifs_add_to_cat(c, &pnode->lprops[i], cat);
8901e51764aSArtem Bityutskiy }
8911e51764aSArtem Bityutskiy }
8921e51764aSArtem Bityutskiy
8931e51764aSArtem Bityutskiy /**
8941e51764aSArtem Bityutskiy * replace_cats - add LEB properties of a pnode to LEB category lists and heaps.
8951e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
8961e51764aSArtem Bityutskiy * @old_pnode: pnode copied
8971e51764aSArtem Bityutskiy * @new_pnode: pnode copy
8981e51764aSArtem Bityutskiy *
8991e51764aSArtem Bityutskiy * During commit it is sometimes necessary to copy a pnode
9001e51764aSArtem Bityutskiy * (see dirty_cow_pnode). When that happens, references in
9011e51764aSArtem Bityutskiy * category lists and heaps must be replaced. This function does that.
9021e51764aSArtem Bityutskiy */
replace_cats(struct ubifs_info * c,struct ubifs_pnode * old_pnode,struct ubifs_pnode * new_pnode)9031e51764aSArtem Bityutskiy static void replace_cats(struct ubifs_info *c, struct ubifs_pnode *old_pnode,
9041e51764aSArtem Bityutskiy struct ubifs_pnode *new_pnode)
9051e51764aSArtem Bityutskiy {
9061e51764aSArtem Bityutskiy int i;
9071e51764aSArtem Bityutskiy
9081e51764aSArtem Bityutskiy for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
9091e51764aSArtem Bityutskiy if (!new_pnode->lprops[i].lnum)
9101e51764aSArtem Bityutskiy return;
9111e51764aSArtem Bityutskiy ubifs_replace_cat(c, &old_pnode->lprops[i],
9121e51764aSArtem Bityutskiy &new_pnode->lprops[i]);
9131e51764aSArtem Bityutskiy }
9141e51764aSArtem Bityutskiy }
9151e51764aSArtem Bityutskiy
9161e51764aSArtem Bityutskiy /**
9171e51764aSArtem Bityutskiy * check_lpt_crc - check LPT node crc is correct.
9181e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
9191e51764aSArtem Bityutskiy * @buf: buffer containing node
9201e51764aSArtem Bityutskiy * @len: length of node
9211e51764aSArtem Bityutskiy *
9221e51764aSArtem Bityutskiy * This function returns %0 on success and a negative error code on failure.
9231e51764aSArtem Bityutskiy */
check_lpt_crc(const struct ubifs_info * c,void * buf,int len)924235c362bSSheng Yong static int check_lpt_crc(const struct ubifs_info *c, void *buf, int len)
9251e51764aSArtem Bityutskiy {
9261e51764aSArtem Bityutskiy int pos = 0;
9271e51764aSArtem Bityutskiy uint8_t *addr = buf;
9281e51764aSArtem Bityutskiy uint16_t crc, calc_crc;
9291e51764aSArtem Bityutskiy
9306eb61d58SRichard Weinberger crc = ubifs_unpack_bits(c, &addr, &pos, UBIFS_LPT_CRC_BITS);
9311e51764aSArtem Bityutskiy calc_crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
9321e51764aSArtem Bityutskiy len - UBIFS_LPT_CRC_BYTES);
9331e51764aSArtem Bityutskiy if (crc != calc_crc) {
934235c362bSSheng Yong ubifs_err(c, "invalid crc in LPT node: crc %hx calc %hx",
935235c362bSSheng Yong crc, calc_crc);
9367c46d0aeSArtem Bityutskiy dump_stack();
9371e51764aSArtem Bityutskiy return -EINVAL;
9381e51764aSArtem Bityutskiy }
9391e51764aSArtem Bityutskiy return 0;
9401e51764aSArtem Bityutskiy }
9411e51764aSArtem Bityutskiy
9421e51764aSArtem Bityutskiy /**
9431e51764aSArtem Bityutskiy * check_lpt_type - check LPT node type is correct.
9441e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
9451e51764aSArtem Bityutskiy * @addr: address of type bit field is passed and returned updated here
9461e51764aSArtem Bityutskiy * @pos: position of type bit field is passed and returned updated here
9471e51764aSArtem Bityutskiy * @type: expected type
9481e51764aSArtem Bityutskiy *
9491e51764aSArtem Bityutskiy * This function returns %0 on success and a negative error code on failure.
9501e51764aSArtem Bityutskiy */
check_lpt_type(const struct ubifs_info * c,uint8_t ** addr,int * pos,int type)951235c362bSSheng Yong static int check_lpt_type(const struct ubifs_info *c, uint8_t **addr,
952235c362bSSheng Yong int *pos, int type)
9531e51764aSArtem Bityutskiy {
9541e51764aSArtem Bityutskiy int node_type;
9551e51764aSArtem Bityutskiy
9566eb61d58SRichard Weinberger node_type = ubifs_unpack_bits(c, addr, pos, UBIFS_LPT_TYPE_BITS);
9571e51764aSArtem Bityutskiy if (node_type != type) {
958235c362bSSheng Yong ubifs_err(c, "invalid type (%d) in LPT node type %d",
959235c362bSSheng Yong node_type, type);
9607c46d0aeSArtem Bityutskiy dump_stack();
9611e51764aSArtem Bityutskiy return -EINVAL;
9621e51764aSArtem Bityutskiy }
9631e51764aSArtem Bityutskiy return 0;
9641e51764aSArtem Bityutskiy }
9651e51764aSArtem Bityutskiy
9661e51764aSArtem Bityutskiy /**
9671e51764aSArtem Bityutskiy * unpack_pnode - unpack a pnode.
9681e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
9691e51764aSArtem Bityutskiy * @buf: buffer containing packed pnode to unpack
9701e51764aSArtem Bityutskiy * @pnode: pnode structure to fill
9711e51764aSArtem Bityutskiy *
9721e51764aSArtem Bityutskiy * This function returns %0 on success and a negative error code on failure.
9731e51764aSArtem Bityutskiy */
unpack_pnode(const struct ubifs_info * c,void * buf,struct ubifs_pnode * pnode)9742ba5f7aeSArtem Bityutskiy static int unpack_pnode(const struct ubifs_info *c, void *buf,
9751e51764aSArtem Bityutskiy struct ubifs_pnode *pnode)
9761e51764aSArtem Bityutskiy {
9771e51764aSArtem Bityutskiy uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
9781e51764aSArtem Bityutskiy int i, pos = 0, err;
9791e51764aSArtem Bityutskiy
980235c362bSSheng Yong err = check_lpt_type(c, &addr, &pos, UBIFS_LPT_PNODE);
9811e51764aSArtem Bityutskiy if (err)
9821e51764aSArtem Bityutskiy return err;
9831e51764aSArtem Bityutskiy if (c->big_lpt)
9846eb61d58SRichard Weinberger pnode->num = ubifs_unpack_bits(c, &addr, &pos, c->pcnt_bits);
9851e51764aSArtem Bityutskiy for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
9861e51764aSArtem Bityutskiy struct ubifs_lprops * const lprops = &pnode->lprops[i];
9871e51764aSArtem Bityutskiy
9886eb61d58SRichard Weinberger lprops->free = ubifs_unpack_bits(c, &addr, &pos, c->space_bits);
9891e51764aSArtem Bityutskiy lprops->free <<= 3;
9906eb61d58SRichard Weinberger lprops->dirty = ubifs_unpack_bits(c, &addr, &pos, c->space_bits);
9911e51764aSArtem Bityutskiy lprops->dirty <<= 3;
9921e51764aSArtem Bityutskiy
9936eb61d58SRichard Weinberger if (ubifs_unpack_bits(c, &addr, &pos, 1))
9941e51764aSArtem Bityutskiy lprops->flags = LPROPS_INDEX;
9951e51764aSArtem Bityutskiy else
9961e51764aSArtem Bityutskiy lprops->flags = 0;
9971e51764aSArtem Bityutskiy lprops->flags |= ubifs_categorize_lprops(c, lprops);
9981e51764aSArtem Bityutskiy }
999235c362bSSheng Yong err = check_lpt_crc(c, buf, c->pnode_sz);
10001e51764aSArtem Bityutskiy return err;
10011e51764aSArtem Bityutskiy }
10021e51764aSArtem Bityutskiy
10031e51764aSArtem Bityutskiy /**
10042ba5f7aeSArtem Bityutskiy * ubifs_unpack_nnode - unpack a nnode.
10051e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
10061e51764aSArtem Bityutskiy * @buf: buffer containing packed nnode to unpack
10071e51764aSArtem Bityutskiy * @nnode: nnode structure to fill
10081e51764aSArtem Bityutskiy *
10091e51764aSArtem Bityutskiy * This function returns %0 on success and a negative error code on failure.
10101e51764aSArtem Bityutskiy */
ubifs_unpack_nnode(const struct ubifs_info * c,void * buf,struct ubifs_nnode * nnode)10112ba5f7aeSArtem Bityutskiy int ubifs_unpack_nnode(const struct ubifs_info *c, void *buf,
10121e51764aSArtem Bityutskiy struct ubifs_nnode *nnode)
10131e51764aSArtem Bityutskiy {
10141e51764aSArtem Bityutskiy uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
10151e51764aSArtem Bityutskiy int i, pos = 0, err;
10161e51764aSArtem Bityutskiy
1017235c362bSSheng Yong err = check_lpt_type(c, &addr, &pos, UBIFS_LPT_NNODE);
10181e51764aSArtem Bityutskiy if (err)
10191e51764aSArtem Bityutskiy return err;
10201e51764aSArtem Bityutskiy if (c->big_lpt)
10216eb61d58SRichard Weinberger nnode->num = ubifs_unpack_bits(c, &addr, &pos, c->pcnt_bits);
10221e51764aSArtem Bityutskiy for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
10231e51764aSArtem Bityutskiy int lnum;
10241e51764aSArtem Bityutskiy
10256eb61d58SRichard Weinberger lnum = ubifs_unpack_bits(c, &addr, &pos, c->lpt_lnum_bits) +
10261e51764aSArtem Bityutskiy c->lpt_first;
10271e51764aSArtem Bityutskiy if (lnum == c->lpt_last + 1)
10281e51764aSArtem Bityutskiy lnum = 0;
10291e51764aSArtem Bityutskiy nnode->nbranch[i].lnum = lnum;
10306eb61d58SRichard Weinberger nnode->nbranch[i].offs = ubifs_unpack_bits(c, &addr, &pos,
10311e51764aSArtem Bityutskiy c->lpt_offs_bits);
10321e51764aSArtem Bityutskiy }
1033235c362bSSheng Yong err = check_lpt_crc(c, buf, c->nnode_sz);
10341e51764aSArtem Bityutskiy return err;
10351e51764aSArtem Bityutskiy }
10361e51764aSArtem Bityutskiy
10371e51764aSArtem Bityutskiy /**
10381e51764aSArtem Bityutskiy * unpack_ltab - unpack the LPT's own lprops table.
10391e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
10401e51764aSArtem Bityutskiy * @buf: buffer from which to unpack
10411e51764aSArtem Bityutskiy *
10421e51764aSArtem Bityutskiy * This function returns %0 on success and a negative error code on failure.
10431e51764aSArtem Bityutskiy */
unpack_ltab(const struct ubifs_info * c,void * buf)10442ba5f7aeSArtem Bityutskiy static int unpack_ltab(const struct ubifs_info *c, void *buf)
10451e51764aSArtem Bityutskiy {
10461e51764aSArtem Bityutskiy uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
10471e51764aSArtem Bityutskiy int i, pos = 0, err;
10481e51764aSArtem Bityutskiy
1049235c362bSSheng Yong err = check_lpt_type(c, &addr, &pos, UBIFS_LPT_LTAB);
10501e51764aSArtem Bityutskiy if (err)
10511e51764aSArtem Bityutskiy return err;
10521e51764aSArtem Bityutskiy for (i = 0; i < c->lpt_lebs; i++) {
10536eb61d58SRichard Weinberger int free = ubifs_unpack_bits(c, &addr, &pos, c->lpt_spc_bits);
10546eb61d58SRichard Weinberger int dirty = ubifs_unpack_bits(c, &addr, &pos, c->lpt_spc_bits);
10551e51764aSArtem Bityutskiy
10561e51764aSArtem Bityutskiy if (free < 0 || free > c->leb_size || dirty < 0 ||
10571e51764aSArtem Bityutskiy dirty > c->leb_size || free + dirty > c->leb_size)
10581e51764aSArtem Bityutskiy return -EINVAL;
10591e51764aSArtem Bityutskiy
10601e51764aSArtem Bityutskiy c->ltab[i].free = free;
10611e51764aSArtem Bityutskiy c->ltab[i].dirty = dirty;
10621e51764aSArtem Bityutskiy c->ltab[i].tgc = 0;
10631e51764aSArtem Bityutskiy c->ltab[i].cmt = 0;
10641e51764aSArtem Bityutskiy }
1065235c362bSSheng Yong err = check_lpt_crc(c, buf, c->ltab_sz);
10661e51764aSArtem Bityutskiy return err;
10671e51764aSArtem Bityutskiy }
10681e51764aSArtem Bityutskiy
10691e51764aSArtem Bityutskiy /**
10701e51764aSArtem Bityutskiy * unpack_lsave - unpack the LPT's save table.
10711e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
10721e51764aSArtem Bityutskiy * @buf: buffer from which to unpack
10731e51764aSArtem Bityutskiy *
10741e51764aSArtem Bityutskiy * This function returns %0 on success and a negative error code on failure.
10751e51764aSArtem Bityutskiy */
unpack_lsave(const struct ubifs_info * c,void * buf)10762ba5f7aeSArtem Bityutskiy static int unpack_lsave(const struct ubifs_info *c, void *buf)
10771e51764aSArtem Bityutskiy {
10781e51764aSArtem Bityutskiy uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
10791e51764aSArtem Bityutskiy int i, pos = 0, err;
10801e51764aSArtem Bityutskiy
1081235c362bSSheng Yong err = check_lpt_type(c, &addr, &pos, UBIFS_LPT_LSAVE);
10821e51764aSArtem Bityutskiy if (err)
10831e51764aSArtem Bityutskiy return err;
10841e51764aSArtem Bityutskiy for (i = 0; i < c->lsave_cnt; i++) {
10856eb61d58SRichard Weinberger int lnum = ubifs_unpack_bits(c, &addr, &pos, c->lnum_bits);
10861e51764aSArtem Bityutskiy
10871e51764aSArtem Bityutskiy if (lnum < c->main_first || lnum >= c->leb_cnt)
10881e51764aSArtem Bityutskiy return -EINVAL;
10891e51764aSArtem Bityutskiy c->lsave[i] = lnum;
10901e51764aSArtem Bityutskiy }
1091235c362bSSheng Yong err = check_lpt_crc(c, buf, c->lsave_sz);
10921e51764aSArtem Bityutskiy return err;
10931e51764aSArtem Bityutskiy }
10941e51764aSArtem Bityutskiy
10951e51764aSArtem Bityutskiy /**
10961e51764aSArtem Bityutskiy * validate_nnode - validate a nnode.
10971e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
10981e51764aSArtem Bityutskiy * @nnode: nnode to validate
10991e51764aSArtem Bityutskiy * @parent: parent nnode (or NULL for the root nnode)
11001e51764aSArtem Bityutskiy * @iip: index in parent
11011e51764aSArtem Bityutskiy *
11021e51764aSArtem Bityutskiy * This function returns %0 on success and a negative error code on failure.
11031e51764aSArtem Bityutskiy */
validate_nnode(const struct ubifs_info * c,struct ubifs_nnode * nnode,struct ubifs_nnode * parent,int iip)11042ba5f7aeSArtem Bityutskiy static int validate_nnode(const struct ubifs_info *c, struct ubifs_nnode *nnode,
11051e51764aSArtem Bityutskiy struct ubifs_nnode *parent, int iip)
11061e51764aSArtem Bityutskiy {
11071e51764aSArtem Bityutskiy int i, lvl, max_offs;
11081e51764aSArtem Bityutskiy
11091e51764aSArtem Bityutskiy if (c->big_lpt) {
11101e51764aSArtem Bityutskiy int num = calc_nnode_num_from_parent(c, parent, iip);
11111e51764aSArtem Bityutskiy
11121e51764aSArtem Bityutskiy if (nnode->num != num)
11131e51764aSArtem Bityutskiy return -EINVAL;
11141e51764aSArtem Bityutskiy }
11151e51764aSArtem Bityutskiy lvl = parent ? parent->level - 1 : c->lpt_hght;
11161e51764aSArtem Bityutskiy if (lvl < 1)
11171e51764aSArtem Bityutskiy return -EINVAL;
11181e51764aSArtem Bityutskiy if (lvl == 1)
11191e51764aSArtem Bityutskiy max_offs = c->leb_size - c->pnode_sz;
11201e51764aSArtem Bityutskiy else
11211e51764aSArtem Bityutskiy max_offs = c->leb_size - c->nnode_sz;
11221e51764aSArtem Bityutskiy for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
11231e51764aSArtem Bityutskiy int lnum = nnode->nbranch[i].lnum;
11241e51764aSArtem Bityutskiy int offs = nnode->nbranch[i].offs;
11251e51764aSArtem Bityutskiy
11261e51764aSArtem Bityutskiy if (lnum == 0) {
11271e51764aSArtem Bityutskiy if (offs != 0)
11281e51764aSArtem Bityutskiy return -EINVAL;
11291e51764aSArtem Bityutskiy continue;
11301e51764aSArtem Bityutskiy }
11311e51764aSArtem Bityutskiy if (lnum < c->lpt_first || lnum > c->lpt_last)
11321e51764aSArtem Bityutskiy return -EINVAL;
11331e51764aSArtem Bityutskiy if (offs < 0 || offs > max_offs)
11341e51764aSArtem Bityutskiy return -EINVAL;
11351e51764aSArtem Bityutskiy }
11361e51764aSArtem Bityutskiy return 0;
11371e51764aSArtem Bityutskiy }
11381e51764aSArtem Bityutskiy
11391e51764aSArtem Bityutskiy /**
11401e51764aSArtem Bityutskiy * validate_pnode - validate a pnode.
11411e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
11421e51764aSArtem Bityutskiy * @pnode: pnode to validate
11431e51764aSArtem Bityutskiy * @parent: parent nnode
11441e51764aSArtem Bityutskiy * @iip: index in parent
11451e51764aSArtem Bityutskiy *
11461e51764aSArtem Bityutskiy * This function returns %0 on success and a negative error code on failure.
11471e51764aSArtem Bityutskiy */
validate_pnode(const struct ubifs_info * c,struct ubifs_pnode * pnode,struct ubifs_nnode * parent,int iip)11482ba5f7aeSArtem Bityutskiy static int validate_pnode(const struct ubifs_info *c, struct ubifs_pnode *pnode,
11491e51764aSArtem Bityutskiy struct ubifs_nnode *parent, int iip)
11501e51764aSArtem Bityutskiy {
11511e51764aSArtem Bityutskiy int i;
11521e51764aSArtem Bityutskiy
11531e51764aSArtem Bityutskiy if (c->big_lpt) {
11541e51764aSArtem Bityutskiy int num = calc_pnode_num_from_parent(c, parent, iip);
11551e51764aSArtem Bityutskiy
11561e51764aSArtem Bityutskiy if (pnode->num != num)
11571e51764aSArtem Bityutskiy return -EINVAL;
11581e51764aSArtem Bityutskiy }
11591e51764aSArtem Bityutskiy for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
11601e51764aSArtem Bityutskiy int free = pnode->lprops[i].free;
11611e51764aSArtem Bityutskiy int dirty = pnode->lprops[i].dirty;
11621e51764aSArtem Bityutskiy
11631e51764aSArtem Bityutskiy if (free < 0 || free > c->leb_size || free % c->min_io_size ||
11641e51764aSArtem Bityutskiy (free & 7))
11651e51764aSArtem Bityutskiy return -EINVAL;
11661e51764aSArtem Bityutskiy if (dirty < 0 || dirty > c->leb_size || (dirty & 7))
11671e51764aSArtem Bityutskiy return -EINVAL;
11681e51764aSArtem Bityutskiy if (dirty + free > c->leb_size)
11691e51764aSArtem Bityutskiy return -EINVAL;
11701e51764aSArtem Bityutskiy }
11711e51764aSArtem Bityutskiy return 0;
11721e51764aSArtem Bityutskiy }
11731e51764aSArtem Bityutskiy
11741e51764aSArtem Bityutskiy /**
11751e51764aSArtem Bityutskiy * set_pnode_lnum - set LEB numbers on a pnode.
11761e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
11771e51764aSArtem Bityutskiy * @pnode: pnode to update
11781e51764aSArtem Bityutskiy *
11791e51764aSArtem Bityutskiy * This function calculates the LEB numbers for the LEB properties it contains
11801e51764aSArtem Bityutskiy * based on the pnode number.
11811e51764aSArtem Bityutskiy */
set_pnode_lnum(const struct ubifs_info * c,struct ubifs_pnode * pnode)11822ba5f7aeSArtem Bityutskiy static void set_pnode_lnum(const struct ubifs_info *c,
11832ba5f7aeSArtem Bityutskiy struct ubifs_pnode *pnode)
11841e51764aSArtem Bityutskiy {
11851e51764aSArtem Bityutskiy int i, lnum;
11861e51764aSArtem Bityutskiy
11871e51764aSArtem Bityutskiy lnum = (pnode->num << UBIFS_LPT_FANOUT_SHIFT) + c->main_first;
11881e51764aSArtem Bityutskiy for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
11891e51764aSArtem Bityutskiy if (lnum >= c->leb_cnt)
11901e51764aSArtem Bityutskiy return;
11911e51764aSArtem Bityutskiy pnode->lprops[i].lnum = lnum++;
11921e51764aSArtem Bityutskiy }
11931e51764aSArtem Bityutskiy }
11941e51764aSArtem Bityutskiy
11951e51764aSArtem Bityutskiy /**
11961e51764aSArtem Bityutskiy * ubifs_read_nnode - read a nnode from flash and link it to the tree in memory.
11971e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
11981e51764aSArtem Bityutskiy * @parent: parent nnode (or NULL for the root)
11991e51764aSArtem Bityutskiy * @iip: index in parent
12001e51764aSArtem Bityutskiy *
12011e51764aSArtem Bityutskiy * This function returns %0 on success and a negative error code on failure.
12021e51764aSArtem Bityutskiy */
ubifs_read_nnode(struct ubifs_info * c,struct ubifs_nnode * parent,int iip)12031e51764aSArtem Bityutskiy int ubifs_read_nnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
12041e51764aSArtem Bityutskiy {
12051e51764aSArtem Bityutskiy struct ubifs_nbranch *branch = NULL;
12061e51764aSArtem Bityutskiy struct ubifs_nnode *nnode = NULL;
12071e51764aSArtem Bityutskiy void *buf = c->lpt_nod_buf;
12081e51764aSArtem Bityutskiy int err, lnum, offs;
12091e51764aSArtem Bityutskiy
12101e51764aSArtem Bityutskiy if (parent) {
12111e51764aSArtem Bityutskiy branch = &parent->nbranch[iip];
12121e51764aSArtem Bityutskiy lnum = branch->lnum;
12131e51764aSArtem Bityutskiy offs = branch->offs;
12141e51764aSArtem Bityutskiy } else {
12151e51764aSArtem Bityutskiy lnum = c->lpt_lnum;
12161e51764aSArtem Bityutskiy offs = c->lpt_offs;
12171e51764aSArtem Bityutskiy }
12181e51764aSArtem Bityutskiy nnode = kzalloc(sizeof(struct ubifs_nnode), GFP_NOFS);
12191e51764aSArtem Bityutskiy if (!nnode) {
12201e51764aSArtem Bityutskiy err = -ENOMEM;
12211e51764aSArtem Bityutskiy goto out;
12221e51764aSArtem Bityutskiy }
12231e51764aSArtem Bityutskiy if (lnum == 0) {
12241e51764aSArtem Bityutskiy /*
12251e51764aSArtem Bityutskiy * This nnode was not written which just means that the LEB
12261e51764aSArtem Bityutskiy * properties in the subtree below it describe empty LEBs. We
12271e51764aSArtem Bityutskiy * make the nnode as though we had read it, which in fact means
12281e51764aSArtem Bityutskiy * doing almost nothing.
12291e51764aSArtem Bityutskiy */
12301e51764aSArtem Bityutskiy if (c->big_lpt)
12311e51764aSArtem Bityutskiy nnode->num = calc_nnode_num_from_parent(c, parent, iip);
12321e51764aSArtem Bityutskiy } else {
1233d304820aSArtem Bityutskiy err = ubifs_leb_read(c, lnum, buf, offs, c->nnode_sz, 1);
12341e51764aSArtem Bityutskiy if (err)
12351e51764aSArtem Bityutskiy goto out;
12362ba5f7aeSArtem Bityutskiy err = ubifs_unpack_nnode(c, buf, nnode);
12371e51764aSArtem Bityutskiy if (err)
12381e51764aSArtem Bityutskiy goto out;
12391e51764aSArtem Bityutskiy }
12401e51764aSArtem Bityutskiy err = validate_nnode(c, nnode, parent, iip);
12411e51764aSArtem Bityutskiy if (err)
12421e51764aSArtem Bityutskiy goto out;
12431e51764aSArtem Bityutskiy if (!c->big_lpt)
12441e51764aSArtem Bityutskiy nnode->num = calc_nnode_num_from_parent(c, parent, iip);
12451e51764aSArtem Bityutskiy if (parent) {
12461e51764aSArtem Bityutskiy branch->nnode = nnode;
12471e51764aSArtem Bityutskiy nnode->level = parent->level - 1;
12481e51764aSArtem Bityutskiy } else {
12491e51764aSArtem Bityutskiy c->nroot = nnode;
12501e51764aSArtem Bityutskiy nnode->level = c->lpt_hght;
12511e51764aSArtem Bityutskiy }
12521e51764aSArtem Bityutskiy nnode->parent = parent;
12531e51764aSArtem Bityutskiy nnode->iip = iip;
12541e51764aSArtem Bityutskiy return 0;
12551e51764aSArtem Bityutskiy
12561e51764aSArtem Bityutskiy out:
1257235c362bSSheng Yong ubifs_err(c, "error %d reading nnode at %d:%d", err, lnum, offs);
12587c46d0aeSArtem Bityutskiy dump_stack();
12591e51764aSArtem Bityutskiy kfree(nnode);
12601e51764aSArtem Bityutskiy return err;
12611e51764aSArtem Bityutskiy }
12621e51764aSArtem Bityutskiy
12631e51764aSArtem Bityutskiy /**
12641e51764aSArtem Bityutskiy * read_pnode - read a pnode from flash and link it to the tree in memory.
12651e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
12661e51764aSArtem Bityutskiy * @parent: parent nnode
12671e51764aSArtem Bityutskiy * @iip: index in parent
12681e51764aSArtem Bityutskiy *
12691e51764aSArtem Bityutskiy * This function returns %0 on success and a negative error code on failure.
12701e51764aSArtem Bityutskiy */
read_pnode(struct ubifs_info * c,struct ubifs_nnode * parent,int iip)12711e51764aSArtem Bityutskiy static int read_pnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
12721e51764aSArtem Bityutskiy {
12731e51764aSArtem Bityutskiy struct ubifs_nbranch *branch;
12741e51764aSArtem Bityutskiy struct ubifs_pnode *pnode = NULL;
12751e51764aSArtem Bityutskiy void *buf = c->lpt_nod_buf;
12761e51764aSArtem Bityutskiy int err, lnum, offs;
12771e51764aSArtem Bityutskiy
12781e51764aSArtem Bityutskiy branch = &parent->nbranch[iip];
12791e51764aSArtem Bityutskiy lnum = branch->lnum;
12801e51764aSArtem Bityutskiy offs = branch->offs;
12811e51764aSArtem Bityutskiy pnode = kzalloc(sizeof(struct ubifs_pnode), GFP_NOFS);
128254acbaaaSArtem Bityutskiy if (!pnode)
128354acbaaaSArtem Bityutskiy return -ENOMEM;
128454acbaaaSArtem Bityutskiy
12851e51764aSArtem Bityutskiy if (lnum == 0) {
12861e51764aSArtem Bityutskiy /*
12871e51764aSArtem Bityutskiy * This pnode was not written which just means that the LEB
12881e51764aSArtem Bityutskiy * properties in it describe empty LEBs. We make the pnode as
12891e51764aSArtem Bityutskiy * though we had read it.
12901e51764aSArtem Bityutskiy */
12911e51764aSArtem Bityutskiy int i;
12921e51764aSArtem Bityutskiy
12931e51764aSArtem Bityutskiy if (c->big_lpt)
12941e51764aSArtem Bityutskiy pnode->num = calc_pnode_num_from_parent(c, parent, iip);
12951e51764aSArtem Bityutskiy for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
12961e51764aSArtem Bityutskiy struct ubifs_lprops * const lprops = &pnode->lprops[i];
12971e51764aSArtem Bityutskiy
12981e51764aSArtem Bityutskiy lprops->free = c->leb_size;
12991e51764aSArtem Bityutskiy lprops->flags = ubifs_categorize_lprops(c, lprops);
13001e51764aSArtem Bityutskiy }
13011e51764aSArtem Bityutskiy } else {
1302d304820aSArtem Bityutskiy err = ubifs_leb_read(c, lnum, buf, offs, c->pnode_sz, 1);
13031e51764aSArtem Bityutskiy if (err)
13041e51764aSArtem Bityutskiy goto out;
13051e51764aSArtem Bityutskiy err = unpack_pnode(c, buf, pnode);
13061e51764aSArtem Bityutskiy if (err)
13071e51764aSArtem Bityutskiy goto out;
13081e51764aSArtem Bityutskiy }
13091e51764aSArtem Bityutskiy err = validate_pnode(c, pnode, parent, iip);
13101e51764aSArtem Bityutskiy if (err)
13111e51764aSArtem Bityutskiy goto out;
13121e51764aSArtem Bityutskiy if (!c->big_lpt)
13131e51764aSArtem Bityutskiy pnode->num = calc_pnode_num_from_parent(c, parent, iip);
13141e51764aSArtem Bityutskiy branch->pnode = pnode;
13151e51764aSArtem Bityutskiy pnode->parent = parent;
13161e51764aSArtem Bityutskiy pnode->iip = iip;
13171e51764aSArtem Bityutskiy set_pnode_lnum(c, pnode);
13181e51764aSArtem Bityutskiy c->pnodes_have += 1;
13191e51764aSArtem Bityutskiy return 0;
13201e51764aSArtem Bityutskiy
13211e51764aSArtem Bityutskiy out:
1322235c362bSSheng Yong ubifs_err(c, "error %d reading pnode at %d:%d", err, lnum, offs);
1323edf6be24SArtem Bityutskiy ubifs_dump_pnode(c, pnode, parent, iip);
13247c46d0aeSArtem Bityutskiy dump_stack();
1325235c362bSSheng Yong ubifs_err(c, "calc num: %d", calc_pnode_num_from_parent(c, parent, iip));
13261e51764aSArtem Bityutskiy kfree(pnode);
13271e51764aSArtem Bityutskiy return err;
13281e51764aSArtem Bityutskiy }
13291e51764aSArtem Bityutskiy
13301e51764aSArtem Bityutskiy /**
13311e51764aSArtem Bityutskiy * read_ltab - read LPT's own lprops table.
13321e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
13331e51764aSArtem Bityutskiy *
13341e51764aSArtem Bityutskiy * This function returns %0 on success and a negative error code on failure.
13351e51764aSArtem Bityutskiy */
read_ltab(struct ubifs_info * c)13361e51764aSArtem Bityutskiy static int read_ltab(struct ubifs_info *c)
13371e51764aSArtem Bityutskiy {
13381e51764aSArtem Bityutskiy int err;
13391e51764aSArtem Bityutskiy void *buf;
13401e51764aSArtem Bityutskiy
13411e51764aSArtem Bityutskiy buf = vmalloc(c->ltab_sz);
13421e51764aSArtem Bityutskiy if (!buf)
13431e51764aSArtem Bityutskiy return -ENOMEM;
1344d304820aSArtem Bityutskiy err = ubifs_leb_read(c, c->ltab_lnum, buf, c->ltab_offs, c->ltab_sz, 1);
13451e51764aSArtem Bityutskiy if (err)
13461e51764aSArtem Bityutskiy goto out;
13471e51764aSArtem Bityutskiy err = unpack_ltab(c, buf);
13481e51764aSArtem Bityutskiy out:
13491e51764aSArtem Bityutskiy vfree(buf);
13501e51764aSArtem Bityutskiy return err;
13511e51764aSArtem Bityutskiy }
13521e51764aSArtem Bityutskiy
13531e51764aSArtem Bityutskiy /**
13541e51764aSArtem Bityutskiy * read_lsave - read LPT's save table.
13551e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
13561e51764aSArtem Bityutskiy *
13571e51764aSArtem Bityutskiy * This function returns %0 on success and a negative error code on failure.
13581e51764aSArtem Bityutskiy */
read_lsave(struct ubifs_info * c)13591e51764aSArtem Bityutskiy static int read_lsave(struct ubifs_info *c)
13601e51764aSArtem Bityutskiy {
13611e51764aSArtem Bityutskiy int err, i;
13621e51764aSArtem Bityutskiy void *buf;
13631e51764aSArtem Bityutskiy
13641e51764aSArtem Bityutskiy buf = vmalloc(c->lsave_sz);
13651e51764aSArtem Bityutskiy if (!buf)
13661e51764aSArtem Bityutskiy return -ENOMEM;
1367d304820aSArtem Bityutskiy err = ubifs_leb_read(c, c->lsave_lnum, buf, c->lsave_offs,
1368d304820aSArtem Bityutskiy c->lsave_sz, 1);
13691e51764aSArtem Bityutskiy if (err)
13701e51764aSArtem Bityutskiy goto out;
13711e51764aSArtem Bityutskiy err = unpack_lsave(c, buf);
13721e51764aSArtem Bityutskiy if (err)
13731e51764aSArtem Bityutskiy goto out;
13741e51764aSArtem Bityutskiy for (i = 0; i < c->lsave_cnt; i++) {
13751e51764aSArtem Bityutskiy int lnum = c->lsave[i];
13760e54c899SVasiliy Kulikov struct ubifs_lprops *lprops;
13771e51764aSArtem Bityutskiy
13781e51764aSArtem Bityutskiy /*
13791e51764aSArtem Bityutskiy * Due to automatic resizing, the values in the lsave table
13801e51764aSArtem Bityutskiy * could be beyond the volume size - just ignore them.
13811e51764aSArtem Bityutskiy */
13821e51764aSArtem Bityutskiy if (lnum >= c->leb_cnt)
13831e51764aSArtem Bityutskiy continue;
13840e54c899SVasiliy Kulikov lprops = ubifs_lpt_lookup(c, lnum);
13850e54c899SVasiliy Kulikov if (IS_ERR(lprops)) {
13860e54c899SVasiliy Kulikov err = PTR_ERR(lprops);
13870e54c899SVasiliy Kulikov goto out;
13880e54c899SVasiliy Kulikov }
13891e51764aSArtem Bityutskiy }
13901e51764aSArtem Bityutskiy out:
13911e51764aSArtem Bityutskiy vfree(buf);
13921e51764aSArtem Bityutskiy return err;
13931e51764aSArtem Bityutskiy }
13941e51764aSArtem Bityutskiy
13951e51764aSArtem Bityutskiy /**
13961e51764aSArtem Bityutskiy * ubifs_get_nnode - get a nnode.
13971e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
13981e51764aSArtem Bityutskiy * @parent: parent nnode (or NULL for the root)
13991e51764aSArtem Bityutskiy * @iip: index in parent
14001e51764aSArtem Bityutskiy *
14011e51764aSArtem Bityutskiy * This function returns a pointer to the nnode on success or a negative error
14021e51764aSArtem Bityutskiy * code on failure.
14031e51764aSArtem Bityutskiy */
ubifs_get_nnode(struct ubifs_info * c,struct ubifs_nnode * parent,int iip)14041e51764aSArtem Bityutskiy struct ubifs_nnode *ubifs_get_nnode(struct ubifs_info *c,
14051e51764aSArtem Bityutskiy struct ubifs_nnode *parent, int iip)
14061e51764aSArtem Bityutskiy {
14071e51764aSArtem Bityutskiy struct ubifs_nbranch *branch;
14081e51764aSArtem Bityutskiy struct ubifs_nnode *nnode;
14091e51764aSArtem Bityutskiy int err;
14101e51764aSArtem Bityutskiy
14111e51764aSArtem Bityutskiy branch = &parent->nbranch[iip];
14121e51764aSArtem Bityutskiy nnode = branch->nnode;
14131e51764aSArtem Bityutskiy if (nnode)
14141e51764aSArtem Bityutskiy return nnode;
14151e51764aSArtem Bityutskiy err = ubifs_read_nnode(c, parent, iip);
14161e51764aSArtem Bityutskiy if (err)
14171e51764aSArtem Bityutskiy return ERR_PTR(err);
14181e51764aSArtem Bityutskiy return branch->nnode;
14191e51764aSArtem Bityutskiy }
14201e51764aSArtem Bityutskiy
14211e51764aSArtem Bityutskiy /**
14221e51764aSArtem Bityutskiy * ubifs_get_pnode - get a pnode.
14231e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
14241e51764aSArtem Bityutskiy * @parent: parent nnode
14251e51764aSArtem Bityutskiy * @iip: index in parent
14261e51764aSArtem Bityutskiy *
14271e51764aSArtem Bityutskiy * This function returns a pointer to the pnode on success or a negative error
14281e51764aSArtem Bityutskiy * code on failure.
14291e51764aSArtem Bityutskiy */
ubifs_get_pnode(struct ubifs_info * c,struct ubifs_nnode * parent,int iip)14301e51764aSArtem Bityutskiy struct ubifs_pnode *ubifs_get_pnode(struct ubifs_info *c,
14311e51764aSArtem Bityutskiy struct ubifs_nnode *parent, int iip)
14321e51764aSArtem Bityutskiy {
14331e51764aSArtem Bityutskiy struct ubifs_nbranch *branch;
14341e51764aSArtem Bityutskiy struct ubifs_pnode *pnode;
14351e51764aSArtem Bityutskiy int err;
14361e51764aSArtem Bityutskiy
14371e51764aSArtem Bityutskiy branch = &parent->nbranch[iip];
14381e51764aSArtem Bityutskiy pnode = branch->pnode;
14391e51764aSArtem Bityutskiy if (pnode)
14401e51764aSArtem Bityutskiy return pnode;
14411e51764aSArtem Bityutskiy err = read_pnode(c, parent, iip);
14421e51764aSArtem Bityutskiy if (err)
14431e51764aSArtem Bityutskiy return ERR_PTR(err);
14441e51764aSArtem Bityutskiy update_cats(c, branch->pnode);
14451e51764aSArtem Bityutskiy return branch->pnode;
14461e51764aSArtem Bityutskiy }
14471e51764aSArtem Bityutskiy
14481e51764aSArtem Bityutskiy /**
14490e26b6e2SSascha Hauer * ubifs_pnode_lookup - lookup a pnode in the LPT.
14500e26b6e2SSascha Hauer * @c: UBIFS file-system description object
14510e26b6e2SSascha Hauer * @i: pnode number (0 to (main_lebs - 1) / UBIFS_LPT_FANOUT)
14520e26b6e2SSascha Hauer *
14530e26b6e2SSascha Hauer * This function returns a pointer to the pnode on success or a negative
14540e26b6e2SSascha Hauer * error code on failure.
14550e26b6e2SSascha Hauer */
ubifs_pnode_lookup(struct ubifs_info * c,int i)14560e26b6e2SSascha Hauer struct ubifs_pnode *ubifs_pnode_lookup(struct ubifs_info *c, int i)
14570e26b6e2SSascha Hauer {
14580e26b6e2SSascha Hauer int err, h, iip, shft;
14590e26b6e2SSascha Hauer struct ubifs_nnode *nnode;
14600e26b6e2SSascha Hauer
14610e26b6e2SSascha Hauer if (!c->nroot) {
14620e26b6e2SSascha Hauer err = ubifs_read_nnode(c, NULL, 0);
14630e26b6e2SSascha Hauer if (err)
14640e26b6e2SSascha Hauer return ERR_PTR(err);
14650e26b6e2SSascha Hauer }
14660e26b6e2SSascha Hauer i <<= UBIFS_LPT_FANOUT_SHIFT;
14670e26b6e2SSascha Hauer nnode = c->nroot;
14680e26b6e2SSascha Hauer shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT;
14690e26b6e2SSascha Hauer for (h = 1; h < c->lpt_hght; h++) {
14700e26b6e2SSascha Hauer iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
14710e26b6e2SSascha Hauer shft -= UBIFS_LPT_FANOUT_SHIFT;
14720e26b6e2SSascha Hauer nnode = ubifs_get_nnode(c, nnode, iip);
14730e26b6e2SSascha Hauer if (IS_ERR(nnode))
14740e26b6e2SSascha Hauer return ERR_CAST(nnode);
14750e26b6e2SSascha Hauer }
14760e26b6e2SSascha Hauer iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
14770e26b6e2SSascha Hauer return ubifs_get_pnode(c, nnode, iip);
14780e26b6e2SSascha Hauer }
14790e26b6e2SSascha Hauer
14800e26b6e2SSascha Hauer /**
14811e51764aSArtem Bityutskiy * ubifs_lpt_lookup - lookup LEB properties in the LPT.
14821e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
14831e51764aSArtem Bityutskiy * @lnum: LEB number to lookup
14841e51764aSArtem Bityutskiy *
14851e51764aSArtem Bityutskiy * This function returns a pointer to the LEB properties on success or a
14861e51764aSArtem Bityutskiy * negative error code on failure.
14871e51764aSArtem Bityutskiy */
ubifs_lpt_lookup(struct ubifs_info * c,int lnum)14881e51764aSArtem Bityutskiy struct ubifs_lprops *ubifs_lpt_lookup(struct ubifs_info *c, int lnum)
14891e51764aSArtem Bityutskiy {
1490e635cf8cSSascha Hauer int i, iip;
14911e51764aSArtem Bityutskiy struct ubifs_pnode *pnode;
14921e51764aSArtem Bityutskiy
14931e51764aSArtem Bityutskiy i = lnum - c->main_first;
1494e635cf8cSSascha Hauer pnode = ubifs_pnode_lookup(c, i >> UBIFS_LPT_FANOUT_SHIFT);
14951e51764aSArtem Bityutskiy if (IS_ERR(pnode))
14966da5156fSJulia Lawall return ERR_CAST(pnode);
14971e51764aSArtem Bityutskiy iip = (i & (UBIFS_LPT_FANOUT - 1));
14981e51764aSArtem Bityutskiy dbg_lp("LEB %d, free %d, dirty %d, flags %d", lnum,
14991e51764aSArtem Bityutskiy pnode->lprops[iip].free, pnode->lprops[iip].dirty,
15001e51764aSArtem Bityutskiy pnode->lprops[iip].flags);
15011e51764aSArtem Bityutskiy return &pnode->lprops[iip];
15021e51764aSArtem Bityutskiy }
15031e51764aSArtem Bityutskiy
15041e51764aSArtem Bityutskiy /**
15051e51764aSArtem Bityutskiy * dirty_cow_nnode - ensure a nnode is not being committed.
15061e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
15071e51764aSArtem Bityutskiy * @nnode: nnode to check
15081e51764aSArtem Bityutskiy *
15091e51764aSArtem Bityutskiy * Returns dirtied nnode on success or negative error code on failure.
15101e51764aSArtem Bityutskiy */
dirty_cow_nnode(struct ubifs_info * c,struct ubifs_nnode * nnode)15111e51764aSArtem Bityutskiy static struct ubifs_nnode *dirty_cow_nnode(struct ubifs_info *c,
15121e51764aSArtem Bityutskiy struct ubifs_nnode *nnode)
15131e51764aSArtem Bityutskiy {
15141e51764aSArtem Bityutskiy struct ubifs_nnode *n;
15151e51764aSArtem Bityutskiy int i;
15161e51764aSArtem Bityutskiy
15171e51764aSArtem Bityutskiy if (!test_bit(COW_CNODE, &nnode->flags)) {
15181e51764aSArtem Bityutskiy /* nnode is not being committed */
15191e51764aSArtem Bityutskiy if (!test_and_set_bit(DIRTY_CNODE, &nnode->flags)) {
15201e51764aSArtem Bityutskiy c->dirty_nn_cnt += 1;
15211e51764aSArtem Bityutskiy ubifs_add_nnode_dirt(c, nnode);
15221e51764aSArtem Bityutskiy }
15231e51764aSArtem Bityutskiy return nnode;
15241e51764aSArtem Bityutskiy }
15251e51764aSArtem Bityutskiy
15261e51764aSArtem Bityutskiy /* nnode is being committed, so copy it */
1527bbc8a004SAndrzej Hajda n = kmemdup(nnode, sizeof(struct ubifs_nnode), GFP_NOFS);
15281e51764aSArtem Bityutskiy if (unlikely(!n))
15291e51764aSArtem Bityutskiy return ERR_PTR(-ENOMEM);
15301e51764aSArtem Bityutskiy
15311e51764aSArtem Bityutskiy n->cnext = NULL;
15321e51764aSArtem Bityutskiy __set_bit(DIRTY_CNODE, &n->flags);
15331e51764aSArtem Bityutskiy __clear_bit(COW_CNODE, &n->flags);
15341e51764aSArtem Bityutskiy
15351e51764aSArtem Bityutskiy /* The children now have new parent */
15361e51764aSArtem Bityutskiy for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
15371e51764aSArtem Bityutskiy struct ubifs_nbranch *branch = &n->nbranch[i];
15381e51764aSArtem Bityutskiy
15391e51764aSArtem Bityutskiy if (branch->cnode)
15401e51764aSArtem Bityutskiy branch->cnode->parent = n;
15411e51764aSArtem Bityutskiy }
15421e51764aSArtem Bityutskiy
15436eb61d58SRichard Weinberger ubifs_assert(c, !test_bit(OBSOLETE_CNODE, &nnode->flags));
15441e51764aSArtem Bityutskiy __set_bit(OBSOLETE_CNODE, &nnode->flags);
15451e51764aSArtem Bityutskiy
15461e51764aSArtem Bityutskiy c->dirty_nn_cnt += 1;
15471e51764aSArtem Bityutskiy ubifs_add_nnode_dirt(c, nnode);
15481e51764aSArtem Bityutskiy if (nnode->parent)
15491e51764aSArtem Bityutskiy nnode->parent->nbranch[n->iip].nnode = n;
15501e51764aSArtem Bityutskiy else
15511e51764aSArtem Bityutskiy c->nroot = n;
15521e51764aSArtem Bityutskiy return n;
15531e51764aSArtem Bityutskiy }
15541e51764aSArtem Bityutskiy
15551e51764aSArtem Bityutskiy /**
15561e51764aSArtem Bityutskiy * dirty_cow_pnode - ensure a pnode is not being committed.
15571e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
15581e51764aSArtem Bityutskiy * @pnode: pnode to check
15591e51764aSArtem Bityutskiy *
15601e51764aSArtem Bityutskiy * Returns dirtied pnode on success or negative error code on failure.
15611e51764aSArtem Bityutskiy */
dirty_cow_pnode(struct ubifs_info * c,struct ubifs_pnode * pnode)15621e51764aSArtem Bityutskiy static struct ubifs_pnode *dirty_cow_pnode(struct ubifs_info *c,
15631e51764aSArtem Bityutskiy struct ubifs_pnode *pnode)
15641e51764aSArtem Bityutskiy {
15651e51764aSArtem Bityutskiy struct ubifs_pnode *p;
15661e51764aSArtem Bityutskiy
15671e51764aSArtem Bityutskiy if (!test_bit(COW_CNODE, &pnode->flags)) {
15681e51764aSArtem Bityutskiy /* pnode is not being committed */
15691e51764aSArtem Bityutskiy if (!test_and_set_bit(DIRTY_CNODE, &pnode->flags)) {
15701e51764aSArtem Bityutskiy c->dirty_pn_cnt += 1;
15711e51764aSArtem Bityutskiy add_pnode_dirt(c, pnode);
15721e51764aSArtem Bityutskiy }
15731e51764aSArtem Bityutskiy return pnode;
15741e51764aSArtem Bityutskiy }
15751e51764aSArtem Bityutskiy
15761e51764aSArtem Bityutskiy /* pnode is being committed, so copy it */
1577bbc8a004SAndrzej Hajda p = kmemdup(pnode, sizeof(struct ubifs_pnode), GFP_NOFS);
15781e51764aSArtem Bityutskiy if (unlikely(!p))
15791e51764aSArtem Bityutskiy return ERR_PTR(-ENOMEM);
15801e51764aSArtem Bityutskiy
15811e51764aSArtem Bityutskiy p->cnext = NULL;
15821e51764aSArtem Bityutskiy __set_bit(DIRTY_CNODE, &p->flags);
15831e51764aSArtem Bityutskiy __clear_bit(COW_CNODE, &p->flags);
15841e51764aSArtem Bityutskiy replace_cats(c, pnode, p);
15851e51764aSArtem Bityutskiy
15866eb61d58SRichard Weinberger ubifs_assert(c, !test_bit(OBSOLETE_CNODE, &pnode->flags));
15871e51764aSArtem Bityutskiy __set_bit(OBSOLETE_CNODE, &pnode->flags);
15881e51764aSArtem Bityutskiy
15891e51764aSArtem Bityutskiy c->dirty_pn_cnt += 1;
15901e51764aSArtem Bityutskiy add_pnode_dirt(c, pnode);
15911e51764aSArtem Bityutskiy pnode->parent->nbranch[p->iip].pnode = p;
15921e51764aSArtem Bityutskiy return p;
15931e51764aSArtem Bityutskiy }
15941e51764aSArtem Bityutskiy
15951e51764aSArtem Bityutskiy /**
15961e51764aSArtem Bityutskiy * ubifs_lpt_lookup_dirty - lookup LEB properties in the LPT.
15971e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
15981e51764aSArtem Bityutskiy * @lnum: LEB number to lookup
15991e51764aSArtem Bityutskiy *
16001e51764aSArtem Bityutskiy * This function returns a pointer to the LEB properties on success or a
16011e51764aSArtem Bityutskiy * negative error code on failure.
16021e51764aSArtem Bityutskiy */
ubifs_lpt_lookup_dirty(struct ubifs_info * c,int lnum)16031e51764aSArtem Bityutskiy struct ubifs_lprops *ubifs_lpt_lookup_dirty(struct ubifs_info *c, int lnum)
16041e51764aSArtem Bityutskiy {
16051e51764aSArtem Bityutskiy int err, i, h, iip, shft;
16061e51764aSArtem Bityutskiy struct ubifs_nnode *nnode;
16071e51764aSArtem Bityutskiy struct ubifs_pnode *pnode;
16081e51764aSArtem Bityutskiy
16091e51764aSArtem Bityutskiy if (!c->nroot) {
16101e51764aSArtem Bityutskiy err = ubifs_read_nnode(c, NULL, 0);
16111e51764aSArtem Bityutskiy if (err)
16121e51764aSArtem Bityutskiy return ERR_PTR(err);
16131e51764aSArtem Bityutskiy }
16141e51764aSArtem Bityutskiy nnode = c->nroot;
16151e51764aSArtem Bityutskiy nnode = dirty_cow_nnode(c, nnode);
16161e51764aSArtem Bityutskiy if (IS_ERR(nnode))
16176da5156fSJulia Lawall return ERR_CAST(nnode);
16181e51764aSArtem Bityutskiy i = lnum - c->main_first;
16191e51764aSArtem Bityutskiy shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT;
16201e51764aSArtem Bityutskiy for (h = 1; h < c->lpt_hght; h++) {
16211e51764aSArtem Bityutskiy iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
16221e51764aSArtem Bityutskiy shft -= UBIFS_LPT_FANOUT_SHIFT;
16231e51764aSArtem Bityutskiy nnode = ubifs_get_nnode(c, nnode, iip);
16241e51764aSArtem Bityutskiy if (IS_ERR(nnode))
16256da5156fSJulia Lawall return ERR_CAST(nnode);
16261e51764aSArtem Bityutskiy nnode = dirty_cow_nnode(c, nnode);
16271e51764aSArtem Bityutskiy if (IS_ERR(nnode))
16286da5156fSJulia Lawall return ERR_CAST(nnode);
16291e51764aSArtem Bityutskiy }
16301e51764aSArtem Bityutskiy iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
16311e51764aSArtem Bityutskiy pnode = ubifs_get_pnode(c, nnode, iip);
16321e51764aSArtem Bityutskiy if (IS_ERR(pnode))
16336da5156fSJulia Lawall return ERR_CAST(pnode);
16341e51764aSArtem Bityutskiy pnode = dirty_cow_pnode(c, pnode);
16351e51764aSArtem Bityutskiy if (IS_ERR(pnode))
16366da5156fSJulia Lawall return ERR_CAST(pnode);
16371e51764aSArtem Bityutskiy iip = (i & (UBIFS_LPT_FANOUT - 1));
16381e51764aSArtem Bityutskiy dbg_lp("LEB %d, free %d, dirty %d, flags %d", lnum,
16391e51764aSArtem Bityutskiy pnode->lprops[iip].free, pnode->lprops[iip].dirty,
16401e51764aSArtem Bityutskiy pnode->lprops[iip].flags);
16416eb61d58SRichard Weinberger ubifs_assert(c, test_bit(DIRTY_CNODE, &pnode->flags));
16421e51764aSArtem Bityutskiy return &pnode->lprops[iip];
16431e51764aSArtem Bityutskiy }
16441e51764aSArtem Bityutskiy
16451e51764aSArtem Bityutskiy /**
1646a1dc5814SSascha Hauer * ubifs_lpt_calc_hash - Calculate hash of the LPT pnodes
1647a1dc5814SSascha Hauer * @c: UBIFS file-system description object
1648a1dc5814SSascha Hauer * @hash: the returned hash of the LPT pnodes
1649a1dc5814SSascha Hauer *
1650a1dc5814SSascha Hauer * This function iterates over the LPT pnodes and creates a hash over them.
1651a1dc5814SSascha Hauer * Returns 0 for success or a negative error code otherwise.
1652a1dc5814SSascha Hauer */
ubifs_lpt_calc_hash(struct ubifs_info * c,u8 * hash)1653a1dc5814SSascha Hauer int ubifs_lpt_calc_hash(struct ubifs_info *c, u8 *hash)
1654a1dc5814SSascha Hauer {
1655a1dc5814SSascha Hauer struct ubifs_nnode *nnode, *nn;
1656a1dc5814SSascha Hauer struct ubifs_cnode *cnode;
1657a1dc5814SSascha Hauer struct shash_desc *desc;
1658a1dc5814SSascha Hauer int iip = 0, i;
1659a1dc5814SSascha Hauer int bufsiz = max_t(int, c->nnode_sz, c->pnode_sz);
1660a1dc5814SSascha Hauer void *buf;
1661a1dc5814SSascha Hauer int err;
1662a1dc5814SSascha Hauer
1663a1dc5814SSascha Hauer if (!ubifs_authenticated(c))
1664a1dc5814SSascha Hauer return 0;
1665a1dc5814SSascha Hauer
16666554a56fSGarry McNulty if (!c->nroot) {
16676554a56fSGarry McNulty err = ubifs_read_nnode(c, NULL, 0);
16686554a56fSGarry McNulty if (err)
16696554a56fSGarry McNulty return err;
16706554a56fSGarry McNulty }
16716554a56fSGarry McNulty
1672a1dc5814SSascha Hauer desc = ubifs_hash_get_desc(c);
1673a1dc5814SSascha Hauer if (IS_ERR(desc))
1674a1dc5814SSascha Hauer return PTR_ERR(desc);
1675a1dc5814SSascha Hauer
1676a1dc5814SSascha Hauer buf = kmalloc(bufsiz, GFP_NOFS);
1677a1dc5814SSascha Hauer if (!buf) {
1678a1dc5814SSascha Hauer err = -ENOMEM;
1679a1dc5814SSascha Hauer goto out;
1680a1dc5814SSascha Hauer }
1681a1dc5814SSascha Hauer
1682a1dc5814SSascha Hauer cnode = (struct ubifs_cnode *)c->nroot;
1683a1dc5814SSascha Hauer
1684a1dc5814SSascha Hauer while (cnode) {
1685a1dc5814SSascha Hauer nnode = cnode->parent;
1686a1dc5814SSascha Hauer nn = (struct ubifs_nnode *)cnode;
1687a1dc5814SSascha Hauer if (cnode->level > 1) {
1688a1dc5814SSascha Hauer while (iip < UBIFS_LPT_FANOUT) {
1689a1dc5814SSascha Hauer if (nn->nbranch[iip].lnum == 0) {
1690a1dc5814SSascha Hauer /* Go right */
1691a1dc5814SSascha Hauer iip++;
1692a1dc5814SSascha Hauer continue;
1693a1dc5814SSascha Hauer }
1694a1dc5814SSascha Hauer
1695a1dc5814SSascha Hauer nnode = ubifs_get_nnode(c, nn, iip);
1696a1dc5814SSascha Hauer if (IS_ERR(nnode)) {
1697a1dc5814SSascha Hauer err = PTR_ERR(nnode);
1698a1dc5814SSascha Hauer goto out;
1699a1dc5814SSascha Hauer }
1700a1dc5814SSascha Hauer
1701a1dc5814SSascha Hauer /* Go down */
1702a1dc5814SSascha Hauer iip = 0;
1703a1dc5814SSascha Hauer cnode = (struct ubifs_cnode *)nnode;
1704a1dc5814SSascha Hauer break;
1705a1dc5814SSascha Hauer }
1706a1dc5814SSascha Hauer if (iip < UBIFS_LPT_FANOUT)
1707a1dc5814SSascha Hauer continue;
1708a1dc5814SSascha Hauer } else {
1709a1dc5814SSascha Hauer struct ubifs_pnode *pnode;
1710a1dc5814SSascha Hauer
1711a1dc5814SSascha Hauer for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
1712a1dc5814SSascha Hauer if (nn->nbranch[i].lnum == 0)
1713a1dc5814SSascha Hauer continue;
1714a1dc5814SSascha Hauer pnode = ubifs_get_pnode(c, nn, i);
1715a1dc5814SSascha Hauer if (IS_ERR(pnode)) {
1716a1dc5814SSascha Hauer err = PTR_ERR(pnode);
1717a1dc5814SSascha Hauer goto out;
1718a1dc5814SSascha Hauer }
1719a1dc5814SSascha Hauer
1720a1dc5814SSascha Hauer ubifs_pack_pnode(c, buf, pnode);
1721a1dc5814SSascha Hauer err = ubifs_shash_update(c, desc, buf,
1722a1dc5814SSascha Hauer c->pnode_sz);
1723a1dc5814SSascha Hauer if (err)
1724a1dc5814SSascha Hauer goto out;
1725a1dc5814SSascha Hauer }
1726a1dc5814SSascha Hauer }
1727a1dc5814SSascha Hauer /* Go up and to the right */
1728a1dc5814SSascha Hauer iip = cnode->iip + 1;
1729a1dc5814SSascha Hauer cnode = (struct ubifs_cnode *)nnode;
1730a1dc5814SSascha Hauer }
1731a1dc5814SSascha Hauer
1732a1dc5814SSascha Hauer err = ubifs_shash_final(c, desc, hash);
1733a1dc5814SSascha Hauer out:
1734a1dc5814SSascha Hauer kfree(desc);
1735a1dc5814SSascha Hauer kfree(buf);
1736a1dc5814SSascha Hauer
1737a1dc5814SSascha Hauer return err;
1738a1dc5814SSascha Hauer }
1739a1dc5814SSascha Hauer
1740a1dc5814SSascha Hauer /**
1741a1dc5814SSascha Hauer * lpt_check_hash - check the hash of the LPT.
1742a1dc5814SSascha Hauer * @c: UBIFS file-system description object
1743a1dc5814SSascha Hauer *
1744a1dc5814SSascha Hauer * This function calculates a hash over all pnodes in the LPT and compares it with
1745a1dc5814SSascha Hauer * the hash stored in the master node. Returns %0 on success and a negative error
1746a1dc5814SSascha Hauer * code on failure.
1747a1dc5814SSascha Hauer */
lpt_check_hash(struct ubifs_info * c)1748a1dc5814SSascha Hauer static int lpt_check_hash(struct ubifs_info *c)
1749a1dc5814SSascha Hauer {
1750a1dc5814SSascha Hauer int err;
1751a1dc5814SSascha Hauer u8 hash[UBIFS_HASH_ARR_SZ];
1752a1dc5814SSascha Hauer
1753a1dc5814SSascha Hauer if (!ubifs_authenticated(c))
1754a1dc5814SSascha Hauer return 0;
1755a1dc5814SSascha Hauer
1756a1dc5814SSascha Hauer err = ubifs_lpt_calc_hash(c, hash);
1757a1dc5814SSascha Hauer if (err)
1758a1dc5814SSascha Hauer return err;
1759a1dc5814SSascha Hauer
1760a1dc5814SSascha Hauer if (ubifs_check_hash(c, c->mst_node->hash_lpt, hash)) {
1761a1dc5814SSascha Hauer err = -EPERM;
1762a1dc5814SSascha Hauer ubifs_err(c, "Failed to authenticate LPT");
1763a1dc5814SSascha Hauer } else {
1764a1dc5814SSascha Hauer err = 0;
1765a1dc5814SSascha Hauer }
1766a1dc5814SSascha Hauer
1767a1dc5814SSascha Hauer return err;
1768a1dc5814SSascha Hauer }
1769a1dc5814SSascha Hauer
1770a1dc5814SSascha Hauer /**
17711e51764aSArtem Bityutskiy * lpt_init_rd - initialize the LPT for reading.
17721e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
17731e51764aSArtem Bityutskiy *
17741e51764aSArtem Bityutskiy * This function returns %0 on success and a negative error code on failure.
17751e51764aSArtem Bityutskiy */
lpt_init_rd(struct ubifs_info * c)17761e51764aSArtem Bityutskiy static int lpt_init_rd(struct ubifs_info *c)
17771e51764aSArtem Bityutskiy {
17781e51764aSArtem Bityutskiy int err, i;
17791e51764aSArtem Bityutskiy
178042bc47b3SKees Cook c->ltab = vmalloc(array_size(sizeof(struct ubifs_lpt_lprops),
178142bc47b3SKees Cook c->lpt_lebs));
17821e51764aSArtem Bityutskiy if (!c->ltab)
17831e51764aSArtem Bityutskiy return -ENOMEM;
17841e51764aSArtem Bityutskiy
17851e51764aSArtem Bityutskiy i = max_t(int, c->nnode_sz, c->pnode_sz);
17861e51764aSArtem Bityutskiy c->lpt_nod_buf = kmalloc(i, GFP_KERNEL);
17871e51764aSArtem Bityutskiy if (!c->lpt_nod_buf)
17881e51764aSArtem Bityutskiy return -ENOMEM;
17891e51764aSArtem Bityutskiy
17901e51764aSArtem Bityutskiy for (i = 0; i < LPROPS_HEAP_CNT; i++) {
17916da2ec56SKees Cook c->lpt_heap[i].arr = kmalloc_array(LPT_HEAP_SZ,
17926da2ec56SKees Cook sizeof(void *),
17931e51764aSArtem Bityutskiy GFP_KERNEL);
17941e51764aSArtem Bityutskiy if (!c->lpt_heap[i].arr)
17951e51764aSArtem Bityutskiy return -ENOMEM;
17961e51764aSArtem Bityutskiy c->lpt_heap[i].cnt = 0;
17971e51764aSArtem Bityutskiy c->lpt_heap[i].max_cnt = LPT_HEAP_SZ;
17981e51764aSArtem Bityutskiy }
17991e51764aSArtem Bityutskiy
18006da2ec56SKees Cook c->dirty_idx.arr = kmalloc_array(LPT_HEAP_SZ, sizeof(void *),
18016da2ec56SKees Cook GFP_KERNEL);
18021e51764aSArtem Bityutskiy if (!c->dirty_idx.arr)
18031e51764aSArtem Bityutskiy return -ENOMEM;
18041e51764aSArtem Bityutskiy c->dirty_idx.cnt = 0;
18051e51764aSArtem Bityutskiy c->dirty_idx.max_cnt = LPT_HEAP_SZ;
18061e51764aSArtem Bityutskiy
18071e51764aSArtem Bityutskiy err = read_ltab(c);
18081e51764aSArtem Bityutskiy if (err)
18091e51764aSArtem Bityutskiy return err;
18101e51764aSArtem Bityutskiy
1811a1dc5814SSascha Hauer err = lpt_check_hash(c);
1812a1dc5814SSascha Hauer if (err)
1813a1dc5814SSascha Hauer return err;
1814a1dc5814SSascha Hauer
18151e51764aSArtem Bityutskiy dbg_lp("space_bits %d", c->space_bits);
18161e51764aSArtem Bityutskiy dbg_lp("lpt_lnum_bits %d", c->lpt_lnum_bits);
18171e51764aSArtem Bityutskiy dbg_lp("lpt_offs_bits %d", c->lpt_offs_bits);
18181e51764aSArtem Bityutskiy dbg_lp("lpt_spc_bits %d", c->lpt_spc_bits);
18191e51764aSArtem Bityutskiy dbg_lp("pcnt_bits %d", c->pcnt_bits);
18201e51764aSArtem Bityutskiy dbg_lp("lnum_bits %d", c->lnum_bits);
18211e51764aSArtem Bityutskiy dbg_lp("pnode_sz %d", c->pnode_sz);
18221e51764aSArtem Bityutskiy dbg_lp("nnode_sz %d", c->nnode_sz);
18231e51764aSArtem Bityutskiy dbg_lp("ltab_sz %d", c->ltab_sz);
18241e51764aSArtem Bityutskiy dbg_lp("lsave_sz %d", c->lsave_sz);
18251e51764aSArtem Bityutskiy dbg_lp("lsave_cnt %d", c->lsave_cnt);
18261e51764aSArtem Bityutskiy dbg_lp("lpt_hght %d", c->lpt_hght);
1827*f2124007SChengsong Ke dbg_lp("big_lpt %u", c->big_lpt);
18281e51764aSArtem Bityutskiy dbg_lp("LPT root is at %d:%d", c->lpt_lnum, c->lpt_offs);
18291e51764aSArtem Bityutskiy dbg_lp("LPT head is at %d:%d", c->nhead_lnum, c->nhead_offs);
18301e51764aSArtem Bityutskiy dbg_lp("LPT ltab is at %d:%d", c->ltab_lnum, c->ltab_offs);
18311e51764aSArtem Bityutskiy if (c->big_lpt)
18321e51764aSArtem Bityutskiy dbg_lp("LPT lsave is at %d:%d", c->lsave_lnum, c->lsave_offs);
18331e51764aSArtem Bityutskiy
18341e51764aSArtem Bityutskiy return 0;
18351e51764aSArtem Bityutskiy }
18361e51764aSArtem Bityutskiy
18371e51764aSArtem Bityutskiy /**
18381e51764aSArtem Bityutskiy * lpt_init_wr - initialize the LPT for writing.
18391e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
18401e51764aSArtem Bityutskiy *
18411e51764aSArtem Bityutskiy * 'lpt_init_rd()' must have been called already.
18421e51764aSArtem Bityutskiy *
18431e51764aSArtem Bityutskiy * This function returns %0 on success and a negative error code on failure.
18441e51764aSArtem Bityutskiy */
lpt_init_wr(struct ubifs_info * c)18451e51764aSArtem Bityutskiy static int lpt_init_wr(struct ubifs_info *c)
18461e51764aSArtem Bityutskiy {
18471e51764aSArtem Bityutskiy int err, i;
18481e51764aSArtem Bityutskiy
184942bc47b3SKees Cook c->ltab_cmt = vmalloc(array_size(sizeof(struct ubifs_lpt_lprops),
185042bc47b3SKees Cook c->lpt_lebs));
18511e51764aSArtem Bityutskiy if (!c->ltab_cmt)
18521e51764aSArtem Bityutskiy return -ENOMEM;
18531e51764aSArtem Bityutskiy
18541e51764aSArtem Bityutskiy c->lpt_buf = vmalloc(c->leb_size);
18551e51764aSArtem Bityutskiy if (!c->lpt_buf)
18561e51764aSArtem Bityutskiy return -ENOMEM;
18571e51764aSArtem Bityutskiy
18581e51764aSArtem Bityutskiy if (c->big_lpt) {
18596da2ec56SKees Cook c->lsave = kmalloc_array(c->lsave_cnt, sizeof(int), GFP_NOFS);
18601e51764aSArtem Bityutskiy if (!c->lsave)
18611e51764aSArtem Bityutskiy return -ENOMEM;
18621e51764aSArtem Bityutskiy err = read_lsave(c);
18631e51764aSArtem Bityutskiy if (err)
18641e51764aSArtem Bityutskiy return err;
18651e51764aSArtem Bityutskiy }
18661e51764aSArtem Bityutskiy
18671e51764aSArtem Bityutskiy for (i = 0; i < c->lpt_lebs; i++)
18681e51764aSArtem Bityutskiy if (c->ltab[i].free == c->leb_size) {
18691e51764aSArtem Bityutskiy err = ubifs_leb_unmap(c, i + c->lpt_first);
18701e51764aSArtem Bityutskiy if (err)
18711e51764aSArtem Bityutskiy return err;
18721e51764aSArtem Bityutskiy }
18731e51764aSArtem Bityutskiy
18741e51764aSArtem Bityutskiy return 0;
18751e51764aSArtem Bityutskiy }
18761e51764aSArtem Bityutskiy
18771e51764aSArtem Bityutskiy /**
18781e51764aSArtem Bityutskiy * ubifs_lpt_init - initialize the LPT.
18791e51764aSArtem Bityutskiy * @c: UBIFS file-system description object
18801e51764aSArtem Bityutskiy * @rd: whether to initialize lpt for reading
18811e51764aSArtem Bityutskiy * @wr: whether to initialize lpt for writing
18821e51764aSArtem Bityutskiy *
18831e51764aSArtem Bityutskiy * For mounting 'rw', @rd and @wr are both true. For mounting 'ro', @rd is true
18841e51764aSArtem Bityutskiy * and @wr is false. For mounting from 'ro' to 'rw', @rd is false and @wr is
18851e51764aSArtem Bityutskiy * true.
18861e51764aSArtem Bityutskiy *
18871e51764aSArtem Bityutskiy * This function returns %0 on success and a negative error code on failure.
18881e51764aSArtem Bityutskiy */
ubifs_lpt_init(struct ubifs_info * c,int rd,int wr)18891e51764aSArtem Bityutskiy int ubifs_lpt_init(struct ubifs_info *c, int rd, int wr)
18901e51764aSArtem Bityutskiy {
18911e51764aSArtem Bityutskiy int err;
18921e51764aSArtem Bityutskiy
18931e51764aSArtem Bityutskiy if (rd) {
18941e51764aSArtem Bityutskiy err = lpt_init_rd(c);
18951e51764aSArtem Bityutskiy if (err)
189649942976SArtem Bityutskiy goto out_err;
18971e51764aSArtem Bityutskiy }
18981e51764aSArtem Bityutskiy
18991e51764aSArtem Bityutskiy if (wr) {
19001e51764aSArtem Bityutskiy err = lpt_init_wr(c);
19011e51764aSArtem Bityutskiy if (err)
190249942976SArtem Bityutskiy goto out_err;
19031e51764aSArtem Bityutskiy }
19041e51764aSArtem Bityutskiy
19051e51764aSArtem Bityutskiy return 0;
190649942976SArtem Bityutskiy
190749942976SArtem Bityutskiy out_err:
190811e3be0bSArtem Bityutskiy if (wr)
190911e3be0bSArtem Bityutskiy ubifs_lpt_free(c, 1);
191011e3be0bSArtem Bityutskiy if (rd)
191149942976SArtem Bityutskiy ubifs_lpt_free(c, 0);
191249942976SArtem Bityutskiy return err;
19131e51764aSArtem Bityutskiy }
19141e51764aSArtem Bityutskiy
19151e51764aSArtem Bityutskiy /**
19161e51764aSArtem Bityutskiy * struct lpt_scan_node - somewhere to put nodes while we scan LPT.
19171e51764aSArtem Bityutskiy * @nnode: where to keep a nnode
19181e51764aSArtem Bityutskiy * @pnode: where to keep a pnode
19191e51764aSArtem Bityutskiy * @cnode: where to keep a cnode
19201e51764aSArtem Bityutskiy * @in_tree: is the node in the tree in memory
19211e51764aSArtem Bityutskiy * @ptr.nnode: pointer to the nnode (if it is an nnode) which may be here or in
19221e51764aSArtem Bityutskiy * the tree
19231e51764aSArtem Bityutskiy * @ptr.pnode: ditto for pnode
19241e51764aSArtem Bityutskiy * @ptr.cnode: ditto for cnode
19251e51764aSArtem Bityutskiy */
19261e51764aSArtem Bityutskiy struct lpt_scan_node {
19271e51764aSArtem Bityutskiy union {
19281e51764aSArtem Bityutskiy struct ubifs_nnode nnode;
19291e51764aSArtem Bityutskiy struct ubifs_pnode pnode;
19301e51764aSArtem Bityutskiy struct ubifs_cnode cnode;
19311e51764aSArtem Bityutskiy };
19321e51764aSArtem Bityutskiy int in_tree;
19331e51764aSArtem Bityutskiy union {
19341e51764aSArtem Bityutskiy struct ubifs_nnode *nnode;
19351e51764aSArtem Bityutskiy struct ubifs_pnode *pnode;
19361e51764aSArtem Bityutskiy struct ubifs_cnode *cnode;
19371e51764aSArtem Bityutskiy } ptr;
19381e51764aSArtem Bityutskiy };
19391e51764aSArtem Bityutskiy
19401e51764aSArtem Bityutskiy /**
19411e51764aSArtem Bityutskiy * scan_get_nnode - for the scan, get a nnode from either the tree or flash.
19421e51764aSArtem Bityutskiy * @c: the UBIFS file-system description object
19431e51764aSArtem Bityutskiy * @path: where to put the nnode
19441e51764aSArtem Bityutskiy * @parent: parent of the nnode
19451e51764aSArtem Bityutskiy * @iip: index in parent of the nnode
19461e51764aSArtem Bityutskiy *
19471e51764aSArtem Bityutskiy * This function returns a pointer to the nnode on success or a negative error
19481e51764aSArtem Bityutskiy * code on failure.
19491e51764aSArtem Bityutskiy */
scan_get_nnode(struct ubifs_info * c,struct lpt_scan_node * path,struct ubifs_nnode * parent,int iip)19501e51764aSArtem Bityutskiy static struct ubifs_nnode *scan_get_nnode(struct ubifs_info *c,
19511e51764aSArtem Bityutskiy struct lpt_scan_node *path,
19521e51764aSArtem Bityutskiy struct ubifs_nnode *parent, int iip)
19531e51764aSArtem Bityutskiy {
19541e51764aSArtem Bityutskiy struct ubifs_nbranch *branch;
19551e51764aSArtem Bityutskiy struct ubifs_nnode *nnode;
19561e51764aSArtem Bityutskiy void *buf = c->lpt_nod_buf;
19571e51764aSArtem Bityutskiy int err;
19581e51764aSArtem Bityutskiy
19591e51764aSArtem Bityutskiy branch = &parent->nbranch[iip];
19601e51764aSArtem Bityutskiy nnode = branch->nnode;
19611e51764aSArtem Bityutskiy if (nnode) {
19621e51764aSArtem Bityutskiy path->in_tree = 1;
19631e51764aSArtem Bityutskiy path->ptr.nnode = nnode;
19641e51764aSArtem Bityutskiy return nnode;
19651e51764aSArtem Bityutskiy }
19661e51764aSArtem Bityutskiy nnode = &path->nnode;
19671e51764aSArtem Bityutskiy path->in_tree = 0;
19681e51764aSArtem Bityutskiy path->ptr.nnode = nnode;
19691e51764aSArtem Bityutskiy memset(nnode, 0, sizeof(struct ubifs_nnode));
19701e51764aSArtem Bityutskiy if (branch->lnum == 0) {
19711e51764aSArtem Bityutskiy /*
19721e51764aSArtem Bityutskiy * This nnode was not written which just means that the LEB
19731e51764aSArtem Bityutskiy * properties in the subtree below it describe empty LEBs. We
19741e51764aSArtem Bityutskiy * make the nnode as though we had read it, which in fact means
19751e51764aSArtem Bityutskiy * doing almost nothing.
19761e51764aSArtem Bityutskiy */
19771e51764aSArtem Bityutskiy if (c->big_lpt)
19781e51764aSArtem Bityutskiy nnode->num = calc_nnode_num_from_parent(c, parent, iip);
19791e51764aSArtem Bityutskiy } else {
1980d304820aSArtem Bityutskiy err = ubifs_leb_read(c, branch->lnum, buf, branch->offs,
1981d304820aSArtem Bityutskiy c->nnode_sz, 1);
19821e51764aSArtem Bityutskiy if (err)
19831e51764aSArtem Bityutskiy return ERR_PTR(err);
19842ba5f7aeSArtem Bityutskiy err = ubifs_unpack_nnode(c, buf, nnode);
19851e51764aSArtem Bityutskiy if (err)
19861e51764aSArtem Bityutskiy return ERR_PTR(err);
19871e51764aSArtem Bityutskiy }
19881e51764aSArtem Bityutskiy err = validate_nnode(c, nnode, parent, iip);
19891e51764aSArtem Bityutskiy if (err)
19901e51764aSArtem Bityutskiy return ERR_PTR(err);
19911e51764aSArtem Bityutskiy if (!c->big_lpt)
19921e51764aSArtem Bityutskiy nnode->num = calc_nnode_num_from_parent(c, parent, iip);
19931e51764aSArtem Bityutskiy nnode->level = parent->level - 1;
19941e51764aSArtem Bityutskiy nnode->parent = parent;
19951e51764aSArtem Bityutskiy nnode->iip = iip;
19961e51764aSArtem Bityutskiy return nnode;
19971e51764aSArtem Bityutskiy }
19981e51764aSArtem Bityutskiy
19991e51764aSArtem Bityutskiy /**
20001e51764aSArtem Bityutskiy * scan_get_pnode - for the scan, get a pnode from either the tree or flash.
20011e51764aSArtem Bityutskiy * @c: the UBIFS file-system description object
20021e51764aSArtem Bityutskiy * @path: where to put the pnode
20031e51764aSArtem Bityutskiy * @parent: parent of the pnode
20041e51764aSArtem Bityutskiy * @iip: index in parent of the pnode
20051e51764aSArtem Bityutskiy *
20061e51764aSArtem Bityutskiy * This function returns a pointer to the pnode on success or a negative error
20071e51764aSArtem Bityutskiy * code on failure.
20081e51764aSArtem Bityutskiy */
scan_get_pnode(struct ubifs_info * c,struct lpt_scan_node * path,struct ubifs_nnode * parent,int iip)20091e51764aSArtem Bityutskiy static struct ubifs_pnode *scan_get_pnode(struct ubifs_info *c,
20101e51764aSArtem Bityutskiy struct lpt_scan_node *path,
20111e51764aSArtem Bityutskiy struct ubifs_nnode *parent, int iip)
20121e51764aSArtem Bityutskiy {
20131e51764aSArtem Bityutskiy struct ubifs_nbranch *branch;
20141e51764aSArtem Bityutskiy struct ubifs_pnode *pnode;
20151e51764aSArtem Bityutskiy void *buf = c->lpt_nod_buf;
20161e51764aSArtem Bityutskiy int err;
20171e51764aSArtem Bityutskiy
20181e51764aSArtem Bityutskiy branch = &parent->nbranch[iip];
20191e51764aSArtem Bityutskiy pnode = branch->pnode;
20201e51764aSArtem Bityutskiy if (pnode) {
20211e51764aSArtem Bityutskiy path->in_tree = 1;
20221e51764aSArtem Bityutskiy path->ptr.pnode = pnode;
20231e51764aSArtem Bityutskiy return pnode;
20241e51764aSArtem Bityutskiy }
20251e51764aSArtem Bityutskiy pnode = &path->pnode;
20261e51764aSArtem Bityutskiy path->in_tree = 0;
20271e51764aSArtem Bityutskiy path->ptr.pnode = pnode;
20281e51764aSArtem Bityutskiy memset(pnode, 0, sizeof(struct ubifs_pnode));
20291e51764aSArtem Bityutskiy if (branch->lnum == 0) {
20301e51764aSArtem Bityutskiy /*
20311e51764aSArtem Bityutskiy * This pnode was not written which just means that the LEB
20321e51764aSArtem Bityutskiy * properties in it describe empty LEBs. We make the pnode as
20331e51764aSArtem Bityutskiy * though we had read it.
20341e51764aSArtem Bityutskiy */
20351e51764aSArtem Bityutskiy int i;
20361e51764aSArtem Bityutskiy
20371e51764aSArtem Bityutskiy if (c->big_lpt)
20381e51764aSArtem Bityutskiy pnode->num = calc_pnode_num_from_parent(c, parent, iip);
20391e51764aSArtem Bityutskiy for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
20401e51764aSArtem Bityutskiy struct ubifs_lprops * const lprops = &pnode->lprops[i];
20411e51764aSArtem Bityutskiy
20421e51764aSArtem Bityutskiy lprops->free = c->leb_size;
20431e51764aSArtem Bityutskiy lprops->flags = ubifs_categorize_lprops(c, lprops);
20441e51764aSArtem Bityutskiy }
20451e51764aSArtem Bityutskiy } else {
20466eb61d58SRichard Weinberger ubifs_assert(c, branch->lnum >= c->lpt_first &&
20471e51764aSArtem Bityutskiy branch->lnum <= c->lpt_last);
20486eb61d58SRichard Weinberger ubifs_assert(c, branch->offs >= 0 && branch->offs < c->leb_size);
2049d304820aSArtem Bityutskiy err = ubifs_leb_read(c, branch->lnum, buf, branch->offs,
2050d304820aSArtem Bityutskiy c->pnode_sz, 1);
20511e51764aSArtem Bityutskiy if (err)
20521e51764aSArtem Bityutskiy return ERR_PTR(err);
20531e51764aSArtem Bityutskiy err = unpack_pnode(c, buf, pnode);
20541e51764aSArtem Bityutskiy if (err)
20551e51764aSArtem Bityutskiy return ERR_PTR(err);
20561e51764aSArtem Bityutskiy }
20571e51764aSArtem Bityutskiy err = validate_pnode(c, pnode, parent, iip);
20581e51764aSArtem Bityutskiy if (err)
20591e51764aSArtem Bityutskiy return ERR_PTR(err);
20601e51764aSArtem Bityutskiy if (!c->big_lpt)
20611e51764aSArtem Bityutskiy pnode->num = calc_pnode_num_from_parent(c, parent, iip);
20621e51764aSArtem Bityutskiy pnode->parent = parent;
20631e51764aSArtem Bityutskiy pnode->iip = iip;
20641e51764aSArtem Bityutskiy set_pnode_lnum(c, pnode);
20651e51764aSArtem Bityutskiy return pnode;
20661e51764aSArtem Bityutskiy }
20671e51764aSArtem Bityutskiy
20681e51764aSArtem Bityutskiy /**
20691e51764aSArtem Bityutskiy * ubifs_lpt_scan_nolock - scan the LPT.
20701e51764aSArtem Bityutskiy * @c: the UBIFS file-system description object
20711e51764aSArtem Bityutskiy * @start_lnum: LEB number from which to start scanning
20721e51764aSArtem Bityutskiy * @end_lnum: LEB number at which to stop scanning
20731e51764aSArtem Bityutskiy * @scan_cb: callback function called for each lprops
20741e51764aSArtem Bityutskiy * @data: data to be passed to the callback function
20751e51764aSArtem Bityutskiy *
20761e51764aSArtem Bityutskiy * This function returns %0 on success and a negative error code on failure.
20771e51764aSArtem Bityutskiy */
ubifs_lpt_scan_nolock(struct ubifs_info * c,int start_lnum,int end_lnum,ubifs_lpt_scan_callback scan_cb,void * data)20781e51764aSArtem Bityutskiy int ubifs_lpt_scan_nolock(struct ubifs_info *c, int start_lnum, int end_lnum,
20791e51764aSArtem Bityutskiy ubifs_lpt_scan_callback scan_cb, void *data)
20801e51764aSArtem Bityutskiy {
20811e51764aSArtem Bityutskiy int err = 0, i, h, iip, shft;
20821e51764aSArtem Bityutskiy struct ubifs_nnode *nnode;
20831e51764aSArtem Bityutskiy struct ubifs_pnode *pnode;
20841e51764aSArtem Bityutskiy struct lpt_scan_node *path;
20851e51764aSArtem Bityutskiy
20861e51764aSArtem Bityutskiy if (start_lnum == -1) {
20871e51764aSArtem Bityutskiy start_lnum = end_lnum + 1;
20881e51764aSArtem Bityutskiy if (start_lnum >= c->leb_cnt)
20891e51764aSArtem Bityutskiy start_lnum = c->main_first;
20901e51764aSArtem Bityutskiy }
20911e51764aSArtem Bityutskiy
20926eb61d58SRichard Weinberger ubifs_assert(c, start_lnum >= c->main_first && start_lnum < c->leb_cnt);
20936eb61d58SRichard Weinberger ubifs_assert(c, end_lnum >= c->main_first && end_lnum < c->leb_cnt);
20941e51764aSArtem Bityutskiy
20951e51764aSArtem Bityutskiy if (!c->nroot) {
20961e51764aSArtem Bityutskiy err = ubifs_read_nnode(c, NULL, 0);
20971e51764aSArtem Bityutskiy if (err)
20981e51764aSArtem Bityutskiy return err;
20991e51764aSArtem Bityutskiy }
21001e51764aSArtem Bityutskiy
21016da2ec56SKees Cook path = kmalloc_array(c->lpt_hght + 1, sizeof(struct lpt_scan_node),
21021e51764aSArtem Bityutskiy GFP_NOFS);
21031e51764aSArtem Bityutskiy if (!path)
21041e51764aSArtem Bityutskiy return -ENOMEM;
21051e51764aSArtem Bityutskiy
21061e51764aSArtem Bityutskiy path[0].ptr.nnode = c->nroot;
21071e51764aSArtem Bityutskiy path[0].in_tree = 1;
21081e51764aSArtem Bityutskiy again:
21091e51764aSArtem Bityutskiy /* Descend to the pnode containing start_lnum */
21101e51764aSArtem Bityutskiy nnode = c->nroot;
21111e51764aSArtem Bityutskiy i = start_lnum - c->main_first;
21121e51764aSArtem Bityutskiy shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT;
21131e51764aSArtem Bityutskiy for (h = 1; h < c->lpt_hght; h++) {
21141e51764aSArtem Bityutskiy iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
21151e51764aSArtem Bityutskiy shft -= UBIFS_LPT_FANOUT_SHIFT;
21161e51764aSArtem Bityutskiy nnode = scan_get_nnode(c, path + h, nnode, iip);
21171e51764aSArtem Bityutskiy if (IS_ERR(nnode)) {
21181e51764aSArtem Bityutskiy err = PTR_ERR(nnode);
21191e51764aSArtem Bityutskiy goto out;
21201e51764aSArtem Bityutskiy }
21211e51764aSArtem Bityutskiy }
21221e51764aSArtem Bityutskiy iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
21231e51764aSArtem Bityutskiy pnode = scan_get_pnode(c, path + h, nnode, iip);
21241e51764aSArtem Bityutskiy if (IS_ERR(pnode)) {
21251e51764aSArtem Bityutskiy err = PTR_ERR(pnode);
21261e51764aSArtem Bityutskiy goto out;
21271e51764aSArtem Bityutskiy }
21281e51764aSArtem Bityutskiy iip = (i & (UBIFS_LPT_FANOUT - 1));
21291e51764aSArtem Bityutskiy
21301e51764aSArtem Bityutskiy /* Loop for each lprops */
21311e51764aSArtem Bityutskiy while (1) {
21321e51764aSArtem Bityutskiy struct ubifs_lprops *lprops = &pnode->lprops[iip];
21331e51764aSArtem Bityutskiy int ret, lnum = lprops->lnum;
21341e51764aSArtem Bityutskiy
21351e51764aSArtem Bityutskiy ret = scan_cb(c, lprops, path[h].in_tree, data);
21361e51764aSArtem Bityutskiy if (ret < 0) {
21371e51764aSArtem Bityutskiy err = ret;
21381e51764aSArtem Bityutskiy goto out;
21391e51764aSArtem Bityutskiy }
21401e51764aSArtem Bityutskiy if (ret & LPT_SCAN_ADD) {
21411e51764aSArtem Bityutskiy /* Add all the nodes in path to the tree in memory */
21421e51764aSArtem Bityutskiy for (h = 1; h < c->lpt_hght; h++) {
21431e51764aSArtem Bityutskiy const size_t sz = sizeof(struct ubifs_nnode);
21441e51764aSArtem Bityutskiy struct ubifs_nnode *parent;
21451e51764aSArtem Bityutskiy
21461e51764aSArtem Bityutskiy if (path[h].in_tree)
21471e51764aSArtem Bityutskiy continue;
2148eaecf43aSThomas Meyer nnode = kmemdup(&path[h].nnode, sz, GFP_NOFS);
21491e51764aSArtem Bityutskiy if (!nnode) {
21501e51764aSArtem Bityutskiy err = -ENOMEM;
21511e51764aSArtem Bityutskiy goto out;
21521e51764aSArtem Bityutskiy }
21531e51764aSArtem Bityutskiy parent = nnode->parent;
21541e51764aSArtem Bityutskiy parent->nbranch[nnode->iip].nnode = nnode;
21551e51764aSArtem Bityutskiy path[h].ptr.nnode = nnode;
21561e51764aSArtem Bityutskiy path[h].in_tree = 1;
21571e51764aSArtem Bityutskiy path[h + 1].cnode.parent = nnode;
21581e51764aSArtem Bityutskiy }
21591e51764aSArtem Bityutskiy if (path[h].in_tree)
21601e51764aSArtem Bityutskiy ubifs_ensure_cat(c, lprops);
21611e51764aSArtem Bityutskiy else {
21621e51764aSArtem Bityutskiy const size_t sz = sizeof(struct ubifs_pnode);
21631e51764aSArtem Bityutskiy struct ubifs_nnode *parent;
21641e51764aSArtem Bityutskiy
2165eaecf43aSThomas Meyer pnode = kmemdup(&path[h].pnode, sz, GFP_NOFS);
21661e51764aSArtem Bityutskiy if (!pnode) {
21671e51764aSArtem Bityutskiy err = -ENOMEM;
21681e51764aSArtem Bityutskiy goto out;
21691e51764aSArtem Bityutskiy }
21701e51764aSArtem Bityutskiy parent = pnode->parent;
21711e51764aSArtem Bityutskiy parent->nbranch[pnode->iip].pnode = pnode;
21721e51764aSArtem Bityutskiy path[h].ptr.pnode = pnode;
21731e51764aSArtem Bityutskiy path[h].in_tree = 1;
21741e51764aSArtem Bityutskiy update_cats(c, pnode);
21751e51764aSArtem Bityutskiy c->pnodes_have += 1;
21761e51764aSArtem Bityutskiy }
21771e51764aSArtem Bityutskiy err = dbg_check_lpt_nodes(c, (struct ubifs_cnode *)
21781e51764aSArtem Bityutskiy c->nroot, 0, 0);
21791e51764aSArtem Bityutskiy if (err)
21801e51764aSArtem Bityutskiy goto out;
21811e51764aSArtem Bityutskiy err = dbg_check_cats(c);
21821e51764aSArtem Bityutskiy if (err)
21831e51764aSArtem Bityutskiy goto out;
21841e51764aSArtem Bityutskiy }
21851e51764aSArtem Bityutskiy if (ret & LPT_SCAN_STOP) {
21861e51764aSArtem Bityutskiy err = 0;
21871e51764aSArtem Bityutskiy break;
21881e51764aSArtem Bityutskiy }
21891e51764aSArtem Bityutskiy /* Get the next lprops */
21901e51764aSArtem Bityutskiy if (lnum == end_lnum) {
21911e51764aSArtem Bityutskiy /*
21921e51764aSArtem Bityutskiy * We got to the end without finding what we were
21931e51764aSArtem Bityutskiy * looking for
21941e51764aSArtem Bityutskiy */
21951e51764aSArtem Bityutskiy err = -ENOSPC;
21961e51764aSArtem Bityutskiy goto out;
21971e51764aSArtem Bityutskiy }
21981e51764aSArtem Bityutskiy if (lnum + 1 >= c->leb_cnt) {
21991e51764aSArtem Bityutskiy /* Wrap-around to the beginning */
22001e51764aSArtem Bityutskiy start_lnum = c->main_first;
22011e51764aSArtem Bityutskiy goto again;
22021e51764aSArtem Bityutskiy }
22031e51764aSArtem Bityutskiy if (iip + 1 < UBIFS_LPT_FANOUT) {
22041e51764aSArtem Bityutskiy /* Next lprops is in the same pnode */
22051e51764aSArtem Bityutskiy iip += 1;
22061e51764aSArtem Bityutskiy continue;
22071e51764aSArtem Bityutskiy }
22081e51764aSArtem Bityutskiy /* We need to get the next pnode. Go up until we can go right */
22091e51764aSArtem Bityutskiy iip = pnode->iip;
22101e51764aSArtem Bityutskiy while (1) {
22111e51764aSArtem Bityutskiy h -= 1;
22126eb61d58SRichard Weinberger ubifs_assert(c, h >= 0);
22131e51764aSArtem Bityutskiy nnode = path[h].ptr.nnode;
22141e51764aSArtem Bityutskiy if (iip + 1 < UBIFS_LPT_FANOUT)
22151e51764aSArtem Bityutskiy break;
22161e51764aSArtem Bityutskiy iip = nnode->iip;
22171e51764aSArtem Bityutskiy }
22181e51764aSArtem Bityutskiy /* Go right */
22191e51764aSArtem Bityutskiy iip += 1;
22201e51764aSArtem Bityutskiy /* Descend to the pnode */
22211e51764aSArtem Bityutskiy h += 1;
22221e51764aSArtem Bityutskiy for (; h < c->lpt_hght; h++) {
22231e51764aSArtem Bityutskiy nnode = scan_get_nnode(c, path + h, nnode, iip);
22241e51764aSArtem Bityutskiy if (IS_ERR(nnode)) {
22251e51764aSArtem Bityutskiy err = PTR_ERR(nnode);
22261e51764aSArtem Bityutskiy goto out;
22271e51764aSArtem Bityutskiy }
22281e51764aSArtem Bityutskiy iip = 0;
22291e51764aSArtem Bityutskiy }
22301e51764aSArtem Bityutskiy pnode = scan_get_pnode(c, path + h, nnode, iip);
22311e51764aSArtem Bityutskiy if (IS_ERR(pnode)) {
22321e51764aSArtem Bityutskiy err = PTR_ERR(pnode);
22331e51764aSArtem Bityutskiy goto out;
22341e51764aSArtem Bityutskiy }
22351e51764aSArtem Bityutskiy iip = 0;
22361e51764aSArtem Bityutskiy }
22371e51764aSArtem Bityutskiy out:
22381e51764aSArtem Bityutskiy kfree(path);
22391e51764aSArtem Bityutskiy return err;
22401e51764aSArtem Bityutskiy }
22411e51764aSArtem Bityutskiy
22421e51764aSArtem Bityutskiy /**
22431e51764aSArtem Bityutskiy * dbg_chk_pnode - check a pnode.
22441e51764aSArtem Bityutskiy * @c: the UBIFS file-system description object
22451e51764aSArtem Bityutskiy * @pnode: pnode to check
22461e51764aSArtem Bityutskiy * @col: pnode column
22471e51764aSArtem Bityutskiy *
22481e51764aSArtem Bityutskiy * This function returns %0 on success and a negative error code on failure.
22491e51764aSArtem Bityutskiy */
dbg_chk_pnode(struct ubifs_info * c,struct ubifs_pnode * pnode,int col)22501e51764aSArtem Bityutskiy static int dbg_chk_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
22511e51764aSArtem Bityutskiy int col)
22521e51764aSArtem Bityutskiy {
22531e51764aSArtem Bityutskiy int i;
22541e51764aSArtem Bityutskiy
22551e51764aSArtem Bityutskiy if (pnode->num != col) {
2256235c362bSSheng Yong ubifs_err(c, "pnode num %d expected %d parent num %d iip %d",
22571e51764aSArtem Bityutskiy pnode->num, col, pnode->parent->num, pnode->iip);
22581e51764aSArtem Bityutskiy return -EINVAL;
22591e51764aSArtem Bityutskiy }
22601e51764aSArtem Bityutskiy for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
22611e51764aSArtem Bityutskiy struct ubifs_lprops *lp, *lprops = &pnode->lprops[i];
22621e51764aSArtem Bityutskiy int lnum = (pnode->num << UBIFS_LPT_FANOUT_SHIFT) + i +
22631e51764aSArtem Bityutskiy c->main_first;
22641e51764aSArtem Bityutskiy int found, cat = lprops->flags & LPROPS_CAT_MASK;
22651e51764aSArtem Bityutskiy struct ubifs_lpt_heap *heap;
22661e51764aSArtem Bityutskiy struct list_head *list = NULL;
22671e51764aSArtem Bityutskiy
22681e51764aSArtem Bityutskiy if (lnum >= c->leb_cnt)
22691e51764aSArtem Bityutskiy continue;
22701e51764aSArtem Bityutskiy if (lprops->lnum != lnum) {
2271235c362bSSheng Yong ubifs_err(c, "bad LEB number %d expected %d",
22721e51764aSArtem Bityutskiy lprops->lnum, lnum);
22731e51764aSArtem Bityutskiy return -EINVAL;
22741e51764aSArtem Bityutskiy }
22751e51764aSArtem Bityutskiy if (lprops->flags & LPROPS_TAKEN) {
22761e51764aSArtem Bityutskiy if (cat != LPROPS_UNCAT) {
2277235c362bSSheng Yong ubifs_err(c, "LEB %d taken but not uncat %d",
22781e51764aSArtem Bityutskiy lprops->lnum, cat);
22791e51764aSArtem Bityutskiy return -EINVAL;
22801e51764aSArtem Bityutskiy }
22811e51764aSArtem Bityutskiy continue;
22821e51764aSArtem Bityutskiy }
22831e51764aSArtem Bityutskiy if (lprops->flags & LPROPS_INDEX) {
22841e51764aSArtem Bityutskiy switch (cat) {
22851e51764aSArtem Bityutskiy case LPROPS_UNCAT:
22861e51764aSArtem Bityutskiy case LPROPS_DIRTY_IDX:
22871e51764aSArtem Bityutskiy case LPROPS_FRDI_IDX:
22881e51764aSArtem Bityutskiy break;
22891e51764aSArtem Bityutskiy default:
2290235c362bSSheng Yong ubifs_err(c, "LEB %d index but cat %d",
22911e51764aSArtem Bityutskiy lprops->lnum, cat);
22921e51764aSArtem Bityutskiy return -EINVAL;
22931e51764aSArtem Bityutskiy }
22941e51764aSArtem Bityutskiy } else {
22951e51764aSArtem Bityutskiy switch (cat) {
22961e51764aSArtem Bityutskiy case LPROPS_UNCAT:
22971e51764aSArtem Bityutskiy case LPROPS_DIRTY:
22981e51764aSArtem Bityutskiy case LPROPS_FREE:
22991e51764aSArtem Bityutskiy case LPROPS_EMPTY:
23001e51764aSArtem Bityutskiy case LPROPS_FREEABLE:
23011e51764aSArtem Bityutskiy break;
23021e51764aSArtem Bityutskiy default:
2303235c362bSSheng Yong ubifs_err(c, "LEB %d not index but cat %d",
23041e51764aSArtem Bityutskiy lprops->lnum, cat);
23051e51764aSArtem Bityutskiy return -EINVAL;
23061e51764aSArtem Bityutskiy }
23071e51764aSArtem Bityutskiy }
23081e51764aSArtem Bityutskiy switch (cat) {
23091e51764aSArtem Bityutskiy case LPROPS_UNCAT:
23101e51764aSArtem Bityutskiy list = &c->uncat_list;
23111e51764aSArtem Bityutskiy break;
23121e51764aSArtem Bityutskiy case LPROPS_EMPTY:
23131e51764aSArtem Bityutskiy list = &c->empty_list;
23141e51764aSArtem Bityutskiy break;
23151e51764aSArtem Bityutskiy case LPROPS_FREEABLE:
23161e51764aSArtem Bityutskiy list = &c->freeable_list;
23171e51764aSArtem Bityutskiy break;
23181e51764aSArtem Bityutskiy case LPROPS_FRDI_IDX:
23191e51764aSArtem Bityutskiy list = &c->frdi_idx_list;
23201e51764aSArtem Bityutskiy break;
23211e51764aSArtem Bityutskiy }
23221e51764aSArtem Bityutskiy found = 0;
23231e51764aSArtem Bityutskiy switch (cat) {
23241e51764aSArtem Bityutskiy case LPROPS_DIRTY:
23251e51764aSArtem Bityutskiy case LPROPS_DIRTY_IDX:
23261e51764aSArtem Bityutskiy case LPROPS_FREE:
23271e51764aSArtem Bityutskiy heap = &c->lpt_heap[cat - 1];
23281e51764aSArtem Bityutskiy if (lprops->hpos < heap->cnt &&
23291e51764aSArtem Bityutskiy heap->arr[lprops->hpos] == lprops)
23301e51764aSArtem Bityutskiy found = 1;
23311e51764aSArtem Bityutskiy break;
23321e51764aSArtem Bityutskiy case LPROPS_UNCAT:
23331e51764aSArtem Bityutskiy case LPROPS_EMPTY:
23341e51764aSArtem Bityutskiy case LPROPS_FREEABLE:
23351e51764aSArtem Bityutskiy case LPROPS_FRDI_IDX:
23361e51764aSArtem Bityutskiy list_for_each_entry(lp, list, list)
23371e51764aSArtem Bityutskiy if (lprops == lp) {
23381e51764aSArtem Bityutskiy found = 1;
23391e51764aSArtem Bityutskiy break;
23401e51764aSArtem Bityutskiy }
23411e51764aSArtem Bityutskiy break;
23421e51764aSArtem Bityutskiy }
23431e51764aSArtem Bityutskiy if (!found) {
2344235c362bSSheng Yong ubifs_err(c, "LEB %d cat %d not found in cat heap/list",
23451e51764aSArtem Bityutskiy lprops->lnum, cat);
23461e51764aSArtem Bityutskiy return -EINVAL;
23471e51764aSArtem Bityutskiy }
23481e51764aSArtem Bityutskiy switch (cat) {
23491e51764aSArtem Bityutskiy case LPROPS_EMPTY:
23501e51764aSArtem Bityutskiy if (lprops->free != c->leb_size) {
2351235c362bSSheng Yong ubifs_err(c, "LEB %d cat %d free %d dirty %d",
23521e51764aSArtem Bityutskiy lprops->lnum, cat, lprops->free,
23531e51764aSArtem Bityutskiy lprops->dirty);
23541e51764aSArtem Bityutskiy return -EINVAL;
23551e51764aSArtem Bityutskiy }
2356ce6ebdb8Shujianyang break;
23571e51764aSArtem Bityutskiy case LPROPS_FREEABLE:
23581e51764aSArtem Bityutskiy case LPROPS_FRDI_IDX:
23591e51764aSArtem Bityutskiy if (lprops->free + lprops->dirty != c->leb_size) {
2360235c362bSSheng Yong ubifs_err(c, "LEB %d cat %d free %d dirty %d",
23611e51764aSArtem Bityutskiy lprops->lnum, cat, lprops->free,
23621e51764aSArtem Bityutskiy lprops->dirty);
23631e51764aSArtem Bityutskiy return -EINVAL;
23641e51764aSArtem Bityutskiy }
2365ce6ebdb8Shujianyang break;
23661e51764aSArtem Bityutskiy }
23671e51764aSArtem Bityutskiy }
23681e51764aSArtem Bityutskiy return 0;
23691e51764aSArtem Bityutskiy }
23701e51764aSArtem Bityutskiy
23711e51764aSArtem Bityutskiy /**
23721e51764aSArtem Bityutskiy * dbg_check_lpt_nodes - check nnodes and pnodes.
23731e51764aSArtem Bityutskiy * @c: the UBIFS file-system description object
23741e51764aSArtem Bityutskiy * @cnode: next cnode (nnode or pnode) to check
23751e51764aSArtem Bityutskiy * @row: row of cnode (root is zero)
23761e51764aSArtem Bityutskiy * @col: column of cnode (leftmost is zero)
23771e51764aSArtem Bityutskiy *
23781e51764aSArtem Bityutskiy * This function returns %0 on success and a negative error code on failure.
23791e51764aSArtem Bityutskiy */
dbg_check_lpt_nodes(struct ubifs_info * c,struct ubifs_cnode * cnode,int row,int col)23801e51764aSArtem Bityutskiy int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode,
23811e51764aSArtem Bityutskiy int row, int col)
23821e51764aSArtem Bityutskiy {
23831e51764aSArtem Bityutskiy struct ubifs_nnode *nnode, *nn;
23841e51764aSArtem Bityutskiy struct ubifs_cnode *cn;
23851e51764aSArtem Bityutskiy int num, iip = 0, err;
23861e51764aSArtem Bityutskiy
23872b1844a8SArtem Bityutskiy if (!dbg_is_chk_lprops(c))
23881e51764aSArtem Bityutskiy return 0;
23891e51764aSArtem Bityutskiy
23901e51764aSArtem Bityutskiy while (cnode) {
23916eb61d58SRichard Weinberger ubifs_assert(c, row >= 0);
23921e51764aSArtem Bityutskiy nnode = cnode->parent;
23931e51764aSArtem Bityutskiy if (cnode->level) {
23941e51764aSArtem Bityutskiy /* cnode is a nnode */
23951e51764aSArtem Bityutskiy num = calc_nnode_num(row, col);
23961e51764aSArtem Bityutskiy if (cnode->num != num) {
2397235c362bSSheng Yong ubifs_err(c, "nnode num %d expected %d parent num %d iip %d",
2398a6aae4ddSArtem Bityutskiy cnode->num, num,
23991e51764aSArtem Bityutskiy (nnode ? nnode->num : 0), cnode->iip);
24001e51764aSArtem Bityutskiy return -EINVAL;
24011e51764aSArtem Bityutskiy }
24021e51764aSArtem Bityutskiy nn = (struct ubifs_nnode *)cnode;
24031e51764aSArtem Bityutskiy while (iip < UBIFS_LPT_FANOUT) {
24041e51764aSArtem Bityutskiy cn = nn->nbranch[iip].cnode;
24051e51764aSArtem Bityutskiy if (cn) {
24061e51764aSArtem Bityutskiy /* Go down */
24071e51764aSArtem Bityutskiy row += 1;
24081e51764aSArtem Bityutskiy col <<= UBIFS_LPT_FANOUT_SHIFT;
24091e51764aSArtem Bityutskiy col += iip;
24101e51764aSArtem Bityutskiy iip = 0;
24111e51764aSArtem Bityutskiy cnode = cn;
24121e51764aSArtem Bityutskiy break;
24131e51764aSArtem Bityutskiy }
24141e51764aSArtem Bityutskiy /* Go right */
24151e51764aSArtem Bityutskiy iip += 1;
24161e51764aSArtem Bityutskiy }
24171e51764aSArtem Bityutskiy if (iip < UBIFS_LPT_FANOUT)
24181e51764aSArtem Bityutskiy continue;
24191e51764aSArtem Bityutskiy } else {
24201e51764aSArtem Bityutskiy struct ubifs_pnode *pnode;
24211e51764aSArtem Bityutskiy
24221e51764aSArtem Bityutskiy /* cnode is a pnode */
24231e51764aSArtem Bityutskiy pnode = (struct ubifs_pnode *)cnode;
24241e51764aSArtem Bityutskiy err = dbg_chk_pnode(c, pnode, col);
24251e51764aSArtem Bityutskiy if (err)
24261e51764aSArtem Bityutskiy return err;
24271e51764aSArtem Bityutskiy }
24281e51764aSArtem Bityutskiy /* Go up and to the right */
24291e51764aSArtem Bityutskiy row -= 1;
24301e51764aSArtem Bityutskiy col >>= UBIFS_LPT_FANOUT_SHIFT;
24311e51764aSArtem Bityutskiy iip = cnode->iip + 1;
24321e51764aSArtem Bityutskiy cnode = (struct ubifs_cnode *)nnode;
24331e51764aSArtem Bityutskiy }
24341e51764aSArtem Bityutskiy return 0;
24351e51764aSArtem Bityutskiy }
2436