uboot/fs/ubifs/master.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * This file is part of UBIFS.
   4 *
   5 * Copyright (C) 2006-2008 Nokia Corporation.
   6 *
   7 * Authors: Artem Bityutskiy (Битюцкий Артём)
   8 *          Adrian Hunter
   9 */
  10
  11/* This file implements reading and writing the master node */
  12
  13#include "ubifs.h"
  14#ifdef __UBOOT__
  15#include <log.h>
  16#include <dm/devres.h>
  17#include <linux/compat.h>
  18#include <linux/err.h>
  19#include <ubi_uboot.h>
  20#endif
  21
  22/**
  23 * scan_for_master - search the valid master node.
  24 * @c: UBIFS file-system description object
  25 *
  26 * This function scans the master node LEBs and search for the latest master
  27 * node. Returns zero in case of success, %-EUCLEAN if there master area is
  28 * corrupted and requires recovery, and a negative error code in case of
  29 * failure.
  30 */
  31static int scan_for_master(struct ubifs_info *c)
  32{
  33        struct ubifs_scan_leb *sleb;
  34        struct ubifs_scan_node *snod;
  35        int lnum, offs = 0, nodes_cnt;
  36
  37        lnum = UBIFS_MST_LNUM;
  38
  39        sleb = ubifs_scan(c, lnum, 0, c->sbuf, 1);
  40        if (IS_ERR(sleb))
  41                return PTR_ERR(sleb);
  42        nodes_cnt = sleb->nodes_cnt;
  43        if (nodes_cnt > 0) {
  44                snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node,
  45                                  list);
  46                if (snod->type != UBIFS_MST_NODE)
  47                        goto out_dump;
  48                memcpy(c->mst_node, snod->node, snod->len);
  49                offs = snod->offs;
  50        }
  51        ubifs_scan_destroy(sleb);
  52
  53        lnum += 1;
  54
  55        sleb = ubifs_scan(c, lnum, 0, c->sbuf, 1);
  56        if (IS_ERR(sleb))
  57                return PTR_ERR(sleb);
  58        if (sleb->nodes_cnt != nodes_cnt)
  59                goto out;
  60        if (!sleb->nodes_cnt)
  61                goto out;
  62        snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node, list);
  63        if (snod->type != UBIFS_MST_NODE)
  64                goto out_dump;
  65        if (snod->offs != offs)
  66                goto out;
  67        if (memcmp((void *)c->mst_node + UBIFS_CH_SZ,
  68                   (void *)snod->node + UBIFS_CH_SZ,
  69                   UBIFS_MST_NODE_SZ - UBIFS_CH_SZ))
  70                goto out;
  71        c->mst_offs = offs;
  72        ubifs_scan_destroy(sleb);
  73        return 0;
  74
  75out:
  76        ubifs_scan_destroy(sleb);
  77        return -EUCLEAN;
  78
  79out_dump:
  80        ubifs_err(c, "unexpected node type %d master LEB %d:%d",
  81                  snod->type, lnum, snod->offs);
  82        ubifs_scan_destroy(sleb);
  83        return -EINVAL;
  84}
  85
  86/**
  87 * validate_master - validate master node.
  88 * @c: UBIFS file-system description object
  89 *
  90 * This function validates data which was read from master node. Returns zero
  91 * if the data is all right and %-EINVAL if not.
  92 */
  93static int validate_master(const struct ubifs_info *c)
  94{
  95        long long main_sz;
  96        int err;
  97
  98        if (c->max_sqnum >= SQNUM_WATERMARK) {
  99                err = 1;
 100                goto out;
 101        }
 102
 103        if (c->cmt_no >= c->max_sqnum) {
 104                err = 2;
 105                goto out;
 106        }
 107
 108        if (c->highest_inum >= INUM_WATERMARK) {
 109                err = 3;
 110                goto out;
 111        }
 112
 113        if (c->lhead_lnum < UBIFS_LOG_LNUM ||
 114            c->lhead_lnum >= UBIFS_LOG_LNUM + c->log_lebs ||
 115            c->lhead_offs < 0 || c->lhead_offs >= c->leb_size ||
 116            c->lhead_offs & (c->min_io_size - 1)) {
 117                err = 4;
 118                goto out;
 119        }
 120
 121        if (c->zroot.lnum >= c->leb_cnt || c->zroot.lnum < c->main_first ||
 122            c->zroot.offs >= c->leb_size || c->zroot.offs & 7) {
 123                err = 5;
 124                goto out;
 125        }
 126
 127        if (c->zroot.len < c->ranges[UBIFS_IDX_NODE].min_len ||
 128            c->zroot.len > c->ranges[UBIFS_IDX_NODE].max_len) {
 129                err = 6;
 130                goto out;
 131        }
 132
 133        if (c->gc_lnum >= c->leb_cnt || c->gc_lnum < c->main_first) {
 134                err = 7;
 135                goto out;
 136        }
 137
 138        if (c->ihead_lnum >= c->leb_cnt || c->ihead_lnum < c->main_first ||
 139            c->ihead_offs % c->min_io_size || c->ihead_offs < 0 ||
 140            c->ihead_offs > c->leb_size || c->ihead_offs & 7) {
 141                err = 8;
 142                goto out;
 143        }
 144
 145        main_sz = (long long)c->main_lebs * c->leb_size;
 146        if (c->bi.old_idx_sz & 7 || c->bi.old_idx_sz >= main_sz) {
 147                err = 9;
 148                goto out;
 149        }
 150
 151        if (c->lpt_lnum < c->lpt_first || c->lpt_lnum > c->lpt_last ||
 152            c->lpt_offs < 0 || c->lpt_offs + c->nnode_sz > c->leb_size) {
 153                err = 10;
 154                goto out;
 155        }
 156
 157        if (c->nhead_lnum < c->lpt_first || c->nhead_lnum > c->lpt_last ||
 158            c->nhead_offs < 0 || c->nhead_offs % c->min_io_size ||
 159            c->nhead_offs > c->leb_size) {
 160                err = 11;
 161                goto out;
 162        }
 163
 164        if (c->ltab_lnum < c->lpt_first || c->ltab_lnum > c->lpt_last ||
 165            c->ltab_offs < 0 ||
 166            c->ltab_offs + c->ltab_sz > c->leb_size) {
 167                err = 12;
 168                goto out;
 169        }
 170
 171        if (c->big_lpt && (c->lsave_lnum < c->lpt_first ||
 172            c->lsave_lnum > c->lpt_last || c->lsave_offs < 0 ||
 173            c->lsave_offs + c->lsave_sz > c->leb_size)) {
 174                err = 13;
 175                goto out;
 176        }
 177
 178        if (c->lscan_lnum < c->main_first || c->lscan_lnum >= c->leb_cnt) {
 179                err = 14;
 180                goto out;
 181        }
 182
 183        if (c->lst.empty_lebs < 0 || c->lst.empty_lebs > c->main_lebs - 2) {
 184                err = 15;
 185                goto out;
 186        }
 187
 188        if (c->lst.idx_lebs < 0 || c->lst.idx_lebs > c->main_lebs - 1) {
 189                err = 16;
 190                goto out;
 191        }
 192
 193        if (c->lst.total_free < 0 || c->lst.total_free > main_sz ||
 194            c->lst.total_free & 7) {
 195                err = 17;
 196                goto out;
 197        }
 198
 199        if (c->lst.total_dirty < 0 || (c->lst.total_dirty & 7)) {
 200                err = 18;
 201                goto out;
 202        }
 203
 204        if (c->lst.total_used < 0 || (c->lst.total_used & 7)) {
 205                err = 19;
 206                goto out;
 207        }
 208
 209        if (c->lst.total_free + c->lst.total_dirty +
 210            c->lst.total_used > main_sz) {
 211                err = 20;
 212                goto out;
 213        }
 214
 215        if (c->lst.total_dead + c->lst.total_dark +
 216            c->lst.total_used + c->bi.old_idx_sz > main_sz) {
 217                err = 21;
 218                goto out;
 219        }
 220
 221        if (c->lst.total_dead < 0 ||
 222            c->lst.total_dead > c->lst.total_free + c->lst.total_dirty ||
 223            c->lst.total_dead & 7) {
 224                err = 22;
 225                goto out;
 226        }
 227
 228        if (c->lst.total_dark < 0 ||
 229            c->lst.total_dark > c->lst.total_free + c->lst.total_dirty ||
 230            c->lst.total_dark & 7) {
 231                err = 23;
 232                goto out;
 233        }
 234
 235        return 0;
 236
 237out:
 238        ubifs_err(c, "bad master node at offset %d error %d", c->mst_offs, err);
 239        ubifs_dump_node(c, c->mst_node);
 240        return -EINVAL;
 241}
 242
 243/**
 244 * ubifs_read_master - read master node.
 245 * @c: UBIFS file-system description object
 246 *
 247 * This function finds and reads the master node during file-system mount. If
 248 * the flash is empty, it creates default master node as well. Returns zero in
 249 * case of success and a negative error code in case of failure.
 250 */
 251int ubifs_read_master(struct ubifs_info *c)
 252{
 253        int err, old_leb_cnt;
 254
 255        c->mst_node = kzalloc(c->mst_node_alsz, GFP_KERNEL);
 256        if (!c->mst_node)
 257                return -ENOMEM;
 258
 259        err = scan_for_master(c);
 260        if (err) {
 261                if (err == -EUCLEAN)
 262                        err = ubifs_recover_master_node(c);
 263                if (err)
 264                        /*
 265                         * Note, we do not free 'c->mst_node' here because the
 266                         * unmount routine will take care of this.
 267                         */
 268                        return err;
 269        }
 270
 271        /* Make sure that the recovery flag is clear */
 272        c->mst_node->flags &= cpu_to_le32(~UBIFS_MST_RCVRY);
 273
 274        c->max_sqnum       = le64_to_cpu(c->mst_node->ch.sqnum);
 275        c->highest_inum    = le64_to_cpu(c->mst_node->highest_inum);
 276        c->cmt_no          = le64_to_cpu(c->mst_node->cmt_no);
 277        c->zroot.lnum      = le32_to_cpu(c->mst_node->root_lnum);
 278        c->zroot.offs      = le32_to_cpu(c->mst_node->root_offs);
 279        c->zroot.len       = le32_to_cpu(c->mst_node->root_len);
 280        c->lhead_lnum      = le32_to_cpu(c->mst_node->log_lnum);
 281        c->gc_lnum         = le32_to_cpu(c->mst_node->gc_lnum);
 282        c->ihead_lnum      = le32_to_cpu(c->mst_node->ihead_lnum);
 283        c->ihead_offs      = le32_to_cpu(c->mst_node->ihead_offs);
 284        c->bi.old_idx_sz   = le64_to_cpu(c->mst_node->index_size);
 285        c->lpt_lnum        = le32_to_cpu(c->mst_node->lpt_lnum);
 286        c->lpt_offs        = le32_to_cpu(c->mst_node->lpt_offs);
 287        c->nhead_lnum      = le32_to_cpu(c->mst_node->nhead_lnum);
 288        c->nhead_offs      = le32_to_cpu(c->mst_node->nhead_offs);
 289        c->ltab_lnum       = le32_to_cpu(c->mst_node->ltab_lnum);
 290        c->ltab_offs       = le32_to_cpu(c->mst_node->ltab_offs);
 291        c->lsave_lnum      = le32_to_cpu(c->mst_node->lsave_lnum);
 292        c->lsave_offs      = le32_to_cpu(c->mst_node->lsave_offs);
 293        c->lscan_lnum      = le32_to_cpu(c->mst_node->lscan_lnum);
 294        c->lst.empty_lebs  = le32_to_cpu(c->mst_node->empty_lebs);
 295        c->lst.idx_lebs    = le32_to_cpu(c->mst_node->idx_lebs);
 296        old_leb_cnt        = le32_to_cpu(c->mst_node->leb_cnt);
 297        c->lst.total_free  = le64_to_cpu(c->mst_node->total_free);
 298        c->lst.total_dirty = le64_to_cpu(c->mst_node->total_dirty);
 299        c->lst.total_used  = le64_to_cpu(c->mst_node->total_used);
 300        c->lst.total_dead  = le64_to_cpu(c->mst_node->total_dead);
 301        c->lst.total_dark  = le64_to_cpu(c->mst_node->total_dark);
 302
 303        c->calc_idx_sz = c->bi.old_idx_sz;
 304
 305        if (c->mst_node->flags & cpu_to_le32(UBIFS_MST_NO_ORPHS))
 306                c->no_orphs = 1;
 307
 308        if (old_leb_cnt != c->leb_cnt) {
 309                /* The file system has been resized */
 310                int growth = c->leb_cnt - old_leb_cnt;
 311
 312                if (c->leb_cnt < old_leb_cnt ||
 313                    c->leb_cnt < UBIFS_MIN_LEB_CNT) {
 314                        ubifs_err(c, "bad leb_cnt on master node");
 315                        ubifs_dump_node(c, c->mst_node);
 316                        return -EINVAL;
 317                }
 318
 319                dbg_mnt("Auto resizing (master) from %d LEBs to %d LEBs",
 320                        old_leb_cnt, c->leb_cnt);
 321                c->lst.empty_lebs += growth;
 322                c->lst.total_free += growth * (long long)c->leb_size;
 323                c->lst.total_dark += growth * (long long)c->dark_wm;
 324
 325                /*
 326                 * Reflect changes back onto the master node. N.B. the master
 327                 * node gets written immediately whenever mounting (or
 328                 * remounting) in read-write mode, so we do not need to write it
 329                 * here.
 330                 */
 331                c->mst_node->leb_cnt = cpu_to_le32(c->leb_cnt);
 332                c->mst_node->empty_lebs = cpu_to_le32(c->lst.empty_lebs);
 333                c->mst_node->total_free = cpu_to_le64(c->lst.total_free);
 334                c->mst_node->total_dark = cpu_to_le64(c->lst.total_dark);
 335        }
 336
 337        err = validate_master(c);
 338        if (err)
 339                return err;
 340
 341#ifndef __UBOOT__
 342        err = dbg_old_index_check_init(c, &c->zroot);
 343#endif
 344
 345        return err;
 346}
 347
 348#ifndef __UBOOT__
 349/**
 350 * ubifs_write_master - write master node.
 351 * @c: UBIFS file-system description object
 352 *
 353 * This function writes the master node. Returns zero in case of success and a
 354 * negative error code in case of failure. The master node is written twice to
 355 * enable recovery.
 356 */
 357int ubifs_write_master(struct ubifs_info *c)
 358{
 359        int err, lnum, offs, len;
 360
 361        ubifs_assert(!c->ro_media && !c->ro_mount);
 362        if (c->ro_error)
 363                return -EROFS;
 364
 365        lnum = UBIFS_MST_LNUM;
 366        offs = c->mst_offs + c->mst_node_alsz;
 367        len = UBIFS_MST_NODE_SZ;
 368
 369        if (offs + UBIFS_MST_NODE_SZ > c->leb_size) {
 370                err = ubifs_leb_unmap(c, lnum);
 371                if (err)
 372                        return err;
 373                offs = 0;
 374        }
 375
 376        c->mst_offs = offs;
 377        c->mst_node->highest_inum = cpu_to_le64(c->highest_inum);
 378
 379        err = ubifs_write_node(c, c->mst_node, len, lnum, offs);
 380        if (err)
 381                return err;
 382
 383        lnum += 1;
 384
 385        if (offs == 0) {
 386                err = ubifs_leb_unmap(c, lnum);
 387                if (err)
 388                        return err;
 389        }
 390        err = ubifs_write_node(c, c->mst_node, len, lnum, offs);
 391
 392        return err;
 393}
 394#endif
 395