diff options
Diffstat (limited to 'ubifs-utils/fsck.ubifs')
| -rw-r--r-- | ubifs-utils/fsck.ubifs/fsck.ubifs.h | 2 | ||||
| -rw-r--r-- | ubifs-utils/fsck.ubifs/rebuild_fs.c | 106 | 
2 files changed, 86 insertions, 22 deletions
| diff --git a/ubifs-utils/fsck.ubifs/fsck.ubifs.h b/ubifs-utils/fsck.ubifs/fsck.ubifs.h index a3b755b..cb7b400 100644 --- a/ubifs-utils/fsck.ubifs/fsck.ubifs.h +++ b/ubifs-utils/fsck.ubifs/fsck.ubifs.h @@ -181,10 +181,12 @@ 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   */  struct ubifs_rebuild_info {  	unsigned long *used_lebs; +	struct ubifs_lprops *lpts;  	struct rb_root scanned_files;  }; diff --git a/ubifs-utils/fsck.ubifs/rebuild_fs.c b/ubifs-utils/fsck.ubifs/rebuild_fs.c index 3be0844..1b03d6c 100644 --- a/ubifs-utils/fsck.ubifs/rebuild_fs.c +++ b/ubifs-utils/fsck.ubifs/rebuild_fs.c @@ -58,9 +58,18 @@ static int init_rebuild_info(struct ubifs_info *c)  		log_err(c, errno, "can not allocate bitmap of used lebs");  		goto free_rebuild;  	} +	FSCK(c)->rebuild->lpts = kzalloc(sizeof(struct ubifs_lprops) * c->main_lebs, +					 GFP_KERNEL); +	if (!FSCK(c)->rebuild->lpts) { +		err = -ENOMEM; +		log_err(c, errno, "can not allocate lpts"); +		goto free_used_lebs; +	}  	return 0; +free_used_lebs: +	kfree(FSCK(c)->rebuild->used_lebs);  free_rebuild:  	kfree(FSCK(c)->rebuild);  free_sbuf: @@ -70,6 +79,7 @@ free_sbuf:  static void destroy_rebuild_info(struct ubifs_info *c)  { +	kfree(FSCK(c)->rebuild->lpts);  	kfree(FSCK(c)->rebuild->used_lebs);  	kfree(FSCK(c)->rebuild);  	vfree(c->sbuf); @@ -461,9 +471,13 @@ static void remove_del_nodes(struct ubifs_info *c, struct scanned_info *si)  		valid_ino_node = lookup_valid_ino_node(c, si, del_ino_node);  		if (valid_ino_node) { -			int lnum = del_ino_node->header.lnum; +			int lnum = del_ino_node->header.lnum - c->main_first; +			int pos = del_ino_node->header.offs + +				  ALIGN(del_ino_node->header.len, 8); -			set_bit(lnum - c->main_first, FSCK(c)->rebuild->used_lebs); +			set_bit(lnum, FSCK(c)->rebuild->used_lebs); +			FSCK(c)->rebuild->lpts[lnum].end = +				max_t(int, FSCK(c)->rebuild->lpts[lnum].end, pos);  			rb_erase(&valid_ino_node->rb, &si->valid_inos);  			kfree(valid_ino_node);  		} @@ -479,9 +493,13 @@ static void remove_del_nodes(struct ubifs_info *c, struct scanned_info *si)  		valid_dent_node = lookup_valid_dent_node(c, si, del_dent_node);  		if (valid_dent_node) { -			int lnum = del_dent_node->header.lnum; +			int lnum = del_dent_node->header.lnum - c->main_first; +			int pos = del_dent_node->header.offs + +				  ALIGN(del_dent_node->header.len, 8); -			set_bit(lnum - c->main_first, FSCK(c)->rebuild->used_lebs); +			set_bit(lnum, FSCK(c)->rebuild->used_lebs); +			FSCK(c)->rebuild->lpts[lnum].end = +				max_t(int, FSCK(c)->rebuild->lpts[lnum].end, pos);  			rb_erase(&valid_dent_node->rb, &si->valid_dents);  			kfree(valid_dent_node);  		} @@ -667,10 +685,21 @@ static const char *get_file_name(struct ubifs_info *c, struct scanned_file *file  	return name;  } +static void parse_node_location(struct ubifs_info *c, struct scanned_node *sn) +{ +	int lnum, pos; + +	lnum = sn->lnum - c->main_first; +	pos = sn->offs + ALIGN(sn->len, 8); + +	set_bit(lnum, FSCK(c)->rebuild->used_lebs); +	FSCK(c)->rebuild->lpts[lnum].end = max_t(int, +					FSCK(c)->rebuild->lpts[lnum].end, pos); +} +  static void record_file_used_lebs(struct ubifs_info *c,  				  struct scanned_file *file)  { -	int lnum;  	struct rb_node *node;  	struct scanned_file *xattr_file;  	struct scanned_dent_node *dent_node; @@ -682,26 +711,21 @@ static void record_file_used_lebs(struct ubifs_info *c,  		 ubifs_get_type_name(ubifs_get_dent_type(file->ino.mode)),  		 c->dev_name); -	lnum = file->ino.header.lnum; -	set_bit(lnum - c->main_first, FSCK(c)->rebuild->used_lebs); +	parse_node_location(c, &file->ino.header); -	if (file->trun.header.exist) { -		lnum = file->trun.header.lnum; -		set_bit(lnum - c->main_first, FSCK(c)->rebuild->used_lebs); -	} +	if (file->trun.header.exist) +		parse_node_location(c, &file->trun.header);  	for (node = rb_first(&file->data_nodes); node; node = rb_next(node)) {  		data_node = rb_entry(node, struct scanned_data_node, rb); -		lnum = data_node->header.lnum; -		set_bit(lnum - c->main_first, FSCK(c)->rebuild->used_lebs); +		parse_node_location(c, &data_node->header);  	}  	for (node = rb_first(&file->dent_nodes); node; node = rb_next(node)) {  		dent_node = rb_entry(node, struct scanned_dent_node, rb); -		lnum = dent_node->header.lnum; -		set_bit(lnum - c->main_first, FSCK(c)->rebuild->used_lebs); +		parse_node_location(c, &dent_node->header);  	}  	for (node = rb_first(&file->xattr_files); node; node = rb_next(node)) { @@ -712,23 +736,57 @@ static void record_file_used_lebs(struct ubifs_info *c,  }  /** - * record_used_lebs - record used LEBs. + * traverse_files_and_nodes - traverse all nodes from valid files.   * @c: UBIFS file-system description object   * - * This function records all used LEBs which may hold useful nodes, then left - * unused LEBs could be taken for storing new index tree. + * This function traverses all nodes from valid files and does following + * things: + * 1. Record all used LEBs which may hold useful nodes, then left unused + *    LEBs could be taken for storing new index tree. + * 2. Re-write data to prevent failed gc scanning in the subsequent mounting + *    process caused by corrupted data.   */ -static void record_used_lebs(struct ubifs_info *c) +static int traverse_files_and_nodes(struct ubifs_info *c)  { +	int i, err = 0;  	struct rb_node *node;  	struct scanned_file *file;  	struct rb_root *tree = &FSCK(c)->rebuild->scanned_files; +	log_out(c, "Record used LEBs");  	for (node = rb_first(tree); node; node = rb_next(node)) {  		file = rb_entry(node, struct scanned_file, rb);  		record_file_used_lebs(c, file);  	} + +	/* Re-write data. */ +	log_out(c, "Re-write data"); +	for (i = 0; i < c->main_lebs; ++i) { +		int lnum, len, end; + +		if (!test_bit(i, FSCK(c)->rebuild->used_lebs)) +			continue; + +		lnum = i + c->main_first; +		dbg_fsck("re-write LEB %d, in %s", lnum, c->dev_name); + +		end = FSCK(c)->rebuild->lpts[i].end; +		len = ALIGN(end, c->min_io_size); + +		err = ubifs_leb_read(c, lnum, c->sbuf, 0, len, 0); +		if (err && err != -EBADMSG) +			return err; + +		if (len > end) +			ubifs_pad(c, c->sbuf + end, len - end); + +		err = ubifs_leb_change(c, lnum, c->sbuf, len); +		if (err) +			return err; +	} + +	return err;  }  /** @@ -789,9 +847,13 @@ int ubifs_rebuild_filesystem(struct ubifs_info *c)  		goto out;  	} -	/* Step 7: Record used LEBs. */ -	log_out(c, "Record used LEBs"); -	record_used_lebs(c); +	/* +	 * Step 7: Record used LEBs. +	 * Step 8: Re-write data to clean corrupted data. +	 */ +	err = traverse_files_and_nodes(c); +	if (err) +		exit_code |= FSCK_ERROR;  out:  	destroy_scanned_info(c, &si); | 
