LCOV - code coverage report
Current view: top level - fsck.ubifs - load_fs.c (source / functions) Hit Total Coverage
Test: a simple test Lines: 120 165 72.7 %
Date: 2024-06-05 20:10:43 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Copyright (C) 2024, Huawei Technologies Co, Ltd.
       4             :  *
       5             :  * Authors: Zhihao Cheng <chengzhihao1@huawei.com>
       6             :  */
       7             : 
       8             : #include <stdio.h>
       9             : #include <stdlib.h>
      10             : 
      11             : #include "bitops.h"
      12             : #include "kmem.h"
      13             : #include "ubifs.h"
      14             : #include "defs.h"
      15             : #include "debug.h"
      16             : #include "key.h"
      17             : #include "misc.h"
      18             : #include "fsck.ubifs.h"
      19             : 
      20        2340 : int ubifs_load_filesystem(struct ubifs_info *c)
      21             : {
      22             :         int err;
      23             :         size_t sz;
      24             : 
      25        2340 :         err = init_constants_early(c);
      26        2340 :         if (err) {
      27           8 :                 exit_code |= FSCK_ERROR;
      28           8 :                 return err;
      29             :         }
      30             : 
      31        2332 :         err = check_volume_empty(c);
      32        2332 :         if (err <= 0) {
      33           0 :                 exit_code |= FSCK_ERROR;
      34           0 :                 log_err(c, 0, "%s UBI volume!", err < 0 ? "bad" : "empty");
      35           0 :                 return -EINVAL;
      36             :         }
      37             : 
      38        2332 :         if (c->ro_media && !c->ro_mount) {
      39           0 :                 exit_code |= FSCK_ERROR;
      40           0 :                 log_err(c, 0, "cannot read-write on read-only media");
      41           0 :                 return -EROFS;
      42             :         }
      43             : 
      44        2332 :         err = -ENOMEM;
      45        2332 :         c->bottom_up_buf = kmalloc_array(BOTTOM_UP_HEIGHT, sizeof(int),
      46             :                                          GFP_KERNEL);
      47        2332 :         if (!c->bottom_up_buf) {
      48           0 :                 exit_code |= FSCK_ERROR;
      49           0 :                 log_err(c, errno, "cannot allocate bottom_up_buf");
      50           0 :                 goto out_free;
      51             :         }
      52             : 
      53        2332 :         c->sbuf = vmalloc(c->leb_size);
      54        2332 :         if (!c->sbuf) {
      55           0 :                 exit_code |= FSCK_ERROR;
      56           0 :                 log_err(c, errno, "cannot allocate sbuf");
      57           0 :                 goto out_free;
      58             :         }
      59             : 
      60        2332 :         if (!c->ro_mount) {
      61        2200 :                 c->ileb_buf = vmalloc(c->leb_size);
      62        2200 :                 if (!c->ileb_buf) {
      63           0 :                         exit_code |= FSCK_ERROR;
      64           0 :                         log_err(c, errno, "cannot allocate ileb_buf");
      65           0 :                         goto out_free;
      66             :                 }
      67             :         }
      68             : 
      69        2332 :         c->mounting = 1;
      70             : 
      71        2332 :         log_out(c, "Read superblock");
      72        2332 :         err = ubifs_read_superblock(c);
      73        2332 :         if (err) {
      74          48 :                 if (test_and_clear_failure_reason_callback(c, FR_DATA_CORRUPTED))
      75          48 :                         fix_problem(c, SB_CORRUPTED, NULL);
      76           0 :                 exit_code |= FSCK_ERROR;
      77           0 :                 goto out_mounting;
      78             :         }
      79             : 
      80        2284 :         err = init_constants_sb(c);
      81        2284 :         if (err) {
      82           0 :                 exit_code |= FSCK_ERROR;
      83           0 :                 goto out_mounting;
      84             :         }
      85             : 
      86        2284 :         sz = ALIGN(c->max_idx_node_sz, c->min_io_size) * 2;
      87        2284 :         c->cbuf = kmalloc(sz, GFP_NOFS);
      88        2284 :         if (!c->cbuf) {
      89           0 :                 err = -ENOMEM;
      90           0 :                 exit_code |= FSCK_ERROR;
      91           0 :                 log_err(c, errno, "cannot allocate cbuf");
      92           0 :                 goto out_mounting;
      93             :         }
      94             : 
      95        2284 :         err = alloc_wbufs(c);
      96        2284 :         if (err) {
      97           0 :                 exit_code |= FSCK_ERROR;
      98           0 :                 log_err(c, 0, "cannot allocate wbuf");
      99           0 :                 goto out_mounting;
     100             :         }
     101             : 
     102        2284 :         log_out(c, "Read master & init lpt");
     103        2284 :         err = ubifs_read_master(c);
     104        2284 :         if (err) {
     105          19 :                 if (test_and_clear_failure_reason_callback(c, FR_DATA_CORRUPTED)) {
     106          19 :                         if (fix_problem(c, MST_CORRUPTED, NULL))
     107           7 :                                 FSCK(c)->try_rebuild = true;
     108             :                 } else
     109           0 :                         exit_code |= FSCK_ERROR;
     110             :                 goto out_master;
     111             :         }
     112             : 
     113        2265 :         init_constants_master(c);
     114             : 
     115        2265 :         if ((c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY)) != 0) {
     116        1155 :                 ubifs_msg(c, "recovery needed");
     117        1155 :                 c->need_recovery = 1;
     118             :         }
     119             : 
     120        2265 :         if (c->need_recovery && !c->ro_mount) {
     121        1033 :                 err = ubifs_recover_inl_heads(c, c->sbuf);
     122        1033 :                 if (err) {
     123           0 :                         exit_code |= FSCK_ERROR;
     124           0 :                         goto out_master;
     125             :                 }
     126             :         }
     127             : 
     128        2265 :         err = ubifs_lpt_init(c, 1, !c->ro_mount);
     129        2265 :         if (err) {
     130           0 :                 exit_code |= FSCK_ERROR;
     131           0 :                 goto out_master;
     132             :         }
     133             : 
     134        2265 :         if (!c->ro_mount && c->space_fixup) {
     135         128 :                 err = ubifs_fixup_free_space(c);
     136         128 :                 if (err) {
     137           0 :                         exit_code |= FSCK_ERROR;
     138           0 :                         goto out_lpt;
     139             :                 }
     140             :         }
     141             : 
     142        2265 :         if (!c->ro_mount && !c->need_recovery) {
     143             :                 /*
     144             :                  * Set the "dirty" flag so that if we reboot uncleanly we
     145             :                  * will notice this immediately on the next mount.
     146             :                  */
     147        1100 :                 c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY);
     148        1100 :                 err = ubifs_write_master(c);
     149        1100 :                 if (err) {
     150           2 :                         exit_code |= FSCK_ERROR;
     151           2 :                         goto out_lpt;
     152             :                 }
     153             :         }
     154             : 
     155        2263 :         if (!c->ro_mount && c->superblock_need_write) {
     156         260 :                 err = ubifs_write_sb_node(c, c->sup_node);
     157         260 :                 if (err) {
     158           0 :                         exit_code |= FSCK_ERROR;
     159           0 :                         goto out_lpt;
     160             :                 }
     161         260 :                 c->superblock_need_write = 0;
     162             :         }
     163             : 
     164        2263 :         log_out(c, "Replay journal");
     165        2263 :         err = ubifs_replay_journal(c);
     166        2248 :         if (err) {
     167          49 :                 handle_error(c, HAS_DATA_CORRUPTED | HAS_TNC_CORRUPTED);
     168          11 :                 goto out_journal;
     169             :         }
     170             : 
     171             :         /* Calculate 'min_idx_lebs' after journal replay */
     172        2199 :         c->bi.min_idx_lebs = ubifs_calc_min_idx_lebs(c);
     173             : 
     174        2199 :         log_out(c, "Handle orphan nodes");
     175        2199 :         err = ubifs_mount_orphans(c, c->need_recovery, c->ro_mount);
     176        2196 :         if (err) {
     177           0 :                 handle_error(c, HAS_TNC_CORRUPTED);
     178           0 :                 goto out_orphans;
     179             :         }
     180             : 
     181        2196 :         if (!c->ro_mount) {
     182             :                 int lnum;
     183             : 
     184             :                 /* Check for enough log space */
     185        2092 :                 lnum = c->lhead_lnum + 1;
     186        2092 :                 if (lnum >= UBIFS_LOG_LNUM + c->log_lebs)
     187         387 :                         lnum = UBIFS_LOG_LNUM;
     188        2092 :                 if (lnum == c->ltail_lnum) {
     189          17 :                         log_out(c, "Consolidate log");
     190          17 :                         err = ubifs_consolidate_log(c);
     191          17 :                         if (err) {
     192           0 :                                 handle_error(c, HAS_DATA_CORRUPTED);
     193           0 :                                 goto out_orphans;
     194             :                         }
     195             :                 }
     196             : 
     197        2092 :                 if (c->need_recovery) {
     198         994 :                         log_out(c, "Recover isize");
     199         994 :                         err = ubifs_recover_size(c, true);
     200         994 :                         if (err) {
     201           0 :                                 handle_error(c, HAS_TNC_CORRUPTED);
     202           0 :                                 goto out_orphans;
     203             :                         }
     204             :                 }
     205         104 :         } else if (c->need_recovery) {
     206          94 :                 log_out(c, "Recover isize");
     207          94 :                 err = ubifs_recover_size(c, false);
     208          94 :                 if (err) {
     209           0 :                         handle_error(c, HAS_TNC_CORRUPTED);
     210           0 :                         goto out_orphans;
     211             :                 }
     212             :         }
     213             : 
     214        2196 :         c->mounting = 0;
     215             : 
     216        2196 :         return 0;
     217             : 
     218           0 : out_orphans:
     219           0 :         free_orphans(c);
     220          11 : out_journal:
     221          11 :         destroy_journal(c);
     222          13 : out_lpt:
     223          13 :         ubifs_lpt_free(c, 0);
     224          20 : out_master:
     225          20 :         c->max_sqnum = 0;
     226          20 :         c->highest_inum = 0;
     227          20 :         c->calc_idx_sz = 0;
     228          40 :         kfree(c->mst_node);
     229          40 :         kfree(c->rcvrd_mst_node);
     230          20 :         free_wbufs(c);
     231          20 : out_mounting:
     232          20 :         c->mounting = 0;
     233          20 : out_free:
     234          40 :         kfree(c->cbuf);
     235          40 :         kfree(c->ileb_buf);
     236          40 :         kfree(c->sbuf);
     237          40 :         kfree(c->bottom_up_buf);
     238          40 :         kfree(c->sup_node);
     239             : 
     240          20 :         return err;
     241             : }
     242             : 
     243        1940 : void ubifs_destroy_filesystem(struct ubifs_info *c)
     244             : {
     245        1940 :         destroy_journal(c);
     246        1940 :         free_wbufs(c);
     247        1940 :         free_orphans(c);
     248        1940 :         ubifs_lpt_free(c, 0);
     249             : 
     250        1940 :         c->max_sqnum = 0;
     251        1940 :         c->highest_inum = 0;
     252        1940 :         c->calc_idx_sz = 0;
     253             : 
     254        3880 :         kfree(c->cbuf);
     255        3880 :         kfree(c->rcvrd_mst_node);
     256        3880 :         kfree(c->mst_node);
     257        3880 :         kfree(c->ileb_buf);
     258        3880 :         kfree(c->sbuf);
     259        3880 :         kfree(c->bottom_up_buf);
     260        3880 :         kfree(c->sup_node);
     261        1940 : }

Generated by: LCOV version 1.13