summaryrefslogtreecommitdiff
path: root/ubifs-utils/libubifs
diff options
context:
space:
mode:
Diffstat (limited to 'ubifs-utils/libubifs')
-rw-r--r--ubifs-utils/libubifs/lpt.c9
-rw-r--r--ubifs-utils/libubifs/lpt_commit.c18
-rw-r--r--ubifs-utils/libubifs/replay.c2
-rw-r--r--ubifs-utils/libubifs/ubifs.h5
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,