diff options
| author | Zhihao Cheng <chengzhihao1@huawei.com> | 2024-11-11 17:01:21 +0800 | 
|---|---|---|
| committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2024-11-11 10:32:46 +0100 | 
| commit | 3f8ee068870a046b0dcf2921ed7ee375f405e49f (patch) | |
| tree | 4e7f4059cb04e7c5216154e7235d2fc3edc92165 /ubifs-utils | |
| parent | 410f5bb08c0dd44358822031e59f64b4b840bd9e (diff) | |
fsck.ubifs: Read master node & init lpt
This is the 1/18 step of fsck. Read and check master node, init lpt.
There could be following errors:
 1. corrupted scanning data in master area or invalid master node:
    danger mode with rebuild_fs and normal mode with 'yes' answer will
    turn to rebuild filesystem, other modes will exit.
 2. incorrect space statistics in master node: Set %FR_LPT_INCORRECT for
    for lpt status. Ignore the error.
 3. corrupted lpt: Set %FR_LPT_CORRUPTED for lpt status. Ignore the error.
Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'ubifs-utils')
| -rw-r--r-- | ubifs-utils/fsck.ubifs/fsck.ubifs.c | 5 | ||||
| -rw-r--r-- | ubifs-utils/fsck.ubifs/fsck.ubifs.h | 2 | ||||
| -rw-r--r-- | ubifs-utils/fsck.ubifs/load_fs.c | 78 | ||||
| -rw-r--r-- | ubifs-utils/fsck.ubifs/problem.c | 1 | ||||
| -rw-r--r-- | ubifs-utils/libubifs/lpt.c | 18 | ||||
| -rw-r--r-- | ubifs-utils/libubifs/master.c | 7 | 
6 files changed, 104 insertions, 7 deletions
| diff --git a/ubifs-utils/fsck.ubifs/fsck.ubifs.c b/ubifs-utils/fsck.ubifs/fsck.ubifs.c index e674451..2fd68df 100644 --- a/ubifs-utils/fsck.ubifs/fsck.ubifs.c +++ b/ubifs-utils/fsck.ubifs/fsck.ubifs.c @@ -423,7 +423,10 @@ int main(int argc, char *argv[])  		goto out_destroy_fsck;  	} -	/* Init: Read superblock */ +	/* +	 * Init: Read superblock +	 * Step 1: Read master & init lpt +	 */  	err = ubifs_load_filesystem(c);  	if (err) {  		if (FSCK(c)->try_rebuild) diff --git a/ubifs-utils/fsck.ubifs/fsck.ubifs.h b/ubifs-utils/fsck.ubifs/fsck.ubifs.h index d25ecc2..7f82615 100644 --- a/ubifs-utils/fsck.ubifs/fsck.ubifs.h +++ b/ubifs-utils/fsck.ubifs/fsck.ubifs.h @@ -37,7 +37,7 @@ enum { NORMAL_MODE = 0, SAFE_MODE, DANGER_MODE0,         DANGER_MODE1, REBUILD_MODE, CHECK_MODE };  /* Types of inconsistent problems */ -enum { SB_CORRUPTED = 0 }; +enum { SB_CORRUPTED = 0, MST_CORRUPTED };  struct scanned_file; diff --git a/ubifs-utils/fsck.ubifs/load_fs.c b/ubifs-utils/fsck.ubifs/load_fs.c index 4a06b4c..036e307 100644 --- a/ubifs-utils/fsck.ubifs/load_fs.c +++ b/ubifs-utils/fsck.ubifs/load_fs.c @@ -99,10 +99,81 @@ int ubifs_load_filesystem(struct ubifs_info *c)  		goto out_mounting;  	} +	log_out(c, "Read master & init lpt"); +	err = ubifs_read_master(c); +	if (err) { +		if (test_and_clear_failure_reason_callback(c, FR_DATA_CORRUPTED)) { +			if (fix_problem(c, MST_CORRUPTED)) +				FSCK(c)->try_rebuild = true; +		} else +			exit_code |= FSCK_ERROR; +		goto out_master; +	} + +	init_constants_master(c); + +	if ((c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY)) != 0) { +		ubifs_msg(c, "recovery needed"); +		c->need_recovery = 1; +	} + +	if (c->need_recovery && !c->ro_mount) { +		err = ubifs_recover_inl_heads(c, c->sbuf); +		if (err) { +			exit_code |= FSCK_ERROR; +			goto out_master; +		} +	} + +	err = ubifs_lpt_init(c, 1, !c->ro_mount); +	if (err) { +		exit_code |= FSCK_ERROR; +		goto out_master; +	} + +	if (!c->ro_mount && c->space_fixup) { +		err = ubifs_fixup_free_space(c); +		if (err) { +			exit_code |= FSCK_ERROR; +			goto out_lpt; +		} +	} + +	if (!c->ro_mount && !c->need_recovery) { +		/* +		 * Set the "dirty" flag so that if we reboot uncleanly we +		 * will notice this immediately on the next mount. +		 */ +		c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY); +		err = ubifs_write_master(c); +		if (err) { +			exit_code |= FSCK_ERROR; +			goto out_lpt; +		} +	} + +	if (!c->ro_mount && c->superblock_need_write) { +		err = ubifs_write_sb_node(c, c->sup_node); +		if (err) { +			exit_code |= FSCK_ERROR; +			goto out_lpt; +		} +		c->superblock_need_write = 0; +	} +  	c->mounting = 0;  	return 0; +out_lpt: +	ubifs_lpt_free(c, 0); +out_master: +	c->max_sqnum = 0; +	c->highest_inum = 0; +	c->calc_idx_sz = 0; +	kfree(c->mst_node); +	kfree(c->rcvrd_mst_node); +	free_wbufs(c);  out_mounting:  	c->mounting = 0;  out_free: @@ -118,8 +189,15 @@ out_free:  void ubifs_destroy_filesystem(struct ubifs_info *c)  {  	free_wbufs(c); +	ubifs_lpt_free(c, 0); + +	c->max_sqnum = 0; +	c->highest_inum = 0; +	c->calc_idx_sz = 0;  	kfree(c->cbuf); +	kfree(c->rcvrd_mst_node); +	kfree(c->mst_node);  	kfree(c->ileb_buf);  	kfree(c->sbuf);  	kfree(c->bottom_up_buf); diff --git a/ubifs-utils/fsck.ubifs/problem.c b/ubifs-utils/fsck.ubifs/problem.c index acb9e45..1af6663 100644 --- a/ubifs-utils/fsck.ubifs/problem.c +++ b/ubifs-utils/fsck.ubifs/problem.c @@ -36,6 +36,7 @@ struct fsck_problem {  static const struct fsck_problem problem_table[] = {  	{0, "Corrupted superblock"},	// SB_CORRUPTED +	{PROBLEM_FIXABLE | PROBLEM_MUST_FIX | PROBLEM_DROP_DATA | PROBLEM_NEED_REBUILD, "Corrupted master node"},	// MST_CORRUPTED  };  static void print_problem(const struct ubifs_info *c, diff --git a/ubifs-utils/libubifs/lpt.c b/ubifs-utils/libubifs/lpt.c index c0df7c7..b07f1f7 100644 --- a/ubifs-utils/libubifs/lpt.c +++ b/ubifs-utils/libubifs/lpt.c @@ -1883,8 +1883,13 @@ static int lpt_init_rd(struct ubifs_info *c)  	c->dirty_idx.max_cnt = LPT_HEAP_SZ;  	err = read_ltab(c); -	if (err) -		return err; +	if (err) { +		if (test_and_clear_failure_reason_callback(c, FR_LPT_CORRUPTED) && +		    can_ignore_failure_callback(c, FR_LPT_CORRUPTED)) +			err = 0; +		else +			return err; +	}  	err = lpt_check_hash(c);  	if (err) @@ -1938,8 +1943,13 @@ static int lpt_init_wr(struct ubifs_info *c)  		if (!c->lsave)  			return -ENOMEM;  		err = read_lsave(c); -		if (err) -			return err; +		if (err) { +			if (test_and_clear_failure_reason_callback(c, FR_LPT_CORRUPTED) && +			    can_ignore_failure_callback(c, FR_LPT_CORRUPTED)) +				err = 0; +			else +				return err; +		}  	}  	for (i = 0; i < c->lpt_lebs; i++) diff --git a/ubifs-utils/libubifs/master.c b/ubifs-utils/libubifs/master.c index 61ff4ce..54d2a78 100644 --- a/ubifs-utils/libubifs/master.c +++ b/ubifs-utils/libubifs/master.c @@ -323,7 +323,12 @@ out:  	set_failure_reason_callback(c, reason);  	ubifs_err(c, "bad master node at offset %d error %d", c->mst_offs, err);  	ubifs_dump_node(c, c->mst_node, c->mst_node_alsz); -	return -EINVAL; +	err = -EINVAL; +	if (can_ignore_failure_callback(c, reason)) { +		clear_failure_reason_callback(c); +		err = 0; +	} +	return err;  }  /** | 
