diff options
Diffstat (limited to 'ubifs-utils')
| -rw-r--r-- | ubifs-utils/fsck.ubifs/extract_files.c | 2 | ||||
| -rw-r--r-- | ubifs-utils/fsck.ubifs/fsck.ubifs.c | 25 | ||||
| -rw-r--r-- | ubifs-utils/fsck.ubifs/fsck.ubifs.h | 13 | ||||
| -rw-r--r-- | ubifs-utils/fsck.ubifs/load_fs.c | 27 | ||||
| -rw-r--r-- | ubifs-utils/fsck.ubifs/rebuild_fs.c | 42 | ||||
| -rw-r--r-- | ubifs-utils/libubifs/tnc.c | 64 | ||||
| -rw-r--r-- | ubifs-utils/libubifs/ubifs.h | 2 | 
7 files changed, 122 insertions, 53 deletions
| diff --git a/ubifs-utils/fsck.ubifs/extract_files.c b/ubifs-utils/fsck.ubifs/extract_files.c index b8777f6..c3ab2b7 100644 --- a/ubifs-utils/fsck.ubifs/extract_files.c +++ b/ubifs-utils/fsck.ubifs/extract_files.c @@ -1234,7 +1234,7 @@ int check_and_correct_files(struct ubifs_info *c)  	int err;  	struct rb_node *node;  	struct scanned_file *file; -	struct rb_root *tree = &FSCK(c)->rebuild->scanned_files; +	struct rb_root *tree = &FSCK(c)->scanned_files;  	for (node = rb_first(tree); node; node = rb_next(node)) {  		file = rb_entry(node, struct scanned_file, rb); diff --git a/ubifs-utils/fsck.ubifs/fsck.ubifs.c b/ubifs-utils/fsck.ubifs/fsck.ubifs.c index 616ed81..59080d8 100644 --- a/ubifs-utils/fsck.ubifs/fsck.ubifs.c +++ b/ubifs-utils/fsck.ubifs/fsck.ubifs.c @@ -404,6 +404,31 @@ static void destroy_fsck_info(struct ubifs_info *c)  	c->dev_name = NULL;  } +void handle_error(const struct ubifs_info *c, int reason_set) +{ +	bool handled = false; +	unsigned int reason = get_failure_reason_callback(c); + +	clear_failure_reason_callback(c); +	if ((reason_set & HAS_DATA_CORRUPTED) && (reason & FR_DATA_CORRUPTED)) { +		handled = true; +		reason &= ~FR_DATA_CORRUPTED; +		if (fix_problem(c, LOG_CORRUPTED, NULL)) +			FSCK(c)->try_rebuild = true; +	} +	if ((reason_set & HAS_TNC_CORRUPTED) && (reason & FR_TNC_CORRUPTED)) { +		ubifs_assert(c, !handled); +		handled = true; +		reason &= ~FR_TNC_CORRUPTED; +		if (fix_problem(c, TNC_CORRUPTED, NULL)) +			FSCK(c)->try_rebuild = true; +	} + +	ubifs_assert(c, reason == 0); +	if (!handled) +		exit_code |= FSCK_ERROR; +} +  /*   * do_fsck - Check & repair the filesystem.   */ diff --git a/ubifs-utils/fsck.ubifs/fsck.ubifs.h b/ubifs-utils/fsck.ubifs/fsck.ubifs.h index a1c64e3..db43ccc 100644 --- a/ubifs-utils/fsck.ubifs/fsck.ubifs.h +++ b/ubifs-utils/fsck.ubifs/fsck.ubifs.h @@ -40,6 +40,8 @@ enum { NORMAL_MODE = 0, SAFE_MODE, DANGER_MODE0,  enum { SB_CORRUPTED = 0, MST_CORRUPTED, LOG_CORRUPTED, BUD_CORRUPTED,         TNC_CORRUPTED, TNC_DATA_CORRUPTED, ORPHAN_CORRUPTED }; +enum { HAS_DATA_CORRUPTED = 1, HAS_TNC_CORRUPTED = 2 }; +  struct scanned_file;  /** @@ -181,18 +183,14 @@ struct scanned_file {  /**   * ubifs_rebuild_info - UBIFS rebuilding information. - * @used_lebs: a bitmap used for recording used lebs   * @lpts: lprops table - * @scanned_files: tree of all scanned files   * @write_buf: write buffer for LEB @head_lnum   * @head_lnum: current writing LEB number   * @head_offs: current writing position in LEB @head_lnum   * @need_update_lpt: whether to update lpt while writing index nodes   */  struct ubifs_rebuild_info { -	unsigned long *used_lebs;  	struct ubifs_lprops *lpts; -	struct rb_root scanned_files;  	void *write_buf;  	int head_lnum;  	int head_offs; @@ -205,6 +203,8 @@ struct ubifs_rebuild_info {   * @failure_reason: reasons for failed operations   * @lpt_status: the status of lpt, could be: %0(OK), %FR_LPT_CORRUPTED or   *		%FR_LPT_INCORRECT + * @scanned_files: tree of all scanned files + * @used_lebs: a bitmap used for recording used lebs   * @try_rebuild: %true means that try to rebuild fs when fsck failed   * @rebuild: rebuilding-related information   */ @@ -212,6 +212,8 @@ struct ubifs_fsck_info {  	int mode;  	unsigned int failure_reason;  	unsigned int lpt_status; +	struct rb_root scanned_files; +	unsigned long *used_lebs;  	bool try_rebuild;  	struct ubifs_rebuild_info *rebuild;  }; @@ -259,6 +261,9 @@ static inline const char *mode_name(const struct ubifs_info *c)  /* Exit code for fsck program. */  extern int exit_code; +/* fsck.ubifs.c */ +void handle_error(const struct ubifs_info *c, int reason_set); +  /* problem.c */  bool fix_problem(const struct ubifs_info *c, int problem_type, const void *priv); diff --git a/ubifs-utils/fsck.ubifs/load_fs.c b/ubifs-utils/fsck.ubifs/load_fs.c index 5854054..04208a1 100644 --- a/ubifs-utils/fsck.ubifs/load_fs.c +++ b/ubifs-utils/fsck.ubifs/load_fs.c @@ -17,33 +17,6 @@  #include "misc.h"  #include "fsck.ubifs.h" -enum { HAS_DATA_CORRUPTED = 1, HAS_TNC_CORRUPTED = 2 }; - -static void handle_error(const struct ubifs_info *c, int reason_set) -{ -	bool handled = false; -	unsigned int reason = get_failure_reason_callback(c); - -	clear_failure_reason_callback(c); -	if ((reason_set & HAS_DATA_CORRUPTED) && (reason & FR_DATA_CORRUPTED)) { -		handled = true; -		reason &= ~FR_DATA_CORRUPTED; -		if (fix_problem(c, LOG_CORRUPTED, NULL)) -			FSCK(c)->try_rebuild = true; -	} -	if ((reason_set & HAS_TNC_CORRUPTED) && (reason & FR_TNC_CORRUPTED)) { -		ubifs_assert(c, !handled); -		handled = true; -		reason &= ~FR_TNC_CORRUPTED; -		if (fix_problem(c, TNC_CORRUPTED, NULL)) -			FSCK(c)->try_rebuild = true; -	} - -	ubifs_assert(c, reason == 0); -	if (!handled) -		exit_code |= FSCK_ERROR; -} -  int ubifs_load_filesystem(struct ubifs_info *c)  {  	int err; diff --git a/ubifs-utils/fsck.ubifs/rebuild_fs.c b/ubifs-utils/fsck.ubifs/rebuild_fs.c index 382687b..f190517 100644 --- a/ubifs-utils/fsck.ubifs/rebuild_fs.c +++ b/ubifs-utils/fsck.ubifs/rebuild_fs.c @@ -73,10 +73,10 @@ static int init_rebuild_info(struct ubifs_info *c)  		log_err(c, errno, "can not allocate rebuild info");  		goto free_sbuf;  	} -	FSCK(c)->rebuild->scanned_files = RB_ROOT; -	FSCK(c)->rebuild->used_lebs = kcalloc(BITS_TO_LONGS(c->main_lebs), -					      sizeof(unsigned long), GFP_KERNEL); -	if (!FSCK(c)->rebuild->used_lebs) { +	FSCK(c)->scanned_files = RB_ROOT; +	FSCK(c)->used_lebs = kcalloc(BITS_TO_LONGS(c->main_lebs), +				     sizeof(unsigned long), GFP_KERNEL); +	if (!FSCK(c)->used_lebs) {  		err = -ENOMEM;  		log_err(c, errno, "can not allocate bitmap of used lebs");  		goto free_rebuild; @@ -100,7 +100,7 @@ static int init_rebuild_info(struct ubifs_info *c)  free_lpts:  	kfree(FSCK(c)->rebuild->lpts);  free_used_lebs: -	kfree(FSCK(c)->rebuild->used_lebs); +	kfree(FSCK(c)->used_lebs);  free_rebuild:  	kfree(FSCK(c)->rebuild);  free_sbuf: @@ -112,7 +112,7 @@ static void destroy_rebuild_info(struct ubifs_info *c)  {  	vfree(FSCK(c)->rebuild->write_buf);  	kfree(FSCK(c)->rebuild->lpts); -	kfree(FSCK(c)->rebuild->used_lebs); +	kfree(FSCK(c)->used_lebs);  	kfree(FSCK(c)->rebuild);  	vfree(c->sbuf);  } @@ -313,7 +313,7 @@ static int process_scanned_node(struct ubifs_info *c, int lnum,  		return 1;  	} -	tree = &FSCK(c)->rebuild->scanned_files; +	tree = &FSCK(c)->scanned_files;  	return insert_or_update_file(c, tree, sn, key_type(c, key), inum);  } @@ -331,7 +331,7 @@ static void destroy_scanned_info(struct ubifs_info *c, struct scanned_info *si)  	struct scanned_dent_node *dent_node;  	struct rb_node *this; -	destroy_file_tree(c, &FSCK(c)->rebuild->scanned_files); +	destroy_file_tree(c, &FSCK(c)->scanned_files);  	this = rb_first(&si->valid_inos);  	while (this) { @@ -377,7 +377,7 @@ static void destroy_scanned_info(struct ubifs_info *c, struct scanned_info *si)   *   * This function scans nodes from flash, all ino/dent nodes are split   * into valid tree and deleted tree, all trun/data nodes are collected - * into file, the file is inserted into @FSCK(c)->rebuild->scanned_files. + * into file, the file is inserted into @FSCK(c)->scanned_files.   */  static int scan_nodes(struct ubifs_info *c, struct scanned_info *si)  { @@ -495,7 +495,7 @@ static void update_lpt(struct ubifs_info *c, struct scanned_node *sn,  	int index = sn->lnum - c->main_first;  	int pos = sn->offs + ALIGN(sn->len, 8); -	set_bit(index, FSCK(c)->rebuild->used_lebs); +	set_bit(index, FSCK(c)->used_lebs);  	FSCK(c)->rebuild->lpts[index].end = max_t(int,  					FSCK(c)->rebuild->lpts[index].end, pos); @@ -572,7 +572,7 @@ static int add_valid_nodes_into_file(struct ubifs_info *c,  	struct scanned_ino_node *ino_node;  	struct scanned_dent_node *dent_node;  	struct rb_node *this; -	struct rb_root *tree = &FSCK(c)->rebuild->scanned_files; +	struct rb_root *tree = &FSCK(c)->scanned_files;  	this = rb_first(&si->valid_inos);  	while (this) { @@ -621,7 +621,7 @@ static void filter_invalid_files(struct ubifs_info *c)  {  	struct rb_node *node;  	struct scanned_file *file; -	struct rb_root *tree = &FSCK(c)->rebuild->scanned_files; +	struct rb_root *tree = &FSCK(c)->scanned_files;  	LIST_HEAD(tmp_list);  	/* Add all xattr files into a list. */ @@ -678,7 +678,7 @@ static void extract_dentry_tree(struct ubifs_info *c)  {  	struct rb_node *node;  	struct scanned_file *file; -	struct rb_root *tree = &FSCK(c)->rebuild->scanned_files; +	struct rb_root *tree = &FSCK(c)->scanned_files;  	LIST_HEAD(unreachable);  	for (node = rb_first(tree); node; node = rb_next(node)) { @@ -731,7 +731,7 @@ static void init_root_ino(struct ubifs_info *c, struct ubifs_ino_node *ino)  }  /** - * get_free_leb - get a free LEB according to @FSCK(c)->rebuild->used_lebs. + * get_free_leb - get a free LEB according to @FSCK(c)->used_lebs.   * @c: UBIFS file-system description object   *   * This function tries to find a free LEB, lnum is returned if found, otherwise @@ -741,12 +741,12 @@ static int get_free_leb(struct ubifs_info *c)  {  	int lnum; -	lnum = find_next_zero_bit(FSCK(c)->rebuild->used_lebs, c->main_lebs, 0); +	lnum = find_next_zero_bit(FSCK(c)->used_lebs, c->main_lebs, 0);  	if (lnum >= c->main_lebs) {  		ubifs_err(c, "No space left.");  		return -ENOSPC;  	} -	set_bit(lnum, FSCK(c)->rebuild->used_lebs); +	set_bit(lnum, FSCK(c)->used_lebs);  	lnum += c->main_first;  	return lnum; @@ -897,8 +897,8 @@ static int create_root(struct ubifs_info *c)  	file->calc_xnms = file->ino.xnms = le32_to_cpu(ino->xattr_names);  	file->calc_size = file->ino.size = le64_to_cpu(ino->size); -	rb_link_node(&file->rb, NULL, &FSCK(c)->rebuild->scanned_files.rb_node); -	rb_insert_color(&file->rb, &FSCK(c)->rebuild->scanned_files); +	rb_link_node(&file->rb, NULL, &FSCK(c)->scanned_files.rb_node); +	rb_insert_color(&file->rb, &FSCK(c)->scanned_files);  out:  	kfree(ino); @@ -1188,7 +1188,7 @@ static int traverse_files_and_nodes(struct ubifs_info *c)  	int i, err = 0, idx_cnt = 0;  	struct rb_node *node;  	struct scanned_file *file; -	struct rb_root *tree = &FSCK(c)->rebuild->scanned_files; +	struct rb_root *tree = &FSCK(c)->scanned_files;  	struct idx_entry *ie, *tmp_ie;  	LIST_HEAD(idx_list); @@ -1214,7 +1214,7 @@ static int traverse_files_and_nodes(struct ubifs_info *c)  	for (i = 0; i < c->main_lebs; ++i) {  		int lnum, len, end; -		if (!test_bit(i, FSCK(c)->rebuild->used_lebs)) +		if (!test_bit(i, FSCK(c)->used_lebs))  			continue;  		lnum = i + c->main_first; @@ -1268,7 +1268,7 @@ static int build_lpt(struct ubifs_info *c)  	/* Update LPT. */  	for (i = 0; i < c->main_lebs; i++) { -		if (!test_bit(i, FSCK(c)->rebuild->used_lebs) || +		if (!test_bit(i, FSCK(c)->used_lebs) ||  		    c->gc_lnum == i + c->main_first) {  			free = c->leb_size;  			dirty = 0; diff --git a/ubifs-utils/libubifs/tnc.c b/ubifs-utils/libubifs/tnc.c index cd1013d..9277062 100644 --- a/ubifs-utils/libubifs/tnc.c +++ b/ubifs-utils/libubifs/tnc.c @@ -2457,6 +2457,70 @@ int ubifs_tnc_remove_ino(struct ubifs_info *c, ino_t inum)  }  /** + * ubifs_tnc_remove_node - remove an index entry of a node by given position. + * @c: UBIFS file-system description object + * @key: key of node + * @lnum: LEB number of node + * @offs: node offset + * + * Returns %0 on success or negative error code on failure. + */ +int ubifs_tnc_remove_node(struct ubifs_info *c, const union ubifs_key *key, +			  int lnum, int offs) +{ +	int found, n, err = 0; +	struct ubifs_znode *znode; + +	mutex_lock(&c->tnc_mutex); +	dbg_tnck(key, "pos %d:%d, key ", lnum, offs); +	found = lookup_level0_dirty(c, key, &znode, &n); +	if (found < 0) { +		err = found; +		goto out_unlock; +	} +	if (found == 1) { +		struct ubifs_zbranch *zbr = &znode->zbranch[n]; + +		if (zbr->lnum == lnum && zbr->offs == offs) { +			err = tnc_delete(c, znode, n); +		} else if (is_hash_key(c, key)) { +			found = resolve_collision_directly(c, key, &znode, &n, +							   lnum, offs); +			if (found < 0) { +				err = found; +				goto out_unlock; +			} + +			if (found) { +				/* Ensure the znode is dirtied */ +				if (znode->cnext || !ubifs_zn_dirty(znode)) { +					znode = dirty_cow_bottom_up(c, znode); +					if (IS_ERR(znode)) { +						err = PTR_ERR(znode); +						goto out_unlock; +					} +				} +				err = tnc_delete(c, znode, n); +			} else { +				goto not_found; +			} +		} else { +			goto not_found; +		} +	} else { +not_found: +		/* Impossible, the node has been found before being deleted. */ +		ubifs_assert(c, 0); +	} +	if (!err) +		err = dbg_check_tnc(c, 0); + +out_unlock: +	mutex_unlock(&c->tnc_mutex); +	return err; +} + +/**   * ubifs_tnc_next_ent - walk directory or extended attribute entries.   * @c: UBIFS file-system description object   * @key: key of last entry diff --git a/ubifs-utils/libubifs/ubifs.h b/ubifs-utils/libubifs/ubifs.h index 8a506a8..03150cd 100644 --- a/ubifs-utils/libubifs/ubifs.h +++ b/ubifs-utils/libubifs/ubifs.h @@ -1661,6 +1661,8 @@ int ubifs_tnc_remove_nm(struct ubifs_info *c, const union ubifs_key *key,  int ubifs_tnc_remove_range(struct ubifs_info *c, union ubifs_key *from_key,  			   union ubifs_key *to_key);  int ubifs_tnc_remove_ino(struct ubifs_info *c, ino_t inum); +int ubifs_tnc_remove_node(struct ubifs_info *c, const union ubifs_key *key, +			  int lnum, int offs);  struct ubifs_dent_node *ubifs_tnc_next_ent(struct ubifs_info *c,  					   union ubifs_key *key,  					   const struct fscrypt_name *nm); | 
