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, | 
