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