mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	f2fs: support recording errors into superblock
This patch supports to record detail reason of FSCORRUPTED error into f2fs_super_block.s_errors[]. Signed-off-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
		
							parent
							
								
									a9cfee0ef9
								
							
						
					
					
						commit
						95fa90c9e5
					
				
					 16 changed files with 150 additions and 9 deletions
				
			
		| 
						 | 
					@ -762,6 +762,7 @@ void f2fs_decompress_cluster(struct decompress_io_ctx *dic, bool in_task)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (dic->clen > PAGE_SIZE * dic->nr_cpages - COMPRESS_HEADER_SIZE) {
 | 
						if (dic->clen > PAGE_SIZE * dic->nr_cpages - COMPRESS_HEADER_SIZE) {
 | 
				
			||||||
		ret = -EFSCORRUPTED;
 | 
							ret = -EFSCORRUPTED;
 | 
				
			||||||
 | 
							f2fs_handle_error(sbi, ERROR_FAIL_DECOMPRESSION);
 | 
				
			||||||
		goto out_release;
 | 
							goto out_release;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -950,6 +951,7 @@ static int __f2fs_cluster_blocks(struct inode *inode,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (f2fs_sanity_check_cluster(&dn)) {
 | 
						if (f2fs_sanity_check_cluster(&dn)) {
 | 
				
			||||||
		ret = -EFSCORRUPTED;
 | 
							ret = -EFSCORRUPTED;
 | 
				
			||||||
 | 
							f2fs_handle_error(F2FS_I_SB(inode), ERROR_CORRUPTED_CLUSTER);
 | 
				
			||||||
		goto fail;
 | 
							goto fail;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -705,8 +705,10 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!f2fs_is_valid_blkaddr(fio->sbi, fio->new_blkaddr,
 | 
						if (!f2fs_is_valid_blkaddr(fio->sbi, fio->new_blkaddr,
 | 
				
			||||||
			fio->is_por ? META_POR : (__is_meta_io(fio) ?
 | 
								fio->is_por ? META_POR : (__is_meta_io(fio) ?
 | 
				
			||||||
			META_GENERIC : DATA_GENERIC_ENHANCE)))
 | 
								META_GENERIC : DATA_GENERIC_ENHANCE))) {
 | 
				
			||||||
 | 
							f2fs_handle_error(fio->sbi, ERROR_INVALID_BLKADDR);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	trace_f2fs_submit_page_bio(page, fio);
 | 
						trace_f2fs_submit_page_bio(page, fio);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -906,8 +908,10 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio)
 | 
				
			||||||
			fio->encrypted_page : fio->page;
 | 
								fio->encrypted_page : fio->page;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!f2fs_is_valid_blkaddr(fio->sbi, fio->new_blkaddr,
 | 
						if (!f2fs_is_valid_blkaddr(fio->sbi, fio->new_blkaddr,
 | 
				
			||||||
			__is_meta_io(fio) ? META_GENERIC : DATA_GENERIC))
 | 
								__is_meta_io(fio) ? META_GENERIC : DATA_GENERIC)) {
 | 
				
			||||||
 | 
							f2fs_handle_error(fio->sbi, ERROR_INVALID_BLKADDR);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	trace_f2fs_submit_page_bio(page, fio);
 | 
						trace_f2fs_submit_page_bio(page, fio);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1217,6 +1221,8 @@ struct page *f2fs_get_read_data_page(struct inode *inode, pgoff_t index,
 | 
				
			||||||
		if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), dn.data_blkaddr,
 | 
							if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), dn.data_blkaddr,
 | 
				
			||||||
						DATA_GENERIC_ENHANCE_READ)) {
 | 
											DATA_GENERIC_ENHANCE_READ)) {
 | 
				
			||||||
			err = -EFSCORRUPTED;
 | 
								err = -EFSCORRUPTED;
 | 
				
			||||||
 | 
								f2fs_handle_error(F2FS_I_SB(inode),
 | 
				
			||||||
 | 
											ERROR_INVALID_BLKADDR);
 | 
				
			||||||
			goto put_err;
 | 
								goto put_err;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		goto got_it;
 | 
							goto got_it;
 | 
				
			||||||
| 
						 | 
					@ -1237,6 +1243,8 @@ struct page *f2fs_get_read_data_page(struct inode *inode, pgoff_t index,
 | 
				
			||||||
						dn.data_blkaddr,
 | 
											dn.data_blkaddr,
 | 
				
			||||||
						DATA_GENERIC_ENHANCE)) {
 | 
											DATA_GENERIC_ENHANCE)) {
 | 
				
			||||||
		err = -EFSCORRUPTED;
 | 
							err = -EFSCORRUPTED;
 | 
				
			||||||
 | 
							f2fs_handle_error(F2FS_I_SB(inode),
 | 
				
			||||||
 | 
										ERROR_INVALID_BLKADDR);
 | 
				
			||||||
		goto put_err;
 | 
							goto put_err;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
got_it:
 | 
					got_it:
 | 
				
			||||||
| 
						 | 
					@ -1550,6 +1558,7 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map,
 | 
				
			||||||
	if (__is_valid_data_blkaddr(blkaddr) &&
 | 
						if (__is_valid_data_blkaddr(blkaddr) &&
 | 
				
			||||||
		!f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC_ENHANCE)) {
 | 
							!f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC_ENHANCE)) {
 | 
				
			||||||
		err = -EFSCORRUPTED;
 | 
							err = -EFSCORRUPTED;
 | 
				
			||||||
 | 
							f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
 | 
				
			||||||
		goto sync_out;
 | 
							goto sync_out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1595,6 +1604,8 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map,
 | 
				
			||||||
					(flag != F2FS_GET_BLOCK_FIEMAP ||
 | 
										(flag != F2FS_GET_BLOCK_FIEMAP ||
 | 
				
			||||||
					IS_ENABLED(CONFIG_F2FS_CHECK_FS))) {
 | 
										IS_ENABLED(CONFIG_F2FS_CHECK_FS))) {
 | 
				
			||||||
				err = -EFSCORRUPTED;
 | 
									err = -EFSCORRUPTED;
 | 
				
			||||||
 | 
									f2fs_handle_error(sbi,
 | 
				
			||||||
 | 
											ERROR_CORRUPTED_CLUSTER);
 | 
				
			||||||
				goto sync_out;
 | 
									goto sync_out;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (flag == F2FS_GET_BLOCK_BMAP) {
 | 
								if (flag == F2FS_GET_BLOCK_BMAP) {
 | 
				
			||||||
| 
						 | 
					@ -2076,6 +2087,8 @@ static int f2fs_read_single_page(struct inode *inode, struct page *page,
 | 
				
			||||||
		if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), block_nr,
 | 
							if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), block_nr,
 | 
				
			||||||
						DATA_GENERIC_ENHANCE_READ)) {
 | 
											DATA_GENERIC_ENHANCE_READ)) {
 | 
				
			||||||
			ret = -EFSCORRUPTED;
 | 
								ret = -EFSCORRUPTED;
 | 
				
			||||||
 | 
								f2fs_handle_error(F2FS_I_SB(inode),
 | 
				
			||||||
 | 
											ERROR_INVALID_BLKADDR);
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
| 
						 | 
					@ -2619,8 +2632,11 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
 | 
				
			||||||
		fio->old_blkaddr = ei.blk + page->index - ei.fofs;
 | 
							fio->old_blkaddr = ei.blk + page->index - ei.fofs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr,
 | 
							if (!f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr,
 | 
				
			||||||
						DATA_GENERIC_ENHANCE))
 | 
											DATA_GENERIC_ENHANCE)) {
 | 
				
			||||||
 | 
								f2fs_handle_error(fio->sbi,
 | 
				
			||||||
 | 
											ERROR_INVALID_BLKADDR);
 | 
				
			||||||
			return -EFSCORRUPTED;
 | 
								return -EFSCORRUPTED;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ipu_force = true;
 | 
							ipu_force = true;
 | 
				
			||||||
		fio->need_lock = LOCK_DONE;
 | 
							fio->need_lock = LOCK_DONE;
 | 
				
			||||||
| 
						 | 
					@ -2648,6 +2664,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
 | 
				
			||||||
		!f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr,
 | 
							!f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr,
 | 
				
			||||||
						DATA_GENERIC_ENHANCE)) {
 | 
											DATA_GENERIC_ENHANCE)) {
 | 
				
			||||||
		err = -EFSCORRUPTED;
 | 
							err = -EFSCORRUPTED;
 | 
				
			||||||
 | 
							f2fs_handle_error(fio->sbi, ERROR_INVALID_BLKADDR);
 | 
				
			||||||
		goto out_writepage;
 | 
							goto out_writepage;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3561,6 +3578,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
 | 
				
			||||||
		if (!f2fs_is_valid_blkaddr(sbi, blkaddr,
 | 
							if (!f2fs_is_valid_blkaddr(sbi, blkaddr,
 | 
				
			||||||
				DATA_GENERIC_ENHANCE_READ)) {
 | 
									DATA_GENERIC_ENHANCE_READ)) {
 | 
				
			||||||
			err = -EFSCORRUPTED;
 | 
								err = -EFSCORRUPTED;
 | 
				
			||||||
 | 
								f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
 | 
				
			||||||
			goto fail;
 | 
								goto fail;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		err = f2fs_submit_page_read(inode, page, blkaddr, 0, true);
 | 
							err = f2fs_submit_page_read(inode, page, blkaddr, 0, true);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1041,6 +1041,7 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
 | 
				
			||||||
				  __func__, le16_to_cpu(de->name_len));
 | 
									  __func__, le16_to_cpu(de->name_len));
 | 
				
			||||||
			set_sbi_flag(sbi, SBI_NEED_FSCK);
 | 
								set_sbi_flag(sbi, SBI_NEED_FSCK);
 | 
				
			||||||
			err = -EFSCORRUPTED;
 | 
								err = -EFSCORRUPTED;
 | 
				
			||||||
 | 
								f2fs_handle_error(sbi, ERROR_CORRUPTED_DIRENT);
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1815,6 +1815,10 @@ struct f2fs_sb_info {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct workqueue_struct *post_read_wq;	/* post read workqueue */
 | 
						struct workqueue_struct *post_read_wq;	/* post read workqueue */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unsigned char errors[MAX_F2FS_ERRORS];	/* error flags */
 | 
				
			||||||
 | 
						spinlock_t error_lock;			/* protect errors array */
 | 
				
			||||||
 | 
						bool error_dirty;			/* errors of sb is dirty */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct kmem_cache *inline_xattr_slab;	/* inline xattr entry */
 | 
						struct kmem_cache *inline_xattr_slab;	/* inline xattr entry */
 | 
				
			||||||
	unsigned int inline_xattr_slab_size;	/* default inline xattr slab size */
 | 
						unsigned int inline_xattr_slab_size;	/* default inline xattr slab size */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3557,6 +3561,7 @@ int f2fs_quota_sync(struct super_block *sb, int type);
 | 
				
			||||||
loff_t max_file_blocks(struct inode *inode);
 | 
					loff_t max_file_blocks(struct inode *inode);
 | 
				
			||||||
void f2fs_quota_off_umount(struct super_block *sb);
 | 
					void f2fs_quota_off_umount(struct super_block *sb);
 | 
				
			||||||
void f2fs_handle_stop(struct f2fs_sb_info *sbi, unsigned char reason);
 | 
					void f2fs_handle_stop(struct f2fs_sb_info *sbi, unsigned char reason);
 | 
				
			||||||
 | 
					void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error);
 | 
				
			||||||
int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover);
 | 
					int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover);
 | 
				
			||||||
