xref: /rk3399_rockchip-uboot/fs/ubifs/master.c (revision e573bdb324c78fac56655a493bea843842c9d9f8)
19eefe2a2SStefan Roese /*
29eefe2a2SStefan Roese  * This file is part of UBIFS.
39eefe2a2SStefan Roese  *
49eefe2a2SStefan Roese  * Copyright (C) 2006-2008 Nokia Corporation.
59eefe2a2SStefan Roese  *
6ff94bc40SHeiko Schocher  * SPDX-License-Identifier:	GPL-2.0+
79eefe2a2SStefan Roese  *
89eefe2a2SStefan Roese  * Authors: Artem Bityutskiy (Битюцкий Артём)
99eefe2a2SStefan Roese  *          Adrian Hunter
109eefe2a2SStefan Roese  */
119eefe2a2SStefan Roese 
129eefe2a2SStefan Roese /* This file implements reading and writing the master node */
139eefe2a2SStefan Roese 
149eefe2a2SStefan Roese #include "ubifs.h"
15ff94bc40SHeiko Schocher #ifdef __UBOOT__
16ff94bc40SHeiko Schocher #include <linux/compat.h>
17ff94bc40SHeiko Schocher #include <linux/err.h>
18ff94bc40SHeiko Schocher #include <ubi_uboot.h>
19ff94bc40SHeiko Schocher #endif
209eefe2a2SStefan Roese 
219eefe2a2SStefan Roese /**
229eefe2a2SStefan Roese  * scan_for_master - search the valid master node.
239eefe2a2SStefan Roese  * @c: UBIFS file-system description object
249eefe2a2SStefan Roese  *
259eefe2a2SStefan Roese  * This function scans the master node LEBs and search for the latest master
26ff94bc40SHeiko Schocher  * node. Returns zero in case of success, %-EUCLEAN if there master area is
27ff94bc40SHeiko Schocher  * corrupted and requires recovery, and a negative error code in case of
289eefe2a2SStefan Roese  * failure.
299eefe2a2SStefan Roese  */
scan_for_master(struct ubifs_info * c)309eefe2a2SStefan Roese static int scan_for_master(struct ubifs_info *c)
319eefe2a2SStefan Roese {
329eefe2a2SStefan Roese 	struct ubifs_scan_leb *sleb;
339eefe2a2SStefan Roese 	struct ubifs_scan_node *snod;
349eefe2a2SStefan Roese 	int lnum, offs = 0, nodes_cnt;
359eefe2a2SStefan Roese 
369eefe2a2SStefan Roese 	lnum = UBIFS_MST_LNUM;
379eefe2a2SStefan Roese 
38ff94bc40SHeiko Schocher 	sleb = ubifs_scan(c, lnum, 0, c->sbuf, 1);
399eefe2a2SStefan Roese 	if (IS_ERR(sleb))
409eefe2a2SStefan Roese 		return PTR_ERR(sleb);
419eefe2a2SStefan Roese 	nodes_cnt = sleb->nodes_cnt;
429eefe2a2SStefan Roese 	if (nodes_cnt > 0) {
439eefe2a2SStefan Roese 		snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node,
449eefe2a2SStefan Roese 				  list);
459eefe2a2SStefan Roese 		if (snod->type != UBIFS_MST_NODE)
46ff94bc40SHeiko Schocher 			goto out_dump;
479eefe2a2SStefan Roese 		memcpy(c->mst_node, snod->node, snod->len);
489eefe2a2SStefan Roese 		offs = snod->offs;
499eefe2a2SStefan Roese 	}
509eefe2a2SStefan Roese 	ubifs_scan_destroy(sleb);
519eefe2a2SStefan Roese 
529eefe2a2SStefan Roese 	lnum += 1;
539eefe2a2SStefan Roese 
54ff94bc40SHeiko Schocher 	sleb = ubifs_scan(c, lnum, 0, c->sbuf, 1);
559eefe2a2SStefan Roese 	if (IS_ERR(sleb))
569eefe2a2SStefan Roese 		return PTR_ERR(sleb);
579eefe2a2SStefan Roese 	if (sleb->nodes_cnt != nodes_cnt)
589eefe2a2SStefan Roese 		goto out;
599eefe2a2SStefan Roese 	if (!sleb->nodes_cnt)
609eefe2a2SStefan Roese 		goto out;
619eefe2a2SStefan Roese 	snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node, list);
629eefe2a2SStefan Roese 	if (snod->type != UBIFS_MST_NODE)
63ff94bc40SHeiko Schocher 		goto out_dump;
649eefe2a2SStefan Roese 	if (snod->offs != offs)
659eefe2a2SStefan Roese 		goto out;
669eefe2a2SStefan Roese 	if (memcmp((void *)c->mst_node + UBIFS_CH_SZ,
679eefe2a2SStefan Roese 		   (void *)snod->node + UBIFS_CH_SZ,
689eefe2a2SStefan Roese 		   UBIFS_MST_NODE_SZ - UBIFS_CH_SZ))
699eefe2a2SStefan Roese 		goto out;
709eefe2a2SStefan Roese 	c->mst_offs = offs;
719eefe2a2SStefan Roese 	ubifs_scan_destroy(sleb);
729eefe2a2SStefan Roese 	return 0;
739eefe2a2SStefan Roese 
749eefe2a2SStefan Roese out:
759eefe2a2SStefan Roese 	ubifs_scan_destroy(sleb);
76ff94bc40SHeiko Schocher 	return -EUCLEAN;
77ff94bc40SHeiko Schocher 
78ff94bc40SHeiko Schocher out_dump:
79*0195a7bbSHeiko Schocher 	ubifs_err(c, "unexpected node type %d master LEB %d:%d",
80ff94bc40SHeiko Schocher 		  snod->type, lnum, snod->offs);
81ff94bc40SHeiko Schocher 	ubifs_scan_destroy(sleb);
829eefe2a2SStefan Roese 	return -EINVAL;
839eefe2a2SStefan Roese }
849eefe2a2SStefan Roese 
859eefe2a2SStefan Roese /**
869eefe2a2SStefan Roese  * validate_master - validate master node.
879eefe2a2SStefan Roese  * @c: UBIFS file-system description object
889eefe2a2SStefan Roese  *
899eefe2a2SStefan Roese  * This function validates data which was read from master node. Returns zero
909eefe2a2SStefan Roese  * if the data is all right and %-EINVAL if not.
919eefe2a2SStefan Roese  */
validate_master(const struct ubifs_info * c)929eefe2a2SStefan Roese static int validate_master(const struct ubifs_info *c)
939eefe2a2SStefan Roese {
949eefe2a2SStefan Roese 	long long main_sz;
959eefe2a2SStefan Roese 	int err;
969eefe2a2SStefan Roese 
979eefe2a2SStefan Roese 	if (c->max_sqnum >= SQNUM_WATERMARK) {
989eefe2a2SStefan Roese 		err = 1;
999eefe2a2SStefan Roese 		goto out;
1009eefe2a2SStefan Roese 	}
1019eefe2a2SStefan Roese 
1029eefe2a2SStefan Roese 	if (c->cmt_no >= c->max_sqnum) {
1039eefe2a2SStefan Roese 		err = 2;
1049eefe2a2SStefan Roese 		goto out;
1059eefe2a2SStefan Roese 	}
1069eefe2a2SStefan Roese 
1079eefe2a2SStefan Roese 	if (c->highest_inum >= INUM_WATERMARK) {
1089eefe2a2SStefan Roese 		err = 3;
1099eefe2a2SStefan Roese 		goto out;
1109eefe2a2SStefan Roese 	}
1119eefe2a2SStefan Roese 
1129eefe2a2SStefan Roese 	if (c->lhead_lnum < UBIFS_LOG_LNUM ||
1139eefe2a2SStefan Roese 	    c->lhead_lnum >= UBIFS_LOG_LNUM + c->log_lebs ||
1149eefe2a2SStefan Roese 	    c->lhead_offs < 0 || c->lhead_offs >= c->leb_size ||
1159eefe2a2SStefan Roese 	    c->lhead_offs & (c->min_io_size - 1)) {
1169eefe2a2SStefan Roese 		err = 4;
1179eefe2a2SStefan Roese 		goto out;
1189eefe2a2SStefan Roese 	}
1199eefe2a2SStefan Roese 
1209eefe2a2SStefan Roese 	if (c->zroot.lnum >= c->leb_cnt || c->zroot.lnum < c->main_first ||
1219eefe2a2SStefan Roese 	    c->zroot.offs >= c->leb_size || c->zroot.offs & 7) {
1229eefe2a2SStefan Roese 		err = 5;
1239eefe2a2SStefan Roese 		goto out;
1249eefe2a2SStefan Roese 	}
1259eefe2a2SStefan Roese 
1269eefe2a2SStefan Roese 	if (c->zroot.len < c->ranges[UBIFS_IDX_NODE].min_len ||
1279eefe2a2SStefan Roese 	    c->zroot.len > c->ranges[UBIFS_IDX_NODE].max_len) {
1289eefe2a2SStefan Roese 		err = 6;
1299eefe2a2SStefan Roese 		goto out;
1309eefe2a2SStefan Roese 	}
1319eefe2a2SStefan Roese 
1329eefe2a2SStefan Roese 	if (c->gc_lnum >= c->leb_cnt || c->gc_lnum < c->main_first) {
1339eefe2a2SStefan Roese 		err = 7;
1349eefe2a2SStefan Roese 		goto out;
1359eefe2a2SStefan Roese 	}
1369eefe2a2SStefan Roese 
1379eefe2a2SStefan Roese 	if (c->ihead_lnum >= c->leb_cnt || c->ihead_lnum < c->main_first ||
1389eefe2a2SStefan Roese 	    c->ihead_offs % c->min_io_size || c->ihead_offs < 0 ||
1399eefe2a2SStefan Roese 	    c->ihead_offs > c->leb_size || c->ihead_offs & 7) {
1409eefe2a2SStefan Roese 		err = 8;
1419eefe2a2SStefan Roese 		goto out;
1429eefe2a2SStefan Roese 	}
1439eefe2a2SStefan Roese 
1449eefe2a2SStefan Roese 	main_sz = (long long)c->main_lebs * c->leb_size;
145ff94bc40SHeiko Schocher 	if (c->bi.old_idx_sz & 7 || c->bi.old_idx_sz >= main_sz) {
1469eefe2a2SStefan Roese 		err = 9;
1479eefe2a2SStefan Roese 		goto out;
1489eefe2a2SStefan Roese 	}
1499eefe2a2SStefan Roese 
1509eefe2a2SStefan Roese 	if (c->lpt_lnum < c->lpt_first || c->lpt_lnum > c->lpt_last ||
1519eefe2a2SStefan Roese 	    c->lpt_offs < 0 || c->lpt_offs + c->nnode_sz > c->leb_size) {
1529eefe2a2SStefan Roese 		err = 10;
1539eefe2a2SStefan Roese 		goto out;
1549eefe2a2SStefan Roese 	}
1559eefe2a2SStefan Roese 
1569eefe2a2SStefan Roese 	if (c->nhead_lnum < c->lpt_first || c->nhead_lnum > c->lpt_last ||
1579eefe2a2SStefan Roese 	    c->nhead_offs < 0 || c->nhead_offs % c->min_io_size ||
1589eefe2a2SStefan Roese 	    c->nhead_offs > c->leb_size) {
1599eefe2a2SStefan Roese 		err = 11;
1609eefe2a2SStefan Roese 		goto out;
1619eefe2a2SStefan Roese 	}
1629eefe2a2SStefan Roese 
1639eefe2a2SStefan Roese 	if (c->ltab_lnum < c->lpt_first || c->ltab_lnum > c->lpt_last ||
1649eefe2a2SStefan Roese 	    c->ltab_offs < 0 ||
1659eefe2a2SStefan Roese 	    c->ltab_offs + c->ltab_sz > c->leb_size) {
1669eefe2a2SStefan Roese 		err = 12;
1679eefe2a2SStefan Roese 		goto out;
1689eefe2a2SStefan Roese 	}
1699eefe2a2SStefan Roese 
1709eefe2a2SStefan Roese 	if (c->big_lpt && (c->lsave_lnum < c->lpt_first ||
1719eefe2a2SStefan Roese 	    c->lsave_lnum > c->lpt_last || c->lsave_offs < 0 ||
1729eefe2a2SStefan Roese 	    c->lsave_offs + c->lsave_sz > c->leb_size)) {
1739eefe2a2SStefan Roese 		err = 13;
1749eefe2a2SStefan Roese 		goto out;
1759eefe2a2SStefan Roese 	}
1769eefe2a2SStefan Roese 
1779eefe2a2SStefan Roese 	if (c->lscan_lnum < c->main_first || c->lscan_lnum >= c->leb_cnt) {
1789eefe2a2SStefan Roese 		err = 14;
1799eefe2a2SStefan Roese 		goto out;
1809eefe2a2SStefan Roese 	}
1819eefe2a2SStefan Roese 
1829eefe2a2SStefan Roese 	if (c->lst.empty_lebs < 0 || c->lst.empty_lebs > c->main_lebs - 2) {
1839eefe2a2SStefan Roese 		err = 15;
1849eefe2a2SStefan Roese 		goto out;
1859eefe2a2SStefan Roese 	}
1869eefe2a2SStefan Roese 
1879eefe2a2SStefan Roese 	if (c->lst.idx_lebs < 0 || c->lst.idx_lebs > c->main_lebs - 1) {
1889eefe2a2SStefan Roese 		err = 16;
1899eefe2a2SStefan Roese 		goto out;
1909eefe2a2SStefan Roese 	}
1919eefe2a2SStefan Roese 
1929eefe2a2SStefan Roese 	if (c->lst.total_free < 0 || c->lst.total_free > main_sz ||
1939eefe2a2SStefan Roese 	    c->lst.total_free & 7) {
1949eefe2a2SStefan Roese 		err = 17;
1959eefe2a2SStefan Roese 		goto out;
1969eefe2a2SStefan Roese 	}
1979eefe2a2SStefan Roese 
1989eefe2a2SStefan Roese 	if (c->lst.total_dirty < 0 || (c->lst.total_dirty & 7)) {
1999eefe2a2SStefan Roese 		err = 18;
2009eefe2a2SStefan Roese 		goto out;
2019eefe2a2SStefan Roese 	}
2029eefe2a2SStefan Roese 
2039eefe2a2SStefan Roese 	if (c->lst.total_used < 0 || (c->lst.total_used & 7)) {
2049eefe2a2SStefan Roese 		err = 19;
2059eefe2a2SStefan Roese 		goto out;
2069eefe2a2SStefan Roese 	}
2079eefe2a2SStefan Roese 
2089eefe2a2SStefan Roese 	if (c->lst.total_free + c->lst.total_dirty +
2099eefe2a2SStefan Roese 	    c->lst.total_used > main_sz) {
2109eefe2a2SStefan Roese 		err = 20;
2119eefe2a2SStefan Roese 		goto out;
2129eefe2a2SStefan Roese 	}
2139eefe2a2SStefan Roese 
2149eefe2a2SStefan Roese 	if (c->lst.total_dead + c->lst.total_dark +
215ff94bc40SHeiko Schocher 	    c->lst.total_used + c->bi.old_idx_sz > main_sz) {
2169eefe2a2SStefan Roese 		err = 21;
2179eefe2a2SStefan Roese 		goto out;
2189eefe2a2SStefan Roese 	}
2199eefe2a2SStefan Roese 
2209eefe2a2SStefan Roese 	if (c->lst.total_dead < 0 ||
2219eefe2a2SStefan Roese 	    c->lst.total_dead > c->lst.total_free + c->lst.total_dirty ||
2229eefe2a2SStefan Roese 	    c->lst.total_dead & 7) {
2239eefe2a2SStefan Roese 		err = 22;
2249eefe2a2SStefan Roese 		goto out;
2259eefe2a2SStefan Roese 	}
2269eefe2a2SStefan Roese 
2279eefe2a2SStefan Roese 	if (c->lst.total_dark < 0 ||
2289eefe2a2SStefan Roese 	    c->lst.total_dark > c->lst.total_free + c->lst.total_dirty ||
2299eefe2a2SStefan Roese 	    c->lst.total_dark & 7) {
2309eefe2a2SStefan Roese 		err = 23;
2319eefe2a2SStefan Roese 		goto out;
2329eefe2a2SStefan Roese 	}
2339eefe2a2SStefan Roese 
2349eefe2a2SStefan Roese 	return 0;
2359eefe2a2SStefan Roese 
2369eefe2a2SStefan Roese out:
237*0195a7bbSHeiko Schocher 	ubifs_err(c, "bad master node at offset %d error %d", c->mst_offs, err);
238ff94bc40SHeiko Schocher 	ubifs_dump_node(c, c->mst_node);
2399eefe2a2SStefan Roese 	return -EINVAL;
2409eefe2a2SStefan Roese }
2419eefe2a2SStefan Roese 
2429eefe2a2SStefan Roese /**
2439eefe2a2SStefan Roese  * ubifs_read_master - read master node.
2449eefe2a2SStefan Roese  * @c: UBIFS file-system description object
2459eefe2a2SStefan Roese  *
2469eefe2a2SStefan Roese  * This function finds and reads the master node during file-system mount. If
2479eefe2a2SStefan Roese  * the flash is empty, it creates default master node as well. Returns zero in
2489eefe2a2SStefan Roese  * case of success and a negative error code in case of failure.
2499eefe2a2SStefan Roese  */
ubifs_read_master(struct ubifs_info * c)2509eefe2a2SStefan Roese int ubifs_read_master(struct ubifs_info *c)
2519eefe2a2SStefan Roese {
2529eefe2a2SStefan Roese 	int err, old_leb_cnt;
2539eefe2a2SStefan Roese 
2549eefe2a2SStefan Roese 	c->mst_node = kzalloc(c->mst_node_alsz, GFP_KERNEL);
2559eefe2a2SStefan Roese 	if (!c->mst_node)
2569eefe2a2SStefan Roese 		return -ENOMEM;
2579eefe2a2SStefan Roese 
2589eefe2a2SStefan Roese 	err = scan_for_master(c);
2599eefe2a2SStefan Roese 	if (err) {
260ff94bc40SHeiko Schocher 		if (err == -EUCLEAN)
2619eefe2a2SStefan Roese 			err = ubifs_recover_master_node(c);
2629eefe2a2SStefan Roese 		if (err)
2639eefe2a2SStefan Roese 			/*
2649eefe2a2SStefan Roese 			 * Note, we do not free 'c->mst_node' here because the
2659eefe2a2SStefan Roese 			 * unmount routine will take care of this.
2669eefe2a2SStefan Roese 			 */
2679eefe2a2SStefan Roese 			return err;
2689eefe2a2SStefan Roese 	}
2699eefe2a2SStefan Roese 
2709eefe2a2SStefan Roese 	/* Make sure that the recovery flag is clear */
2719eefe2a2SStefan Roese 	c->mst_node->flags &= cpu_to_le32(~UBIFS_MST_RCVRY);
2729eefe2a2SStefan Roese 
2739eefe2a2SStefan Roese 	c->max_sqnum       = le64_to_cpu(c->mst_node->ch.sqnum);
2749eefe2a2SStefan Roese 	c->highest_inum    = le64_to_cpu(c->mst_node->highest_inum);
2759eefe2a2SStefan Roese 	c->cmt_no          = le64_to_cpu(c->mst_node->cmt_no);
2769eefe2a2SStefan Roese 	c->zroot.lnum      = le32_to_cpu(c->mst_node->root_lnum);
2779eefe2a2SStefan Roese 	c->zroot.offs      = le32_to_cpu(c->mst_node->root_offs);
2789eefe2a2SStefan Roese 	c->zroot.len       = le32_to_cpu(c->mst_node->root_len);
2799eefe2a2SStefan Roese 	c->lhead_lnum      = le32_to_cpu(c->mst_node->log_lnum);
2809eefe2a2SStefan Roese 	c->gc_lnum         = le32_to_cpu(c->mst_node->gc_lnum);
2819eefe2a2SStefan Roese 	c->ihead_lnum      = le32_to_cpu(c->mst_node->ihead_lnum);
2829eefe2a2SStefan Roese 	c->ihead_offs      = le32_to_cpu(c->mst_node->ihead_offs);
283ff94bc40SHeiko Schocher 	c->bi.old_idx_sz   = le64_to_cpu(c->mst_node->index_size);
2849eefe2a2SStefan Roese 	c->lpt_lnum        = le32_to_cpu(c->mst_node->lpt_lnum);
2859eefe2a2SStefan Roese 	c->lpt_offs        = le32_to_cpu(c->mst_node->lpt_offs);
2869eefe2a2SStefan Roese 	c->nhead_lnum      = le32_to_cpu(c->mst_node->nhead_lnum);
2879eefe2a2SStefan Roese 	c->nhead_offs      = le32_to_cpu(c->mst_node->nhead_offs);
2889eefe2a2SStefan Roese 	c->ltab_lnum       = le32_to_cpu(c->mst_node->ltab_lnum);
2899eefe2a2SStefan Roese 	c->ltab_offs       = le32_to_cpu(c->mst_node->ltab_offs);
2909eefe2a2SStefan Roese 	c->lsave_lnum      = le32_to_cpu(c->mst_node->lsave_lnum);
2919eefe2a2SStefan Roese 	c->lsave_offs      = le32_to_cpu(c->mst_node->lsave_offs);
2929eefe2a2SStefan Roese 	c->lscan_lnum      = le32_to_cpu(c->mst_node->lscan_lnum);
2939eefe2a2SStefan Roese 	c->lst.empty_lebs  = le32_to_cpu(c->mst_node->empty_lebs);
2949eefe2a2SStefan Roese 	c->lst.idx_lebs    = le32_to_cpu(c->mst_node->idx_lebs);
2959eefe2a2SStefan Roese 	old_leb_cnt        = le32_to_cpu(c->mst_node->leb_cnt);
2969eefe2a2SStefan Roese 	c->lst.total_free  = le64_to_cpu(c->mst_node->total_free);
2979eefe2a2SStefan Roese 	c->lst.total_dirty = le64_to_cpu(c->mst_node->total_dirty);
2989eefe2a2SStefan Roese 	c->lst.total_used  = le64_to_cpu(c->mst_node->total_used);
2999eefe2a2SStefan Roese 	c->lst.total_dead  = le64_to_cpu(c->mst_node->total_dead);
3009eefe2a2SStefan Roese 	c->lst.total_dark  = le64_to_cpu(c->mst_node->total_dark);
3019eefe2a2SStefan Roese 
302ff94bc40SHeiko Schocher 	c->calc_idx_sz = c->bi.old_idx_sz;
3039eefe2a2SStefan Roese 
3049eefe2a2SStefan Roese 	if (c->mst_node->flags & cpu_to_le32(UBIFS_MST_NO_ORPHS))
3059eefe2a2SStefan Roese 		c->no_orphs = 1;
3069eefe2a2SStefan Roese 
3079eefe2a2SStefan Roese 	if (old_leb_cnt != c->leb_cnt) {
3089eefe2a2SStefan Roese 		/* The file system has been resized */
3099eefe2a2SStefan Roese 		int growth = c->leb_cnt - old_leb_cnt;
3109eefe2a2SStefan Roese 
3119eefe2a2SStefan Roese 		if (c->leb_cnt < old_leb_cnt ||
3129eefe2a2SStefan Roese 		    c->leb_cnt < UBIFS_MIN_LEB_CNT) {
313*0195a7bbSHeiko Schocher 			ubifs_err(c, "bad leb_cnt on master node");
314ff94bc40SHeiko Schocher 			ubifs_dump_node(c, c->mst_node);
3159eefe2a2SStefan Roese 			return -EINVAL;
3169eefe2a2SStefan Roese 		}
3179eefe2a2SStefan Roese 
3189eefe2a2SStefan Roese 		dbg_mnt("Auto resizing (master) from %d LEBs to %d LEBs",
3199eefe2a2SStefan Roese 			old_leb_cnt, c->leb_cnt);
3209eefe2a2SStefan Roese 		c->lst.empty_lebs += growth;
3219eefe2a2SStefan Roese 		c->lst.total_free += growth * (long long)c->leb_size;
3229eefe2a2SStefan Roese 		c->lst.total_dark += growth * (long long)c->dark_wm;
3239eefe2a2SStefan Roese 
3249eefe2a2SStefan Roese 		/*
3259eefe2a2SStefan Roese 		 * Reflect changes back onto the master node. N.B. the master
3269eefe2a2SStefan Roese 		 * node gets written immediately whenever mounting (or
3279eefe2a2SStefan Roese 		 * remounting) in read-write mode, so we do not need to write it
3289eefe2a2SStefan Roese 		 * here.
3299eefe2a2SStefan Roese 		 */
3309eefe2a2SStefan Roese 		c->mst_node->leb_cnt = cpu_to_le32(c->leb_cnt);
3319eefe2a2SStefan Roese 		c->mst_node->empty_lebs = cpu_to_le32(c->lst.empty_lebs);
3329eefe2a2SStefan Roese 		c->mst_node->total_free = cpu_to_le64(c->lst.total_free);
3339eefe2a2SStefan Roese 		c->mst_node->total_dark = cpu_to_le64(c->lst.total_dark);
3349eefe2a2SStefan Roese 	}
3359eefe2a2SStefan Roese 
3369eefe2a2SStefan Roese 	err = validate_master(c);
3379eefe2a2SStefan Roese 	if (err)
3389eefe2a2SStefan Roese 		return err;
3399eefe2a2SStefan Roese 
340ff94bc40SHeiko Schocher #ifndef __UBOOT__
3419eefe2a2SStefan Roese 	err = dbg_old_index_check_init(c, &c->zroot);
342ff94bc40SHeiko Schocher #endif
3439eefe2a2SStefan Roese 
3449eefe2a2SStefan Roese 	return err;
3459eefe2a2SStefan Roese }
346ff94bc40SHeiko Schocher 
347ff94bc40SHeiko Schocher #ifndef __UBOOT__
348ff94bc40SHeiko Schocher /**
349ff94bc40SHeiko Schocher  * ubifs_write_master - write master node.
350ff94bc40SHeiko Schocher  * @c: UBIFS file-system description object
351ff94bc40SHeiko Schocher  *
352*0195a7bbSHeiko Schocher  * This function writes the master node. Returns zero in case of success and a
353*0195a7bbSHeiko Schocher  * negative error code in case of failure. The master node is written twice to
354*0195a7bbSHeiko Schocher  * enable recovery.
355ff94bc40SHeiko Schocher  */
ubifs_write_master(struct ubifs_info * c)356ff94bc40SHeiko Schocher int ubifs_write_master(struct ubifs_info *c)
357ff94bc40SHeiko Schocher {
358ff94bc40SHeiko Schocher 	int err, lnum, offs, len;
359ff94bc40SHeiko Schocher 
360ff94bc40SHeiko Schocher 	ubifs_assert(!c->ro_media && !c->ro_mount);
361ff94bc40SHeiko Schocher 	if (c->ro_error)
362ff94bc40SHeiko Schocher 		return -EROFS;
363ff94bc40SHeiko Schocher 
364ff94bc40SHeiko Schocher 	lnum = UBIFS_MST_LNUM;
365ff94bc40SHeiko Schocher 	offs = c->mst_offs + c->mst_node_alsz;
366ff94bc40SHeiko Schocher 	len = UBIFS_MST_NODE_SZ;
367ff94bc40SHeiko Schocher 
368ff94bc40SHeiko Schocher 	if (offs + UBIFS_MST_NODE_SZ > c->leb_size) {
369ff94bc40SHeiko Schocher 		err = ubifs_leb_unmap(c, lnum);
370ff94bc40SHeiko Schocher 		if (err)
371ff94bc40SHeiko Schocher 			return err;
372ff94bc40SHeiko Schocher 		offs = 0;
373ff94bc40SHeiko Schocher 	}
374ff94bc40SHeiko Schocher 
375ff94bc40SHeiko Schocher 	c->mst_offs = offs;
376ff94bc40SHeiko Schocher 	c->mst_node->highest_inum = cpu_to_le64(c->highest_inum);
377ff94bc40SHeiko Schocher 
378ff94bc40SHeiko Schocher 	err = ubifs_write_node(c, c->mst_node, len, lnum, offs);
379ff94bc40SHeiko Schocher 	if (err)
380ff94bc40SHeiko Schocher 		return err;
381ff94bc40SHeiko Schocher 
382ff94bc40SHeiko Schocher 	lnum += 1;
383ff94bc40SHeiko Schocher 
384ff94bc40SHeiko Schocher 	if (offs == 0) {
385ff94bc40SHeiko Schocher 		err = ubifs_leb_unmap(c, lnum);
386ff94bc40SHeiko Schocher 		if (err)
387ff94bc40SHeiko Schocher 			return err;
388ff94bc40SHeiko Schocher 	}
389ff94bc40SHeiko Schocher 	err = ubifs_write_node(c, c->mst_node, len, lnum, offs);
390ff94bc40SHeiko Schocher 
391ff94bc40SHeiko Schocher 	return err;
392ff94bc40SHeiko Schocher }
393ff94bc40SHeiko Schocher #endif
394