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