int f2fs_sync_fs(struct super_block *sb, int sync);
 | 
					int f2fs_sync_fs(struct super_block *sb, int sync);
 | 
				
			||||||
int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi);
 | 
					int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1156,6 +1156,7 @@ static int __read_out_blkaddrs(struct inode *inode, block_t *blkaddr,
 | 
				
			||||||
			!f2fs_is_valid_blkaddr(sbi, *blkaddr,
 | 
								!f2fs_is_valid_blkaddr(sbi, *blkaddr,
 | 
				
			||||||
					DATA_GENERIC_ENHANCE)) {
 | 
										DATA_GENERIC_ENHANCE)) {
 | 
				
			||||||
			f2fs_put_dnode(&dn);
 | 
								f2fs_put_dnode(&dn);
 | 
				
			||||||
 | 
								f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
 | 
				
			||||||
			return -EFSCORRUPTED;
 | 
								return -EFSCORRUPTED;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1440,6 +1441,7 @@ static int f2fs_do_zero_range(struct dnode_of_data *dn, pgoff_t start,
 | 
				
			||||||
		if (!f2fs_is_valid_blkaddr(sbi, dn->data_blkaddr,
 | 
							if (!f2fs_is_valid_blkaddr(sbi, dn->data_blkaddr,
 | 
				
			||||||
					DATA_GENERIC_ENHANCE)) {
 | 
										DATA_GENERIC_ENHANCE)) {
 | 
				
			||||||
			ret = -EFSCORRUPTED;
 | 
								ret = -EFSCORRUPTED;
 | 
				
			||||||
 | 
								f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3323,8 +3325,10 @@ static int release_compress_blocks(struct dnode_of_data *dn, pgoff_t count)
 | 
				
			||||||
		if (!__is_valid_data_blkaddr(blkaddr))
 | 
							if (!__is_valid_data_blkaddr(blkaddr))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		if (unlikely(!f2fs_is_valid_blkaddr(sbi, blkaddr,
 | 
							if (unlikely(!f2fs_is_valid_blkaddr(sbi, blkaddr,
 | 
				
			||||||
					DATA_GENERIC_ENHANCE)))
 | 
										DATA_GENERIC_ENHANCE))) {
 | 
				
			||||||
 | 
								f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
 | 
				
			||||||
			return -EFSCORRUPTED;
 | 
								return -EFSCORRUPTED;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (count) {
 | 
						while (count) {
 | 
				
			||||||
| 
						 | 
					@ -3485,8 +3489,10 @@ static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count)
 | 
				
			||||||
		if (!__is_valid_data_blkaddr(blkaddr))
 | 
							if (!__is_valid_data_blkaddr(blkaddr))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		if (unlikely(!f2fs_is_valid_blkaddr(sbi, blkaddr,
 | 
							if (unlikely(!f2fs_is_valid_blkaddr(sbi, blkaddr,
 | 
				
			||||||
					DATA_GENERIC_ENHANCE)))
 | 
										DATA_GENERIC_ENHANCE))) {
 | 
				
			||||||
 | 
								f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
 | 
				
			||||||
			return -EFSCORRUPTED;
 | 
								return -EFSCORRUPTED;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (count) {
 | 
						while (count) {
 | 
				
			||||||
| 
						 | 
					@ -3758,6 +3764,8 @@ static int f2fs_sec_trim_file(struct file *filp, unsigned long arg)
 | 
				
			||||||
						DATA_GENERIC_ENHANCE)) {
 | 
											DATA_GENERIC_ENHANCE)) {
 | 
				
			||||||
				ret = -EFSCORRUPTED;
 | 
									ret = -EFSCORRUPTED;
 | 
				
			||||||
				f2fs_put_dnode(&dn);
 | 
									f2fs_put_dnode(&dn);
 | 
				
			||||||
 | 
									f2fs_handle_error(sbi,
 | 
				
			||||||
 | 
											ERROR_INVALID_BLKADDR);
 | 
				
			||||||
				goto out;
 | 
									goto out;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1164,6 +1164,7 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
 | 
				
			||||||
		if (unlikely(!f2fs_is_valid_blkaddr(sbi, dn.data_blkaddr,
 | 
							if (unlikely(!f2fs_is_valid_blkaddr(sbi, dn.data_blkaddr,
 | 
				
			||||||
						DATA_GENERIC_ENHANCE_READ))) {
 | 
											DATA_GENERIC_ENHANCE_READ))) {
 | 
				
			||||||
			err = -EFSCORRUPTED;
 | 
								err = -EFSCORRUPTED;
 | 
				
			||||||
 | 
								f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
 | 
				
			||||||
			goto put_page;
 | 
								goto put_page;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		goto got_it;
 | 
							goto got_it;
 | 
				
			||||||
| 
						 | 
					@ -1182,6 +1183,7 @@ static int ra_data_block(struct inode *inode, pgoff_t index)
 | 
				
			||||||
	if (unlikely(!f2fs_is_valid_blkaddr(sbi, dn.data_blkaddr,
 | 
						if (unlikely(!f2fs_is_valid_blkaddr(sbi, dn.data_blkaddr,
 | 
				
			||||||
						DATA_GENERIC_ENHANCE))) {
 | 
											DATA_GENERIC_ENHANCE))) {
 | 
				
			||||||
		err = -EFSCORRUPTED;
 | 
							err = -EFSCORRUPTED;
 | 
				
			||||||
 | 
							f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
 | 
				
			||||||
		goto put_page;
 | 
							goto put_page;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
got_it:
 | 
					got_it:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -160,6 +160,7 @@ int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page)
 | 
				
			||||||
		set_sbi_flag(fio.sbi, SBI_NEED_FSCK);
 | 
							set_sbi_flag(fio.sbi, SBI_NEED_FSCK);
 | 
				
			||||||
		f2fs_warn(fio.sbi, "%s: corrupted inline inode ino=%lx, i_addr[0]:0x%x, run fsck to fix.",
 | 
							f2fs_warn(fio.sbi, "%s: corrupted inline inode ino=%lx, i_addr[0]:0x%x, run fsck to fix.",
 | 
				
			||||||
			  __func__, dn->inode->i_ino, dn->data_blkaddr);
 | 
								  __func__, dn->inode->i_ino, dn->data_blkaddr);
 | 
				
			||||||
 | 
							f2fs_handle_error(fio.sbi, ERROR_INVALID_BLKADDR);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -412,6 +413,7 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct page *ipage,
 | 
				
			||||||
		set_sbi_flag(F2FS_P_SB(page), SBI_NEED_FSCK);
 | 
							set_sbi_flag(F2FS_P_SB(page), SBI_NEED_FSCK);
 | 
				
			||||||
		f2fs_warn(F2FS_P_SB(page), "%s: corrupted inline inode ino=%lx, i_addr[0]:0x%x, run fsck to fix.",
 | 
							f2fs_warn(F2FS_P_SB(page), "%s: corrupted inline inode ino=%lx, i_addr[0]:0x%x, run fsck to fix.",
 | 
				
			||||||
			  __func__, dir->i_ino, dn.data_blkaddr);
 | 
								  __func__, dir->i_ino, dn.data_blkaddr);
 | 
				
			||||||
 | 
							f2fs_handle_error(F2FS_P_SB(page), ERROR_INVALID_BLKADDR);
 | 
				
			||||||
		err = -EFSCORRUPTED;
 | 
							err = -EFSCORRUPTED;
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,8 +81,10 @@ static int __written_first_block(struct f2fs_sb_info *sbi,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!__is_valid_data_blkaddr(addr))
 | 
						if (!__is_valid_data_blkaddr(addr))
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
	if (!f2fs_is_valid_blkaddr(sbi, addr, DATA_GENERIC_ENHANCE))
 | 
						if (!f2fs_is_valid_blkaddr(sbi, addr, DATA_GENERIC_ENHANCE)) {
 | 
				
			||||||
 | 
							f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -415,6 +417,7 @@ static int do_read_inode(struct inode *inode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!sanity_check_inode(inode, node_page)) {
 | 
						if (!sanity_check_inode(inode, node_page)) {
 | 
				
			||||||
		f2fs_put_page(node_page, 1);
 | 
							f2fs_put_page(node_page, 1);
 | 
				
			||||||
 | 
							f2fs_handle_error(sbi, ERROR_CORRUPTED_INODE);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -510,6 +513,7 @@ struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
 | 
				
			||||||
			ret = -EFSCORRUPTED;
 | 
								ret = -EFSCORRUPTED;
 | 
				
			||||||
			trace_f2fs_iget_exit(inode, ret);
 | 
								trace_f2fs_iget_exit(inode, ret);
 | 
				
			||||||
			iput(inode);
 | 
								iput(inode);
 | 
				
			||||||
 | 
								f2fs_handle_error(sbi, ERROR_CORRUPTED_INODE);
 | 
				
			||||||
			return ERR_PTR(ret);
 | 
								return ERR_PTR(ret);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,6 +36,7 @@ int f2fs_check_nid_range(struct f2fs_sb_info *sbi, nid_t nid)
 | 
				
			||||||
		set_sbi_flag(sbi, SBI_NEED_FSCK);
 | 
							set_sbi_flag(sbi, SBI_NEED_FSCK);
 | 
				
			||||||
		f2fs_warn(sbi, "%s: out-of-range nid=%x, run fsck to fix.",
 | 
							f2fs_warn(sbi, "%s: out-of-range nid=%x, run fsck to fix.",
 | 
				
			||||||
			  __func__, nid);
 | 
								  __func__, nid);
 | 
				
			||||||
 | 
							f2fs_handle_error(sbi, ERROR_CORRUPTED_INODE);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -1295,6 +1296,7 @@ struct page *f2fs_new_node_page(struct dnode_of_data *dn, unsigned int ofs)
 | 
				
			||||||
	if (unlikely(new_ni.blk_addr != NULL_ADDR)) {
 | 
						if (unlikely(new_ni.blk_addr != NULL_ADDR)) {
 | 
				
			||||||
		err = -EFSCORRUPTED;
 | 
							err = -EFSCORRUPTED;
 | 
				
			||||||
		set_sbi_flag(sbi, SBI_NEED_FSCK);
 | 
							set_sbi_flag(sbi, SBI_NEED_FSCK);
 | 
				
			||||||
 | 
							f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
 | 
				
			||||||
		goto fail;
 | 
							goto fail;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -507,6 +507,7 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
 | 
				
			||||||
	if (ofs_in_node >= max_addrs) {
 | 
						if (ofs_in_node >= max_addrs) {
 | 
				
			||||||
		f2fs_err(sbi, "Inconsistent ofs_in_node:%u in summary, ino:%lu, nid:%u, max:%u",
 | 
							f2fs_err(sbi, "Inconsistent ofs_in_node:%u in summary, ino:%lu, nid:%u, max:%u",
 | 
				
			||||||
			ofs_in_node, dn->inode->i_ino, nid, max_addrs);
 | 
								ofs_in_node, dn->inode->i_ino, nid, max_addrs);
 | 
				
			||||||
 | 
							f2fs_handle_error(sbi, ERROR_INCONSISTENT_SUMMARY);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -637,6 +638,7 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
 | 
				
			||||||
			  inode->i_ino, ofs_of_node(dn.node_page),
 | 
								  inode->i_ino, ofs_of_node(dn.node_page),
 | 
				
			||||||
			  ofs_of_node(page));
 | 
								  ofs_of_node(page));
 | 
				
			||||||
		err = -EFSCORRUPTED;
 | 
							err = -EFSCORRUPTED;
 | 
				
			||||||
 | 
							f2fs_handle_error(sbi, ERROR_INCONSISTENT_FOOTER);
 | 
				
			||||||
		goto err;
 | 
							goto err;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -649,12 +651,14 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
 | 
				
			||||||
		if (__is_valid_data_blkaddr(src) &&
 | 
							if (__is_valid_data_blkaddr(src) &&
 | 
				
			||||||
			!f2fs_is_valid_blkaddr(sbi, src, META_POR)) {
 | 
								!f2fs_is_valid_blkaddr(sbi, src, META_POR)) {
 | 
				
			||||||
			err = -EFSCORRUPTED;
 | 
								err = -EFSCORRUPTED;
 | 
				
			||||||
 | 
								f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
 | 
				
			||||||
			goto err;
 | 
								goto err;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (__is_valid_data_blkaddr(dest) &&
 | 
							if (__is_valid_data_blkaddr(dest) &&
 | 
				
			||||||
			!f2fs_is_valid_blkaddr(sbi, dest, META_POR)) {
 | 
								!f2fs_is_valid_blkaddr(sbi, dest, META_POR)) {
 | 
				
			||||||
			err = -EFSCORRUPTED;
 | 
								err = -EFSCORRUPTED;
 | 
				
			||||||
 | 
								f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
 | 
				
			||||||
			goto err;
 | 
								goto err;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -712,6 +716,8 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
 | 
				
			||||||
				f2fs_err(sbi, "Inconsistent dest blkaddr:%u, ino:%lu, ofs:%u",
 | 
									f2fs_err(sbi, "Inconsistent dest blkaddr:%u, ino:%lu, ofs:%u",
 | 
				
			||||||
					dest, inode->i_ino, dn.ofs_in_node);
 | 
										dest, inode->i_ino, dn.ofs_in_node);
 | 
				
			||||||
				err = -EFSCORRUPTED;
 | 
									err = -EFSCORRUPTED;
 | 
				
			||||||
 | 
									f2fs_handle_error(sbi,
 | 
				
			||||||
 | 
											ERROR_INVALID_BLKADDR);
 | 
				
			||||||
				goto err;
 | 
									goto err;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -312,6 +312,8 @@ static int __f2fs_commit_atomic_write(struct inode *inode)
 | 
				
			||||||
					DATA_GENERIC_ENHANCE)) {
 | 
										DATA_GENERIC_ENHANCE)) {
 | 
				
			||||||
				f2fs_put_dnode(&dn);
 | 
									f2fs_put_dnode(&dn);
 | 
				
			||||||
				ret = -EFSCORRUPTED;
 | 
									ret = -EFSCORRUPTED;
 | 
				
			||||||
 | 
									f2fs_handle_error(sbi,
 | 
				
			||||||
 | 
											ERROR_INVALID_BLKADDR);
 | 
				
			||||||
				goto out;
 | 
									goto out;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3433,6 +3435,7 @@ int f2fs_inplace_write_data(struct f2fs_io_info *fio)
 | 
				
			||||||
		f2fs_warn(sbi, "%s: incorrect segment(%u) type, run fsck to fix.",
 | 
							f2fs_warn(sbi, "%s: incorrect segment(%u) type, run fsck to fix.",
 | 
				
			||||||
			  __func__, segno);
 | 
								  __func__, segno);
 | 
				
			||||||
		err = -EFSCORRUPTED;
 | 
							err = -EFSCORRUPTED;
 | 
				
			||||||
 | 
							f2fs_handle_error(sbi, ERROR_INCONSISTENT_SUM_TYPE);
 | 
				
			||||||
		goto drop_bio;
 | 
							goto drop_bio;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4381,6 +4384,8 @@ static int build_sit_entries(struct f2fs_sb_info *sbi)
 | 
				
			||||||
			if (se->type >= NR_PERSISTENT_LOG) {
 | 
								if (se->type >= NR_PERSISTENT_LOG) {
 | 
				
			||||||
				f2fs_err(sbi, "Invalid segment type: %u, segno: %u",
 | 
									f2fs_err(sbi, "Invalid segment type: %u, segno: %u",
 | 
				
			||||||
							se->type, start);
 | 
												se->type, start);
 | 
				
			||||||
 | 
									f2fs_handle_error(sbi,
 | 
				
			||||||
 | 
											ERROR_INCONSISTENT_SUM_TYPE);
 | 
				
			||||||
				return -EFSCORRUPTED;
 | 
									return -EFSCORRUPTED;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4417,6 +4422,7 @@ static int build_sit_entries(struct f2fs_sb_info *sbi)
 | 
				
			||||||
			f2fs_err(sbi, "Wrong journal entry on segno %u",
 | 
								f2fs_err(sbi, "Wrong journal entry on segno %u",
 | 
				
			||||||
				 start);
 | 
									 start);
 | 
				
			||||||
			err = -EFSCORRUPTED;
 | 
								err = -EFSCORRUPTED;
 | 
				
			||||||
 | 
								f2fs_handle_error(sbi, ERROR_CORRUPTED_JOURNAL);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4436,6 +4442,7 @@ static int build_sit_entries(struct f2fs_sb_info *sbi)
 | 
				
			||||||
			f2fs_err(sbi, "Invalid segment type: %u, segno: %u",
 | 
								f2fs_err(sbi, "Invalid segment type: %u, segno: %u",
 | 
				
			||||||
							se->type, start);
 | 
												se->type, start);
 | 
				
			||||||
			err = -EFSCORRUPTED;
 | 
								err = -EFSCORRUPTED;
 | 
				
			||||||
 | 
								f2fs_handle_error(sbi, ERROR_INCONSISTENT_SUM_TYPE);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4467,6 +4474,7 @@ static int build_sit_entries(struct f2fs_sb_info *sbi)
 | 
				
			||||||
	if (sit_valid_blocks[NODE] != valid_node_count(sbi)) {
 | 
						if (sit_valid_blocks[NODE] != valid_node_count(sbi)) {
 | 
				
			||||||
		f2fs_err(sbi, "SIT is corrupted node# %u vs %u",
 | 
							f2fs_err(sbi, "SIT is corrupted node# %u vs %u",
 | 
				
			||||||
			 sit_valid_blocks[NODE], valid_node_count(sbi));
 | 
								 sit_valid_blocks[NODE], valid_node_count(sbi));
 | 
				
			||||||
 | 
							f2fs_handle_error(sbi, ERROR_INCONSISTENT_NODE_COUNT);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4475,6 +4483,7 @@ static int build_sit_entries(struct f2fs_sb_info *sbi)
 | 
				
			||||||
		f2fs_err(sbi, "SIT is corrupted data# %u %u vs %u",
 | 
							f2fs_err(sbi, "SIT is corrupted data# %u %u vs %u",
 | 
				
			||||||
			 sit_valid_blocks[DATA], sit_valid_blocks[NODE],
 | 
								 sit_valid_blocks[DATA], sit_valid_blocks[NODE],
 | 
				
			||||||
			 valid_user_blocks(sbi));
 | 
								 valid_user_blocks(sbi));
 | 
				
			||||||
 | 
							f2fs_handle_error(sbi, ERROR_INCONSISTENT_BLOCK_COUNT);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4625,6 +4634,7 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
 | 
				
			||||||
			f2fs_err(sbi,
 | 
								f2fs_err(sbi,
 | 
				
			||||||
				 "Current segment has invalid alloc_type:%d",
 | 
									 "Current segment has invalid alloc_type:%d",
 | 
				
			||||||
				 curseg->alloc_type);
 | 
									 curseg->alloc_type);
 | 
				
			||||||
 | 
								f2fs_handle_error(sbi, ERROR_INVALID_CURSEG);
 | 
				
			||||||
			return -EFSCORRUPTED;
 | 
								return -EFSCORRUPTED;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4642,6 +4652,7 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
 | 
				
			||||||
				 "Current segment's next free block offset is inconsistent with bitmap, logtype:%u, segno:%u, type:%u, next_blkoff:%u, blkofs:%u",
 | 
									 "Current segment's next free block offset is inconsistent with bitmap, logtype:%u, segno:%u, type:%u, next_blkoff:%u, blkofs:%u",
 | 
				
			||||||
				 i, curseg->segno, curseg->alloc_type,
 | 
									 i, curseg->segno, curseg->alloc_type,
 | 
				
			||||||
				 curseg->next_blkoff, blkofs);
 | 
									 curseg->next_blkoff, blkofs);
 | 
				
			||||||
 | 
								f2fs_handle_error(sbi, ERROR_INVALID_CURSEG);
 | 
				
			||||||
			return -EFSCORRUPTED;
 | 
								return -EFSCORRUPTED;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -753,6 +753,7 @@ static inline int check_block_count(struct f2fs_sb_info *sbi,
 | 
				
			||||||
		f2fs_err(sbi, "Mismatch valid blocks %d vs. %d",
 | 
							f2fs_err(sbi, "Mismatch valid blocks %d vs. %d",
 | 
				
			||||||
			 GET_SIT_VBLOCKS(raw_sit), valid_blocks);
 | 
								 GET_SIT_VBLOCKS(raw_sit), valid_blocks);
 | 
				
			||||||
		set_sbi_flag(sbi, SBI_NEED_FSCK);
 | 
							set_sbi_flag(sbi, SBI_NEED_FSCK);
 | 
				
			||||||
 | 
							f2fs_handle_error(sbi, ERROR_INCONSISTENT_SIT);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -767,6 +768,7 @@ static inline int check_block_count(struct f2fs_sb_info *sbi,
 | 
				
			||||||
		f2fs_err(sbi, "Wrong valid blocks %d or segno %u",
 | 
							f2fs_err(sbi, "Wrong valid blocks %d or segno %u",
 | 
				
			||||||
			 GET_SIT_VBLOCKS(raw_sit), segno);
 | 
								 GET_SIT_VBLOCKS(raw_sit), segno);
 | 
				
			||||||
		set_sbi_flag(sbi, SBI_NEED_FSCK);
 | 
							set_sbi_flag(sbi, SBI_NEED_FSCK);
 | 
				
			||||||
 | 
							f2fs_handle_error(sbi, ERROR_INCONSISTENT_SIT);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3851,8 +3851,6 @@ void f2fs_handle_stop(struct f2fs_sb_info *sbi, unsigned char reason)
 | 
				
			||||||
	struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
 | 
						struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	f2fs_bug_on(sbi, reason >= MAX_STOP_REASON);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	f2fs_down_write(&sbi->sb_lock);
 | 
						f2fs_down_write(&sbi->sb_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (raw_super->s_stop_reason[reason] < ((1 << BITS_PER_BYTE) - 1))
 | 
						if (raw_super->s_stop_reason[reason] < ((1 << BITS_PER_BYTE) - 1))
 | 
				
			||||||
| 
						 | 
					@ -3862,7 +3860,51 @@ void f2fs_handle_stop(struct f2fs_sb_info *sbi, unsigned char reason)
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		f2fs_err(sbi, "f2fs_commit_super fails to record reason:%u err:%d",
 | 
							f2fs_err(sbi, "f2fs_commit_super fails to record reason:%u err:%d",
 | 
				
			||||||
								reason, err);
 | 
													reason, err);
 | 
				
			||||||
 | 
						f2fs_up_write(&sbi->sb_lock);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void f2fs_save_errors(struct f2fs_sb_info *sbi, unsigned char flag)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						spin_lock(&sbi->error_lock);
 | 
				
			||||||
 | 
						if (!test_bit(flag, (unsigned long *)sbi->errors)) {
 | 
				
			||||||
 | 
							set_bit(flag, (unsigned long *)sbi->errors);
 | 
				
			||||||
 | 
							sbi->error_dirty = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						spin_unlock(&sbi->error_lock);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool f2fs_update_errors(struct f2fs_sb_info *sbi)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						bool need_update = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock(&sbi->error_lock);
 | 
				
			||||||
 | 
						if (sbi->error_dirty) {
 | 
				
			||||||
 | 
							memcpy(F2FS_RAW_SUPER(sbi)->s_errors, sbi->errors,
 | 
				
			||||||
 | 
												MAX_F2FS_ERRORS);
 | 
				
			||||||
 | 
							sbi->error_dirty = false;
 | 
				
			||||||
 | 
							need_update = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						spin_unlock(&sbi->error_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return need_update;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						f2fs_save_errors(sbi, error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						f2fs_down_write(&sbi->sb_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!f2fs_update_errors(sbi))
 | 
				
			||||||
 | 
							goto out_unlock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = f2fs_commit_super(sbi, false);
 | 
				
			||||||
 | 
						if (err)
 | 
				
			||||||
 | 
							f2fs_err(sbi, "f2fs_commit_super fails to record errors:%u, err:%d",
 | 
				
			||||||
 | 
													error, err);
 | 
				
			||||||
 | 
					out_unlock:
 | 
				
			||||||
	f2fs_up_write(&sbi->sb_lock);
 | 
						f2fs_up_write(&sbi->sb_lock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4213,6 +4255,9 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
 | 
				
			||||||
		goto free_devices;
 | 
							goto free_devices;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_init(&sbi->error_lock);
 | 
				
			||||||
 | 
						memcpy(sbi->errors, raw_super->s_errors, MAX_F2FS_ERRORS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sbi->total_valid_node_count =
 | 
						sbi->total_valid_node_count =
 | 
				
			||||||
				le32_to_cpu(sbi->ckpt->valid_node_count);
 | 
									le32_to_cpu(sbi->ckpt->valid_node_count);
 | 
				
			||||||
	percpu_counter_set(&sbi->total_valid_inode_count,
 | 
						percpu_counter_set(&sbi->total_valid_inode_count,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -240,6 +240,8 @@ static int f2fs_get_verity_descriptor(struct inode *inode, void *buf,
 | 
				
			||||||
	if (pos + size < pos || pos + size > inode->i_sb->s_maxbytes ||
 | 
						if (pos + size < pos || pos + size > inode->i_sb->s_maxbytes ||
 | 
				
			||||||
	    pos < f2fs_verity_metadata_pos(inode) || size > INT_MAX) {
 | 
						    pos < f2fs_verity_metadata_pos(inode) || size > INT_MAX) {
 | 
				
			||||||
		f2fs_warn(F2FS_I_SB(inode), "invalid verity xattr");
 | 
							f2fs_warn(F2FS_I_SB(inode), "invalid verity xattr");
 | 
				
			||||||
 | 
							f2fs_handle_error(F2FS_I_SB(inode),
 | 
				
			||||||
 | 
									ERROR_CORRUPTED_VERITY_XATTR);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (buf_size) {
 | 
						if (buf_size) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -367,6 +367,8 @@ static int lookup_all_xattrs(struct inode *inode, struct page *ipage,
 | 
				
			||||||
								inode->i_ino);
 | 
													inode->i_ino);
 | 
				
			||||||
		set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK);
 | 
							set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK);
 | 
				
			||||||
		err = -EFSCORRUPTED;
 | 
							err = -EFSCORRUPTED;
 | 
				
			||||||
 | 
							f2fs_handle_error(F2FS_I_SB(inode),
 | 
				
			||||||
 | 
										ERROR_CORRUPTED_XATTR);
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
check:
 | 
					check:
 | 
				
			||||||
| 
						 | 
					@ -583,6 +585,8 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 | 
				
			||||||
						inode->i_ino);
 | 
											inode->i_ino);
 | 
				
			||||||
			set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK);
 | 
								set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK);
 | 
				
			||||||
			error = -EFSCORRUPTED;
 | 
								error = -EFSCORRUPTED;
 | 
				
			||||||
 | 
								f2fs_handle_error(F2FS_I_SB(inode),
 | 
				
			||||||
 | 
											ERROR_CORRUPTED_XATTR);
 | 
				
			||||||
			goto cleanup;
 | 
								goto cleanup;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -658,6 +662,8 @@ static int __f2fs_setxattr(struct inode *inode, int index,
 | 
				
			||||||
								inode->i_ino);
 | 
													inode->i_ino);
 | 
				
			||||||
		set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK);
 | 
							set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK);
 | 
				
			||||||
		error = -EFSCORRUPTED;
 | 
							error = -EFSCORRUPTED;
 | 
				
			||||||
 | 
							f2fs_handle_error(F2FS_I_SB(inode),
 | 
				
			||||||
 | 
										ERROR_CORRUPTED_XATTR);
 | 
				
			||||||
		goto exit;
 | 
							goto exit;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -684,6 +690,8 @@ static int __f2fs_setxattr(struct inode *inode, int index,
 | 
				
			||||||
					inode->i_ino, ENTRY_SIZE(last));
 | 
										inode->i_ino, ENTRY_SIZE(last));
 | 
				
			||||||
			set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK);
 | 
								set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK);
 | 
				
			||||||
			error = -EFSCORRUPTED;
 | 
								error = -EFSCORRUPTED;
 | 
				
			||||||
 | 
								f2fs_handle_error(F2FS_I_SB(inode),
 | 
				
			||||||
 | 
											ERROR_CORRUPTED_XATTR);
 | 
				
			||||||
			goto exit;
 | 
								goto exit;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		last = XATTR_NEXT_ENTRY(last);
 | 
							last = XATTR_NEXT_ENTRY(last);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -87,6 +87,28 @@ enum stop_cp_reason {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define	MAX_STOP_REASON			32
 | 
					#define	MAX_STOP_REASON			32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* detail reason for EFSCORRUPTED */
 | 
				
			||||||
 | 
					enum f2fs_error {
 | 
				
			||||||
 | 
						ERROR_CORRUPTED_CLUSTER,
 | 
				
			||||||
 | 
						ERROR_FAIL_DECOMPRESSION,
 | 
				
			||||||
 | 
						ERROR_INVALID_BLKADDR,
 | 
				
			||||||
 | 
						ERROR_CORRUPTED_DIRENT,
 | 
				
			||||||
 | 
						ERROR_CORRUPTED_INODE,
 | 
				
			||||||
 | 
						ERROR_INCONSISTENT_SUMMARY,
 | 
				
			||||||
 | 
						ERROR_INCONSISTENT_FOOTER,
 | 
				
			||||||
 | 
						ERROR_INCONSISTENT_SUM_TYPE,
 | 
				
			||||||
 | 
						ERROR_CORRUPTED_JOURNAL,
 | 
				
			||||||
 | 
						ERROR_INCONSISTENT_NODE_COUNT,
 | 
				
			||||||
 | 
						ERROR_INCONSISTENT_BLOCK_COUNT,
 | 
				
			||||||
 | 
						ERROR_INVALID_CURSEG,
 | 
				
			||||||
 | 
						ERROR_INCONSISTENT_SIT,
 | 
				
			||||||
 | 
						ERROR_CORRUPTED_VERITY_XATTR,
 | 
				
			||||||
 | 
						ERROR_CORRUPTED_XATTR,
 | 
				
			||||||
 | 
						ERROR_MAX,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MAX_F2FS_ERRORS			16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct f2fs_super_block {
 | 
					struct f2fs_super_block {
 | 
				
			||||||
	__le32 magic;			/* Magic Number */
 | 
						__le32 magic;			/* Magic Number */
 | 
				
			||||||
	__le16 major_ver;		/* Major Version */
 | 
						__le16 major_ver;		/* Major Version */
 | 
				
			||||||
| 
						 | 
					@ -131,7 +153,8 @@ struct f2fs_super_block {
 | 
				
			||||||
	__le16  s_encoding;		/* Filename charset encoding */
 | 
						__le16  s_encoding;		/* Filename charset encoding */
 | 
				
			||||||
	__le16  s_encoding_flags;	/* Filename charset encoding flags */
 | 
						__le16  s_encoding_flags;	/* Filename charset encoding flags */
 | 
				
			||||||
	__u8 s_stop_reason[MAX_STOP_REASON];	/* stop checkpoint reason */
 | 
						__u8 s_stop_reason[MAX_STOP_REASON];	/* stop checkpoint reason */
 | 
				
			||||||
	__u8 reserved[274];		/* valid reserved region */
 | 
						__u8 s_errors[MAX_F2FS_ERRORS];		/* reason of image corrupts */
 | 
				
			||||||
 | 
						__u8 reserved[258];		/* valid reserved region */
 | 
				
			||||||
	__le32 crc;			/* checksum of superblock */
 | 
						__le32 crc;			/* checksum of superblock */
 | 
				
			||||||
} __packed;
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue