diff options
Diffstat (limited to 'ubifs-utils/libubifs')
-rw-r--r-- | ubifs-utils/libubifs/lpt.c | 9 | ||||
-rw-r--r-- | ubifs-utils/libubifs/lpt_commit.c | 18 | ||||
-rw-r--r-- | ubifs-utils/libubifs/replay.c | 2 | ||||
-rw-r--r-- | ubifs-utils/libubifs/ubifs.h | 5 |
4 files changed, 25 insertions, 9 deletions
diff --git a/ubifs-utils/libubifs/lpt.c b/ubifs-utils/libubifs/lpt.c index fc70cad..8e20a17 100644 --- a/ubifs-utils/libubifs/lpt.c +++ b/ubifs-utils/libubifs/lpt.c @@ -605,6 +605,7 @@ static int calc_pnode_num_from_parent(const struct ubifs_info *c, * @lps: array of logical eraseblock properties * @lp_cnt: the length of @lps * @hash: hash of the LPT is returned here + * @free_ltab: %true means to release c->ltab after creating lpt * * This function creates lpt, the pnode will be initialized based on * corresponding elements in @lps. If there are no corresponding lprops @@ -612,7 +613,7 @@ static int calc_pnode_num_from_parent(const struct ubifs_info *c, * as free state. */ int ubifs_create_lpt(struct ubifs_info *c, struct ubifs_lprops *lps, int lp_cnt, - u8 *hash) + u8 *hash, bool free_ltab) { int lnum, err = 0, i, j, cnt, len, alen, row; int blnum, boffs, bsz, bcnt; @@ -910,10 +911,12 @@ int ubifs_create_lpt(struct ubifs_info *c, struct ubifs_lprops *lps, int lp_cnt, if (c->big_lpt) dbg_lp("LPT lsave is at %d:%d", c->lsave_lnum, c->lsave_offs); out: - c->ltab = NULL; + if (free_ltab || err) { + c->ltab = NULL; + vfree(ltab); + } kfree(desc); kfree(lsave); - vfree(ltab); vfree(buf); kfree(nnode); kfree(pnode); diff --git a/ubifs-utils/libubifs/lpt_commit.c b/ubifs-utils/libubifs/lpt_commit.c index 8a44546..ee84f80 100644 --- a/ubifs-utils/libubifs/lpt_commit.c +++ b/ubifs-utils/libubifs/lpt_commit.c @@ -1599,7 +1599,7 @@ static int dbg_is_node_dirty(struct ubifs_info *c, int node_type, int lnum, * * This function returns %0 on success and a negative error code on failure. */ -static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum) +int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum) { int err, len = c->leb_size, dirty = 0, node_type, node_num, node_len; int ret; @@ -1608,7 +1608,7 @@ static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum) buf = p = __vmalloc(c->leb_size, GFP_NOFS); if (!buf) { ubifs_err(c, "cannot allocate memory for ltab checking"); - return 0; + return -ENOMEM; } dbg_lp("LEB %d", lnum); @@ -1632,20 +1632,30 @@ static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum) continue; } if (!dbg_is_all_ff(p, len)) { + set_failure_reason_callback(c, FR_LPT_CORRUPTED); ubifs_err(c, "invalid empty space in LEB %d at %d", lnum, c->leb_size - len); err = -EINVAL; + goto out; } i = lnum - c->lpt_first; if (len != c->ltab[i].free) { ubifs_err(c, "invalid free space in LEB %d (free %d, expected %d)", - lnum, len, c->ltab[i].free); + lnum, c->ltab[i].free, len); err = -EINVAL; + if (handle_failure_callback(c, FR_H_LTAB_INCORRECT, NULL)) { + c->ltab[i].free = len; + err = 0; + } } if (dirty != c->ltab[i].dirty) { ubifs_err(c, "invalid dirty space in LEB %d (dirty %d, expected %d)", - lnum, dirty, c->ltab[i].dirty); + lnum, c->ltab[i].dirty, dirty); err = -EINVAL; + if (handle_failure_callback(c, FR_H_LTAB_INCORRECT, NULL)) { + c->ltab[i].dirty = dirty; + err = 0; + } } goto out; } diff --git a/ubifs-utils/libubifs/replay.c b/ubifs-utils/libubifs/replay.c index 2741742..3943b32 100644 --- a/ubifs-utils/libubifs/replay.c +++ b/ubifs-utils/libubifs/replay.c @@ -1099,7 +1099,7 @@ out_dump: * This function returns the amount of free space in the index head LEB or a * negative error code. */ -static int take_ihead(struct ubifs_info *c) +int take_ihead(struct ubifs_info *c) { const struct ubifs_lprops *lp; int err, free; diff --git a/ubifs-utils/libubifs/ubifs.h b/ubifs-utils/libubifs/ubifs.h index 45c4105..a4b05a6 100644 --- a/ubifs-utils/libubifs/ubifs.h +++ b/ubifs-utils/libubifs/ubifs.h @@ -1563,6 +1563,7 @@ enum { FR_H_BUD_CORRUPTED = 0, /* Bud LEB is corrupted */ FR_H_TNC_DATA_CORRUPTED, /* Data searched from TNC is corrupted */ FR_H_ORPHAN_CORRUPTED, /* Orphan LEB is corrupted */ + FR_H_LTAB_INCORRECT, /* Lprops table is incorrect */ }; /* Callback functions for failure(which can be handled by fsck) happens. */ static inline void set_failure_reason_callback(const struct ubifs_info *c, @@ -1734,6 +1735,7 @@ int ubifs_fixup_free_space(struct ubifs_info *c); /* replay.c */ int ubifs_validate_entry(struct ubifs_info *c, const struct ubifs_dent_node *dent); +int take_ihead(struct ubifs_info *c); int ubifs_replay_journal(struct ubifs_info *c); /* gc.c */ @@ -1754,7 +1756,7 @@ int ubifs_clear_orphans(struct ubifs_info *c); int ubifs_calc_dflt_lpt_geom(struct ubifs_info *c, int *main_lebs, int *big_lpt); int ubifs_calc_lpt_geom(struct ubifs_info *c); int ubifs_create_lpt(struct ubifs_info *c, struct ubifs_lprops *lps, int lp_cnt, - u8 *hash); + u8 *hash, bool free_ltab); int ubifs_lpt_init(struct ubifs_info *c, int rd, int wr); struct ubifs_lprops *ubifs_lpt_lookup(struct ubifs_info *c, int lnum); struct ubifs_lprops *ubifs_lpt_lookup_dirty(struct ubifs_info *c, int lnum); @@ -1795,6 +1797,7 @@ int ubifs_lpt_end_commit(struct ubifs_info *c); int ubifs_lpt_post_commit(struct ubifs_info *c); void ubifs_free_lpt_nodes(struct ubifs_info *c); void ubifs_lpt_free(struct ubifs_info *c, int wr_only); +int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum); /* lprops.c */ const struct ubifs_lprops *ubifs_change_lp(struct ubifs_info *c, |