xref: /openbmc/linux/fs/ubifs/master.c (revision 762f99f4f3cb41a775b5157dd761217beba65873)
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: Artem Bityutskiy (Битюцкий Артём)
81e51764aSArtem Bityutskiy  *          Adrian Hunter
91e51764aSArtem Bityutskiy  */
101e51764aSArtem Bityutskiy 
111e51764aSArtem Bityutskiy /* This file implements reading and writing the master node */
121e51764aSArtem Bityutskiy 
131e51764aSArtem Bityutskiy #include "ubifs.h"
141e51764aSArtem Bityutskiy 
151e51764aSArtem Bityutskiy /**
16625700ccSSascha Hauer  * ubifs_compare_master_node - compare two UBIFS master nodes
17625700ccSSascha Hauer  * @c: UBIFS file-system description object
18625700ccSSascha Hauer  * @m1: the first node
19625700ccSSascha Hauer  * @m2: the second node
20625700ccSSascha Hauer  *
21625700ccSSascha Hauer  * This function compares two UBIFS master nodes. Returns 0 if they are equal
22625700ccSSascha Hauer  * and nonzero if not.
23625700ccSSascha Hauer  */
ubifs_compare_master_node(struct ubifs_info * c,void * m1,void * m2)24625700ccSSascha Hauer int ubifs_compare_master_node(struct ubifs_info *c, void *m1, void *m2)
25625700ccSSascha Hauer {
26625700ccSSascha Hauer 	int ret;
27625700ccSSascha Hauer 	int behind;
28625700ccSSascha Hauer 	int hmac_offs = offsetof(struct ubifs_mst_node, hmac);
29625700ccSSascha Hauer 
30625700ccSSascha Hauer 	/*
31625700ccSSascha Hauer 	 * Do not compare the common node header since the sequence number and
32625700ccSSascha Hauer 	 * hence the CRC are different.
33625700ccSSascha Hauer 	 */
34625700ccSSascha Hauer 	ret = memcmp(m1 + UBIFS_CH_SZ, m2 + UBIFS_CH_SZ,
35625700ccSSascha Hauer 		     hmac_offs - UBIFS_CH_SZ);
36625700ccSSascha Hauer 	if (ret)
37625700ccSSascha Hauer 		return ret;
38625700ccSSascha Hauer 
39625700ccSSascha Hauer 	/*
40625700ccSSascha Hauer 	 * Do not compare the embedded HMAC as well which also must be different
41625700ccSSascha Hauer 	 * due to the different common node header.
42625700ccSSascha Hauer 	 */
43625700ccSSascha Hauer 	behind = hmac_offs + UBIFS_MAX_HMAC_LEN;
44625700ccSSascha Hauer 
45625700ccSSascha Hauer 	if (UBIFS_MST_NODE_SZ > behind)
46625700ccSSascha Hauer 		return memcmp(m1 + behind, m2 + behind, UBIFS_MST_NODE_SZ - behind);
47625700ccSSascha Hauer 
48625700ccSSascha Hauer 	return 0;
49625700ccSSascha Hauer }
50625700ccSSascha Hauer 
51817aa094SSascha Hauer /* mst_node_check_hash - Check hash of a master node
52817aa094SSascha Hauer  * @c: UBIFS file-system description object
53817aa094SSascha Hauer  * @mst: The master node
54817aa094SSascha Hauer  * @expected: The expected hash of the master node
55817aa094SSascha Hauer  *
56817aa094SSascha Hauer  * This checks the hash of a master node against a given expected hash.
57817aa094SSascha Hauer  * Note that we have two master nodes on a UBIFS image which have different
58817aa094SSascha Hauer  * sequence numbers and consequently different CRCs. To be able to match
59817aa094SSascha Hauer  * both master nodes we exclude the common node header containing the sequence
60817aa094SSascha Hauer  * number and CRC from the hash.
61817aa094SSascha Hauer  *
62817aa094SSascha Hauer  * Returns 0 if the hashes are equal, a negative error code otherwise.
63817aa094SSascha Hauer  */
mst_node_check_hash(const struct ubifs_info * c,const struct ubifs_mst_node * mst,const u8 * expected)64817aa094SSascha Hauer static int mst_node_check_hash(const struct ubifs_info *c,
65817aa094SSascha Hauer 			       const struct ubifs_mst_node *mst,
66817aa094SSascha Hauer 			       const u8 *expected)
67817aa094SSascha Hauer {
68817aa094SSascha Hauer 	u8 calc[UBIFS_MAX_HASH_LEN];
69817aa094SSascha Hauer 	const void *node = mst;
70817aa094SSascha Hauer 
71f80df385SEric Biggers 	crypto_shash_tfm_digest(c->hash_tfm, node + sizeof(struct ubifs_ch),
72f80df385SEric Biggers 				UBIFS_MST_NODE_SZ - sizeof(struct ubifs_ch),
73f80df385SEric Biggers 				calc);
74817aa094SSascha Hauer 
75817aa094SSascha Hauer 	if (ubifs_check_hash(c, expected, calc))
76817aa094SSascha Hauer 		return -EPERM;
77817aa094SSascha Hauer 
78817aa094SSascha Hauer 	return 0;
79817aa094SSascha Hauer }
80817aa094SSascha Hauer 
81625700ccSSascha Hauer /**
821e51764aSArtem Bityutskiy  * scan_for_master - search the valid master node.
831e51764aSArtem Bityutskiy  * @c: UBIFS file-system description object
841e51764aSArtem Bityutskiy  *
851e51764aSArtem Bityutskiy  * This function scans the master node LEBs and search for the latest master
860dcd18e4SArtem Bityutskiy  * node. Returns zero in case of success, %-EUCLEAN if there master area is
870dcd18e4SArtem Bityutskiy  * corrupted and requires recovery, and a negative error code in case of
881e51764aSArtem Bityutskiy  * failure.
891e51764aSArtem Bityutskiy  */
scan_for_master(struct ubifs_info * c)901e51764aSArtem Bityutskiy static int scan_for_master(struct ubifs_info *c)
911e51764aSArtem Bityutskiy {
921e51764aSArtem Bityutskiy 	struct ubifs_scan_leb *sleb;
931e51764aSArtem Bityutskiy 	struct ubifs_scan_node *snod;
94625700ccSSascha Hauer 	int lnum, offs = 0, nodes_cnt, err;
951e51764aSArtem Bityutskiy 
961e51764aSArtem Bityutskiy 	lnum = UBIFS_MST_LNUM;
971e51764aSArtem Bityutskiy 
98348709baSArtem Bityutskiy 	sleb = ubifs_scan(c, lnum, 0, c->sbuf, 1);
991e51764aSArtem Bityutskiy 	if (IS_ERR(sleb))
1001e51764aSArtem Bityutskiy 		return PTR_ERR(sleb);
1011e51764aSArtem Bityutskiy 	nodes_cnt = sleb->nodes_cnt;
1021e51764aSArtem Bityutskiy 	if (nodes_cnt > 0) {
1031e51764aSArtem Bityutskiy 		snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node,
1041e51764aSArtem Bityutskiy 				  list);
1051e51764aSArtem Bityutskiy 		if (snod->type != UBIFS_MST_NODE)
1060dcd18e4SArtem Bityutskiy 			goto out_dump;
1071e51764aSArtem Bityutskiy 		memcpy(c->mst_node, snod->node, snod->len);
1081e51764aSArtem Bityutskiy 		offs = snod->offs;
1091e51764aSArtem Bityutskiy 	}
1101e51764aSArtem Bityutskiy 	ubifs_scan_destroy(sleb);
1111e51764aSArtem Bityutskiy 
1121e51764aSArtem Bityutskiy 	lnum += 1;
1131e51764aSArtem Bityutskiy 
114348709baSArtem Bityutskiy 	sleb = ubifs_scan(c, lnum, 0, c->sbuf, 1);
1151e51764aSArtem Bityutskiy 	if (IS_ERR(sleb))
1161e51764aSArtem Bityutskiy 		return PTR_ERR(sleb);
1171e51764aSArtem Bityutskiy 	if (sleb->nodes_cnt != nodes_cnt)
1181e51764aSArtem Bityutskiy 		goto out;
1191e51764aSArtem Bityutskiy 	if (!sleb->nodes_cnt)
1201e51764aSArtem Bityutskiy 		goto out;
1211e51764aSArtem Bityutskiy 	snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node, list);
1221e51764aSArtem Bityutskiy 	if (snod->type != UBIFS_MST_NODE)
1230dcd18e4SArtem Bityutskiy 		goto out_dump;
1241e51764aSArtem Bityutskiy 	if (snod->offs != offs)
1251e51764aSArtem Bityutskiy 		goto out;
126625700ccSSascha Hauer 	if (ubifs_compare_master_node(c, c->mst_node, snod->node))
1271e51764aSArtem Bityutskiy 		goto out;
128625700ccSSascha Hauer 
1291e51764aSArtem Bityutskiy 	c->mst_offs = offs;
1301e51764aSArtem Bityutskiy 	ubifs_scan_destroy(sleb);
131625700ccSSascha Hauer 
132625700ccSSascha Hauer 	if (!ubifs_authenticated(c))
133625700ccSSascha Hauer 		return 0;
134625700ccSSascha Hauer 
135817aa094SSascha Hauer 	if (ubifs_hmac_zero(c, c->mst_node->hmac)) {
136817aa094SSascha Hauer 		err = mst_node_check_hash(c, c->mst_node,
137817aa094SSascha Hauer 					  c->sup_node->hash_mst);
138817aa094SSascha Hauer 		if (err)
139817aa094SSascha Hauer 			ubifs_err(c, "Failed to verify master node hash");
140817aa094SSascha Hauer 	} else {
141625700ccSSascha Hauer 		err = ubifs_node_verify_hmac(c, c->mst_node,
142625700ccSSascha Hauer 					sizeof(struct ubifs_mst_node),
143625700ccSSascha Hauer 					offsetof(struct ubifs_mst_node, hmac));
144817aa094SSascha Hauer 		if (err)
145625700ccSSascha Hauer 			ubifs_err(c, "Failed to verify master node HMAC");
146625700ccSSascha Hauer 	}
147625700ccSSascha Hauer 
148817aa094SSascha Hauer 	if (err)
149817aa094SSascha Hauer 		return -EPERM;
150817aa094SSascha Hauer 
1511e51764aSArtem Bityutskiy 	return 0;
1521e51764aSArtem Bityutskiy 
1531e51764aSArtem Bityutskiy out:
1541e51764aSArtem Bityutskiy 	ubifs_scan_destroy(sleb);
1550dcd18e4SArtem Bityutskiy 	return -EUCLEAN;
1560dcd18e4SArtem Bityutskiy 
1570dcd18e4SArtem Bityutskiy out_dump:
158235c362bSSheng Yong 	ubifs_err(c, "unexpected node type %d master LEB %d:%d",
1590dcd18e4SArtem Bityutskiy 		  snod->type, lnum, snod->offs);
1600dcd18e4SArtem Bityutskiy 	ubifs_scan_destroy(sleb);
1611e51764aSArtem Bityutskiy 	return -EINVAL;
1621e51764aSArtem Bityutskiy }
1631e51764aSArtem Bityutskiy 
1641e51764aSArtem Bityutskiy /**
1651e51764aSArtem Bityutskiy  * validate_master - validate master node.
1661e51764aSArtem Bityutskiy  * @c: UBIFS file-system description object
1671e51764aSArtem Bityutskiy  *
1681e51764aSArtem Bityutskiy  * This function validates data which was read from master node. Returns zero
1691e51764aSArtem Bityutskiy  * if the data is all right and %-EINVAL if not.
1701e51764aSArtem Bityutskiy  */
validate_master(const struct ubifs_info * c)1711e51764aSArtem Bityutskiy static int validate_master(const struct ubifs_info *c)
1721e51764aSArtem Bityutskiy {
1731e51764aSArtem Bityutskiy 	long long main_sz;
1741e51764aSArtem Bityutskiy 	int err;
1751e51764aSArtem Bityutskiy 
1761e51764aSArtem Bityutskiy 	if (c->max_sqnum >= SQNUM_WATERMARK) {
1771e51764aSArtem Bityutskiy 		err = 1;
1781e51764aSArtem Bityutskiy 		goto out;
1791e51764aSArtem Bityutskiy 	}
1801e51764aSArtem Bityutskiy 
1811e51764aSArtem Bityutskiy 	if (c->cmt_no >= c->max_sqnum) {
1821e51764aSArtem Bityutskiy 		err = 2;
1831e51764aSArtem Bityutskiy 		goto out;
1841e51764aSArtem Bityutskiy 	}
1851e51764aSArtem Bityutskiy 
1861e51764aSArtem Bityutskiy 	if (c->highest_inum >= INUM_WATERMARK) {
1871e51764aSArtem Bityutskiy 		err = 3;
1881e51764aSArtem Bityutskiy 		goto out;
1891e51764aSArtem Bityutskiy 	}
1901e51764aSArtem Bityutskiy 
1911e51764aSArtem Bityutskiy 	if (c->lhead_lnum < UBIFS_LOG_LNUM ||
1921e51764aSArtem Bityutskiy 	    c->lhead_lnum >= UBIFS_LOG_LNUM + c->log_lebs ||
1931e51764aSArtem Bityutskiy 	    c->lhead_offs < 0 || c->lhead_offs >= c->leb_size ||
1941e51764aSArtem Bityutskiy 	    c->lhead_offs & (c->min_io_size - 1)) {
1951e51764aSArtem Bityutskiy 		err = 4;
1961e51764aSArtem Bityutskiy 		goto out;
1971e51764aSArtem Bityutskiy 	}
1981e51764aSArtem Bityutskiy 
1991e51764aSArtem Bityutskiy 	if (c->zroot.lnum >= c->leb_cnt || c->zroot.lnum < c->main_first ||
2001e51764aSArtem Bityutskiy 	    c->zroot.offs >= c->leb_size || c->zroot.offs & 7) {
2011e51764aSArtem Bityutskiy 		err = 5;
2021e51764aSArtem Bityutskiy 		goto out;
2031e51764aSArtem Bityutskiy 	}
2041e51764aSArtem Bityutskiy 
2051e51764aSArtem Bityutskiy 	if (c->zroot.len < c->ranges[UBIFS_IDX_NODE].min_len ||
2061e51764aSArtem Bityutskiy 	    c->zroot.len > c->ranges[UBIFS_IDX_NODE].max_len) {
2071e51764aSArtem Bityutskiy 		err = 6;
2081e51764aSArtem Bityutskiy 		goto out;
2091e51764aSArtem Bityutskiy 	}
2101e51764aSArtem Bityutskiy 
2111e51764aSArtem Bityutskiy 	if (c->gc_lnum >= c->leb_cnt || c->gc_lnum < c->main_first) {
2121e51764aSArtem Bityutskiy 		err = 7;
2131e51764aSArtem Bityutskiy 		goto out;
2141e51764aSArtem Bityutskiy 	}
2151e51764aSArtem Bityutskiy 
2161e51764aSArtem Bityutskiy 	if (c->ihead_lnum >= c->leb_cnt || c->ihead_lnum < c->main_first ||
2171e51764aSArtem Bityutskiy 	    c->ihead_offs % c->min_io_size || c->ihead_offs < 0 ||
2181e51764aSArtem Bityutskiy 	    c->ihead_offs > c->leb_size || c->ihead_offs & 7) {
2191e51764aSArtem Bityutskiy 		err = 8;
2201e51764aSArtem Bityutskiy 		goto out;
2211e51764aSArtem Bityutskiy 	}
2221e51764aSArtem Bityutskiy 
2231e51764aSArtem Bityutskiy 	main_sz = (long long)c->main_lebs * c->leb_size;
224b137545cSArtem Bityutskiy 	if (c->bi.old_idx_sz & 7 || c->bi.old_idx_sz >= main_sz) {
2251e51764aSArtem Bityutskiy 		err = 9;
2261e51764aSArtem Bityutskiy 		goto out;
2271e51764aSArtem Bityutskiy 	}
2281e51764aSArtem Bityutskiy 
2291e51764aSArtem Bityutskiy 	if (c->lpt_lnum < c->lpt_first || c->lpt_lnum > c->lpt_last ||
2301e51764aSArtem Bityutskiy 	    c->lpt_offs < 0 || c->lpt_offs + c->nnode_sz > c->leb_size) {
2311e51764aSArtem Bityutskiy 		err = 10;
2321e51764aSArtem Bityutskiy 		goto out;
2331e51764aSArtem Bityutskiy 	}
2341e51764aSArtem Bityutskiy 
2351e51764aSArtem Bityutskiy 	if (c->nhead_lnum < c->lpt_first || c->nhead_lnum > c->lpt_last ||
2361e51764aSArtem Bityutskiy 	    c->nhead_offs < 0 || c->nhead_offs % c->min_io_size ||
2371e51764aSArtem Bityutskiy 	    c->nhead_offs > c->leb_size) {
2381e51764aSArtem Bityutskiy 		err = 11;
2391e51764aSArtem Bityutskiy 		goto out;
2401e51764aSArtem Bityutskiy 	}
2411e51764aSArtem Bityutskiy 
2421e51764aSArtem Bityutskiy 	if (c->ltab_lnum < c->lpt_first || c->ltab_lnum > c->lpt_last ||
2431e51764aSArtem Bityutskiy 	    c->ltab_offs < 0 ||
2441e51764aSArtem Bityutskiy 	    c->ltab_offs + c->ltab_sz > c->leb_size) {
2451e51764aSArtem Bityutskiy 		err = 12;
2461e51764aSArtem Bityutskiy 		goto out;
2471e51764aSArtem Bityutskiy 	}
2481e51764aSArtem Bityutskiy 
2491e51764aSArtem Bityutskiy 	if (c->big_lpt && (c->lsave_lnum < c->lpt_first ||
2501e51764aSArtem Bityutskiy 	    c->lsave_lnum > c->lpt_last || c->lsave_offs < 0 ||
2511e51764aSArtem Bityutskiy 	    c->lsave_offs + c->lsave_sz > c->leb_size)) {
2521e51764aSArtem Bityutskiy 		err = 13;
2531e51764aSArtem Bityutskiy 		goto out;
2541e51764aSArtem Bityutskiy 	}
2551e51764aSArtem Bityutskiy 
2561e51764aSArtem Bityutskiy 	if (c->lscan_lnum < c->main_first || c->lscan_lnum >= c->leb_cnt) {
2571e51764aSArtem Bityutskiy 		err = 14;
2581e51764aSArtem Bityutskiy 		goto out;
2591e51764aSArtem Bityutskiy 	}
2601e51764aSArtem Bityutskiy 
2611e51764aSArtem Bityutskiy 	if (c->lst.empty_lebs < 0 || c->lst.empty_lebs > c->main_lebs - 2) {
2621e51764aSArtem Bityutskiy 		err = 15;
2631e51764aSArtem Bityutskiy 		goto out;
2641e51764aSArtem Bityutskiy 	}
2651e51764aSArtem Bityutskiy 
2661e51764aSArtem Bityutskiy 	if (c->lst.idx_lebs < 0 || c->lst.idx_lebs > c->main_lebs - 1) {
2671e51764aSArtem Bityutskiy 		err = 16;
2681e51764aSArtem Bityutskiy 		goto out;
2691e51764aSArtem Bityutskiy 	}
2701e51764aSArtem Bityutskiy 
2711e51764aSArtem Bityutskiy 	if (c->lst.total_free < 0 || c->lst.total_free > main_sz ||
2721e51764aSArtem Bityutskiy 	    c->lst.total_free & 7) {
2731e51764aSArtem Bityutskiy 		err = 17;
2741e51764aSArtem Bityutskiy 		goto out;
2751e51764aSArtem Bityutskiy 	}
2761e51764aSArtem Bityutskiy 
2771e51764aSArtem Bityutskiy 	if (c->lst.total_dirty < 0 || (c->lst.total_dirty & 7)) {
2781e51764aSArtem Bityutskiy 		err = 18;
2791e51764aSArtem Bityutskiy 		goto out;
2801e51764aSArtem Bityutskiy 	}
2811e51764aSArtem Bityutskiy 
2821e51764aSArtem Bityutskiy 	if (c->lst.total_used < 0 || (c->lst.total_used & 7)) {
2831e51764aSArtem Bityutskiy 		err = 19;
2841e51764aSArtem Bityutskiy 		goto out;
2851e51764aSArtem Bityutskiy 	}
2861e51764aSArtem Bityutskiy 
2871e51764aSArtem Bityutskiy 	if (c->lst.total_free + c->lst.total_dirty +
2881e51764aSArtem Bityutskiy 	    c->lst.total_used > main_sz) {
2891e51764aSArtem Bityutskiy 		err = 20;
2901e51764aSArtem Bityutskiy 		goto out;
2911e51764aSArtem Bityutskiy 	}
2921e51764aSArtem Bityutskiy 
2931e51764aSArtem Bityutskiy 	if (c->lst.total_dead + c->lst.total_dark +
294b137545cSArtem Bityutskiy 	    c->lst.total_used + c->bi.old_idx_sz > main_sz) {
2951e51764aSArtem Bityutskiy 		err = 21;
2961e51764aSArtem Bityutskiy 		goto out;
2971e51764aSArtem Bityutskiy 	}
2981e51764aSArtem Bityutskiy 
2991e51764aSArtem Bityutskiy 	if (c->lst.total_dead < 0 ||
3001e51764aSArtem Bityutskiy 	    c->lst.total_dead > c->lst.total_free + c->lst.total_dirty ||
3011e51764aSArtem Bityutskiy 	    c->lst.total_dead & 7) {
3021e51764aSArtem Bityutskiy 		err = 22;
3031e51764aSArtem Bityutskiy 		goto out;
3041e51764aSArtem Bityutskiy 	}
3051e51764aSArtem Bityutskiy 
3061e51764aSArtem Bityutskiy 	if (c->lst.total_dark < 0 ||
3071e51764aSArtem Bityutskiy 	    c->lst.total_dark > c->lst.total_free + c->lst.total_dirty ||
3081e51764aSArtem Bityutskiy 	    c->lst.total_dark & 7) {
3091e51764aSArtem Bityutskiy 		err = 23;
3101e51764aSArtem Bityutskiy 		goto out;
3111e51764aSArtem Bityutskiy 	}
3121e51764aSArtem Bityutskiy 
3131e51764aSArtem Bityutskiy 	return 0;
3141e51764aSArtem Bityutskiy 
3151e51764aSArtem Bityutskiy out:
316235c362bSSheng Yong 	ubifs_err(c, "bad master node at offset %d error %d", c->mst_offs, err);
317*a33e30a0SZhihao Cheng 	ubifs_dump_node(c, c->mst_node, c->mst_node_alsz);
3181e51764aSArtem Bityutskiy 	return -EINVAL;
3191e51764aSArtem Bityutskiy }
3201e51764aSArtem Bityutskiy 
3211e51764aSArtem Bityutskiy /**
3221e51764aSArtem Bityutskiy  * ubifs_read_master - read master node.
3231e51764aSArtem Bityutskiy  * @c: UBIFS file-system description object
3241e51764aSArtem Bityutskiy  *
3251e51764aSArtem Bityutskiy  * This function finds and reads the master node during file-system mount. If
3261e51764aSArtem Bityutskiy  * the flash is empty, it creates default master node as well. Returns zero in
3271e51764aSArtem Bityutskiy  * case of success and a negative error code in case of failure.
3281e51764aSArtem Bityutskiy  */
ubifs_read_master(struct ubifs_info * c)3291e51764aSArtem Bityutskiy int ubifs_read_master(struct ubifs_info *c)
3301e51764aSArtem Bityutskiy {
3311e51764aSArtem Bityutskiy 	int err, old_leb_cnt;
3321e51764aSArtem Bityutskiy 
3331e51764aSArtem Bityutskiy 	c->mst_node = kzalloc(c->mst_node_alsz, GFP_KERNEL);
3341e51764aSArtem Bityutskiy 	if (!c->mst_node)
3351e51764aSArtem Bityutskiy 		return -ENOMEM;
3361e51764aSArtem Bityutskiy 
3371e51764aSArtem Bityutskiy 	err = scan_for_master(c);
3381e51764aSArtem Bityutskiy 	if (err) {
3390dcd18e4SArtem Bityutskiy 		if (err == -EUCLEAN)
3401e51764aSArtem Bityutskiy 			err = ubifs_recover_master_node(c);
3411e51764aSArtem Bityutskiy 		if (err)
3421e51764aSArtem Bityutskiy 			/*
3431e51764aSArtem Bityutskiy 			 * Note, we do not free 'c->mst_node' here because the
3441e51764aSArtem Bityutskiy 			 * unmount routine will take care of this.
3451e51764aSArtem Bityutskiy 			 */
3461e51764aSArtem Bityutskiy 			return err;
3471e51764aSArtem Bityutskiy 	}
3481e51764aSArtem Bityutskiy 
3491e51764aSArtem Bityutskiy 	/* Make sure that the recovery flag is clear */
3501e51764aSArtem Bityutskiy 	c->mst_node->flags &= cpu_to_le32(~UBIFS_MST_RCVRY);
3511e51764aSArtem Bityutskiy 
3521e51764aSArtem Bityutskiy 	c->max_sqnum       = le64_to_cpu(c->mst_node->ch.sqnum);
3531e51764aSArtem Bityutskiy 	c->highest_inum    = le64_to_cpu(c->mst_node->highest_inum);
3541e51764aSArtem Bityutskiy 	c->cmt_no          = le64_to_cpu(c->mst_node->cmt_no);
3551e51764aSArtem Bityutskiy 	c->zroot.lnum      = le32_to_cpu(c->mst_node->root_lnum);
3561e51764aSArtem Bityutskiy 	c->zroot.offs      = le32_to_cpu(c->mst_node->root_offs);
3571e51764aSArtem Bityutskiy 	c->zroot.len       = le32_to_cpu(c->mst_node->root_len);
3581e51764aSArtem Bityutskiy 	c->lhead_lnum      = le32_to_cpu(c->mst_node->log_lnum);
3591e51764aSArtem Bityutskiy 	c->gc_lnum         = le32_to_cpu(c->mst_node->gc_lnum);
3601e51764aSArtem Bityutskiy 	c->ihead_lnum      = le32_to_cpu(c->mst_node->ihead_lnum);
3611e51764aSArtem Bityutskiy 	c->ihead_offs      = le32_to_cpu(c->mst_node->ihead_offs);
362b137545cSArtem Bityutskiy 	c->bi.old_idx_sz   = le64_to_cpu(c->mst_node->index_size);
3631e51764aSArtem Bityutskiy 	c->lpt_lnum        = le32_to_cpu(c->mst_node->lpt_lnum);
3641e51764aSArtem Bityutskiy 	c->lpt_offs        = le32_to_cpu(c->mst_node->lpt_offs);
3651e51764aSArtem Bityutskiy 	c->nhead_lnum      = le32_to_cpu(c->mst_node->nhead_lnum);
3661e51764aSArtem Bityutskiy 	c->nhead_offs      = le32_to_cpu(c->mst_node->nhead_offs);
3671e51764aSArtem Bityutskiy 	c->ltab_lnum       = le32_to_cpu(c->mst_node->ltab_lnum);
3681e51764aSArtem Bityutskiy 	c->ltab_offs       = le32_to_cpu(c->mst_node->ltab_offs);
3691e51764aSArtem Bityutskiy 	c->lsave_lnum      = le32_to_cpu(c->mst_node->lsave_lnum);
3701e51764aSArtem Bityutskiy 	c->lsave_offs      = le32_to_cpu(c->mst_node->lsave_offs);
3711e51764aSArtem Bityutskiy 	c->lscan_lnum      = le32_to_cpu(c->mst_node->lscan_lnum);
3721e51764aSArtem Bityutskiy 	c->lst.empty_lebs  = le32_to_cpu(c->mst_node->empty_lebs);
3731e51764aSArtem Bityutskiy 	c->lst.idx_lebs    = le32_to_cpu(c->mst_node->idx_lebs);
3741e51764aSArtem Bityutskiy 	old_leb_cnt        = le32_to_cpu(c->mst_node->leb_cnt);
3751e51764aSArtem Bityutskiy 	c->lst.total_free  = le64_to_cpu(c->mst_node->total_free);
3761e51764aSArtem Bityutskiy 	c->lst.total_dirty = le64_to_cpu(c->mst_node->total_dirty);
3771e51764aSArtem Bityutskiy 	c->lst.total_used  = le64_to_cpu(c->mst_node->total_used);
3781e51764aSArtem Bityutskiy 	c->lst.total_dead  = le64_to_cpu(c->mst_node->total_dead);
3791e51764aSArtem Bityutskiy 	c->lst.total_dark  = le64_to_cpu(c->mst_node->total_dark);
3801e51764aSArtem Bityutskiy 
38116a26b20SSascha Hauer 	ubifs_copy_hash(c, c->mst_node->hash_root_idx, c->zroot.hash);
38216a26b20SSascha Hauer 
383b137545cSArtem Bityutskiy 	c->calc_idx_sz = c->bi.old_idx_sz;
3841e51764aSArtem Bityutskiy 
3851e51764aSArtem Bityutskiy 	if (c->mst_node->flags & cpu_to_le32(UBIFS_MST_NO_ORPHS))
3861e51764aSArtem Bityutskiy 		c->no_orphs = 1;
3871e51764aSArtem Bityutskiy 
3881e51764aSArtem Bityutskiy 	if (old_leb_cnt != c->leb_cnt) {
3891e51764aSArtem Bityutskiy 		/* The file system has been resized */
3901e51764aSArtem Bityutskiy 		int growth = c->leb_cnt - old_leb_cnt;
3911e51764aSArtem Bityutskiy 
3921e51764aSArtem Bityutskiy 		if (c->leb_cnt < old_leb_cnt ||
3931e51764aSArtem Bityutskiy 		    c->leb_cnt < UBIFS_MIN_LEB_CNT) {
394235c362bSSheng Yong 			ubifs_err(c, "bad leb_cnt on master node");
395*a33e30a0SZhihao Cheng 			ubifs_dump_node(c, c->mst_node, c->mst_node_alsz);
3961e51764aSArtem Bityutskiy 			return -EINVAL;
3971e51764aSArtem Bityutskiy 		}
3981e51764aSArtem Bityutskiy 
3991e51764aSArtem Bityutskiy 		dbg_mnt("Auto resizing (master) from %d LEBs to %d LEBs",
4001e51764aSArtem Bityutskiy 			old_leb_cnt, c->leb_cnt);
4011e51764aSArtem Bityutskiy 		c->lst.empty_lebs += growth;
4021e51764aSArtem Bityutskiy 		c->lst.total_free += growth * (long long)c->leb_size;
4031e51764aSArtem Bityutskiy 		c->lst.total_dark += growth * (long long)c->dark_wm;
4041e51764aSArtem Bityutskiy 
4051e51764aSArtem Bityutskiy 		/*
4061e51764aSArtem Bityutskiy 		 * Reflect changes back onto the master node. N.B. the master
4071e51764aSArtem Bityutskiy 		 * node gets written immediately whenever mounting (or
4081e51764aSArtem Bityutskiy 		 * remounting) in read-write mode, so we do not need to write it
4091e51764aSArtem Bityutskiy 		 * here.
4101e51764aSArtem Bityutskiy 		 */
4111e51764aSArtem Bityutskiy 		c->mst_node->leb_cnt = cpu_to_le32(c->leb_cnt);
4121e51764aSArtem Bityutskiy 		c->mst_node->empty_lebs = cpu_to_le32(c->lst.empty_lebs);
4131e51764aSArtem Bityutskiy 		c->mst_node->total_free = cpu_to_le64(c->lst.total_free);
4141e51764aSArtem Bityutskiy 		c->mst_node->total_dark = cpu_to_le64(c->lst.total_dark);
4151e51764aSArtem Bityutskiy 	}
4161e51764aSArtem Bityutskiy 
4171e51764aSArtem Bityutskiy 	err = validate_master(c);
4181e51764aSArtem Bityutskiy 	if (err)
4191e51764aSArtem Bityutskiy 		return err;
4201e51764aSArtem Bityutskiy 
4211e51764aSArtem Bityutskiy 	err = dbg_old_index_check_init(c, &c->zroot);
4221e51764aSArtem Bityutskiy 
4231e51764aSArtem Bityutskiy 	return err;
4241e51764aSArtem Bityutskiy }
4251e51764aSArtem Bityutskiy 
4261e51764aSArtem Bityutskiy /**
4271e51764aSArtem Bityutskiy  * ubifs_write_master - write master node.
4281e51764aSArtem Bityutskiy  * @c: UBIFS file-system description object
4291e51764aSArtem Bityutskiy  *
43007e19dffSArtem Bityutskiy  * This function writes the master node. Returns zero in case of success and a
43107e19dffSArtem Bityutskiy  * negative error code in case of failure. The master node is written twice to
43207e19dffSArtem Bityutskiy  * enable recovery.
4331e51764aSArtem Bityutskiy  */
ubifs_write_master(struct ubifs_info * c)4341e51764aSArtem Bityutskiy int ubifs_write_master(struct ubifs_info *c)
4351e51764aSArtem Bityutskiy {
4361e51764aSArtem Bityutskiy 	int err, lnum, offs, len;
4371e51764aSArtem Bityutskiy 
4386eb61d58SRichard Weinberger 	ubifs_assert(c, !c->ro_media && !c->ro_mount);
4392680d722SArtem Bityutskiy 	if (c->ro_error)
440a2b9df3fSArtem Bityutskiy 		return -EROFS;
4411e51764aSArtem Bityutskiy 
4421e51764aSArtem Bityutskiy 	lnum = UBIFS_MST_LNUM;
4431e51764aSArtem Bityutskiy 	offs = c->mst_offs + c->mst_node_alsz;
4441e51764aSArtem Bityutskiy 	len = UBIFS_MST_NODE_SZ;
4451e51764aSArtem Bityutskiy 
4461e51764aSArtem Bityutskiy 	if (offs + UBIFS_MST_NODE_SZ > c->leb_size) {
4471e51764aSArtem Bityutskiy 		err = ubifs_leb_unmap(c, lnum);
4481e51764aSArtem Bityutskiy 		if (err)
4491e51764aSArtem Bityutskiy 			return err;
4501e51764aSArtem Bityutskiy 		offs = 0;
4511e51764aSArtem Bityutskiy 	}
4521e51764aSArtem Bityutskiy 
4531e51764aSArtem Bityutskiy 	c->mst_offs = offs;
4541e51764aSArtem Bityutskiy 	c->mst_node->highest_inum = cpu_to_le64(c->highest_inum);
4551e51764aSArtem Bityutskiy 
45616a26b20SSascha Hauer 	ubifs_copy_hash(c, c->zroot.hash, c->mst_node->hash_root_idx);
457625700ccSSascha Hauer 	err = ubifs_write_node_hmac(c, c->mst_node, len, lnum, offs,
458625700ccSSascha Hauer 				    offsetof(struct ubifs_mst_node, hmac));
4591e51764aSArtem Bityutskiy 	if (err)
4601e51764aSArtem Bityutskiy 		return err;
4611e51764aSArtem Bityutskiy 
4621e51764aSArtem Bityutskiy 	lnum += 1;
4631e51764aSArtem Bityutskiy 
4641e51764aSArtem Bityutskiy 	if (offs == 0) {
4651e51764aSArtem Bityutskiy 		err = ubifs_leb_unmap(c, lnum);
4661e51764aSArtem Bityutskiy 		if (err)
4671e51764aSArtem Bityutskiy 			return err;
4681e51764aSArtem Bityutskiy 	}
469625700ccSSascha Hauer 	err = ubifs_write_node_hmac(c, c->mst_node, len, lnum, offs,
470625700ccSSascha Hauer 				    offsetof(struct ubifs_mst_node, hmac));
4711e51764aSArtem Bityutskiy 
4721e51764aSArtem Bityutskiy 	return err;
4731e51764aSArtem Bityutskiy }
474