Commit 6d61a53d authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull f2fs updates from Jaegeuk Kim:
 "In this series, there are several major improvements such as folio
  conversion by Matthew, speed-up of block truncation, and caching more
  dentry pages.

  In addition, we implemented a linear dentry search to address recent
  unicode regression, and figured out some false alarms that we could
  get rid of.

  Enhancements:
   - foilio conversion in various IO paths
   - optimize f2fs_truncate_data_blocks_range()
   - cache more dentry pages
   - remove unnecessary blk_finish_plug
   - procfs: show mtime in segment_bits

  Bug fixes:
   - introduce linear search for dentries
   - don't call block truncation for aliased file
   - fix using wrong 'submitted' value in f2fs_write_cache_pages
   - fix to do sanity check correctly on i_inline_xattr_size
   - avoid trying to get invalid block address
   - fix inconsistent dirty state of atomic file"

* tag 'f2fs-for-6.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (32 commits)
  f2fs: fix inconsistent dirty state of atomic file
  f2fs: fix to avoid changing 'check only' behaior of recovery
  f2fs: Clean up the loop outside of f2fs_invalidate_blocks()
  f2fs: procfs: show mtime in segment_bits
  f2fs: fix to avoid return invalid mtime from f2fs_get_section_mtime()
  f2fs: Fix format specifier in sanity_check_inode()
  f2fs: avoid trying to get invalid block address
  f2fs: fix to do sanity check correctly on i_inline_xattr_size
  f2fs: remove blk_finish_plug
  f2fs: Optimize f2fs_truncate_data_blocks_range()
  f2fs: fix using wrong 'submitted' value in f2fs_write_cache_pages
  f2fs: add parameter @len to f2fs_invalidate_blocks()
  f2fs: update_sit_entry_for_release() supports consecutive blocks.
  f2fs: introduce update_sit_entry_for_release/alloc()
  f2fs: don't call block truncation for aliased file
  f2fs: Introduce linear search for dentries
  f2fs: add parameter @len to f2fs_invalidate_internal_cache()
  f2fs: expand f2fs_invalidate_compress_page() to f2fs_invalidate_compress_pages_range()
  f2fs: ensure that node info flags are always initialized
  f2fs: The GC triggered by ioctl also needs to mark the segno as victim
  ...
parents f34b5805 03511e93
Loading
Loading
Loading
Loading
+23 −15
Original line number Diff line number Diff line
@@ -846,7 +846,7 @@ bool f2fs_cluster_can_merge_page(struct compress_ctx *cc, pgoff_t index)
bool f2fs_all_cluster_page_ready(struct compress_ctx *cc, struct page **pages,
				int index, int nr_pages, bool uptodate)
{
	unsigned long pgidx = pages[index]->index;
	unsigned long pgidx = page_folio(pages[index])->index;
	int i = uptodate ? 0 : 1;

	/*
@@ -860,9 +860,11 @@ bool f2fs_all_cluster_page_ready(struct compress_ctx *cc, struct page **pages,
		return false;

	for (; i < cc->cluster_size; i++) {
		if (pages[index + i]->index != pgidx + i)
		struct folio *folio = page_folio(pages[index + i]);

		if (folio->index != pgidx + i)
			return false;
		if (uptodate && !PageUptodate(pages[index + i]))
		if (uptodate && !folio_test_uptodate(folio))
			return false;
	}

@@ -1195,7 +1197,8 @@ bool f2fs_compress_write_end(struct inode *inode, void *fsdata,
		.cluster_size = F2FS_I(inode)->i_cluster_size,
		.rpages = fsdata,
	};
	bool first_index = (index == cc.rpages[0]->index);
	struct folio *folio = page_folio(cc.rpages[0]);
	bool first_index = (index == folio->index);

	if (copied)
		set_cluster_dirty(&cc);
@@ -1239,13 +1242,14 @@ int f2fs_truncate_partial_cluster(struct inode *inode, u64 from, bool lock)
		int i;

		for (i = cluster_size - 1; i >= 0; i--) {
			loff_t start = rpages[i]->index << PAGE_SHIFT;
			struct folio *folio = page_folio(rpages[i]);
			loff_t start = folio->index << PAGE_SHIFT;

			if (from <= start) {
				zero_user_segment(rpages[i], 0, PAGE_SIZE);
				folio_zero_segment(folio, 0, folio_size(folio));
			} else {
				zero_user_segment(rpages[i], from - start,
								PAGE_SIZE);
				folio_zero_segment(folio, from - start,
						folio_size(folio));
				break;
			}
		}
@@ -1278,6 +1282,7 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc,
		.encrypted = fscrypt_inode_uses_fs_layer_crypto(cc->inode) ?
									1 : 0,
	};
	struct folio *folio;
	struct dnode_of_data dn;
	struct node_info ni;
	struct compress_io_ctx *cic;
@@ -1289,7 +1294,7 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc,

	/* we should bypass data pages to proceed the kworker jobs */
	if (unlikely(f2fs_cp_error(sbi))) {
		mapping_set_error(cc->rpages[0]->mapping, -EIO);
		mapping_set_error(inode->i_mapping, -EIO);
		goto out_free;
	}

@@ -1316,7 +1321,8 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc,
			goto out_put_dnode;
	}

	psize = (loff_t)(cc->rpages[last_index]->index + 1) << PAGE_SHIFT;
	folio = page_folio(cc->rpages[last_index]);
	psize = folio_pos(folio) + folio_size(folio);

	err = f2fs_get_node_info(fio.sbi, dn.nid, &ni, false);
	if (err)
@@ -1339,7 +1345,7 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc,

	for (i = 0; i < cc->valid_nr_cpages; i++) {
		f2fs_set_compressed_page(cc->cpages[i], inode,
					cc->rpages[i + 1]->index, cic);
				page_folio(cc->rpages[i + 1])->index, cic);
		fio.compressed_page = cc->cpages[i];

		fio.old_blkaddr = data_blkaddr(dn.inode, dn.node_page,
@@ -1374,7 +1380,7 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc,
			if (blkaddr == COMPRESS_ADDR)
				fio.compr_blocks++;
			if (__is_valid_data_blkaddr(blkaddr))
				f2fs_invalidate_blocks(sbi, blkaddr);
				f2fs_invalidate_blocks(sbi, blkaddr, 1);
			f2fs_update_data_blkaddr(&dn, COMPRESS_ADDR);
			goto unlock_continue;
		}
@@ -1384,7 +1390,7 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc,

		if (i > cc->valid_nr_cpages) {
			if (__is_valid_data_blkaddr(blkaddr)) {
				f2fs_invalidate_blocks(sbi, blkaddr);
				f2fs_invalidate_blocks(sbi, blkaddr, 1);
				f2fs_update_data_blkaddr(&dn, NEW_ADDR);
			}
			goto unlock_continue;
@@ -1545,6 +1551,7 @@ static int f2fs_write_raw_pages(struct compress_ctx *cc,
		if (!clear_page_dirty_for_io(cc->rpages[i]))
			goto continue_unlock;

		submitted = 0;
		ret = f2fs_write_single_data_page(page_folio(cc->rpages[i]),
						&submitted,
						NULL, NULL, wbc, io_type,
@@ -1903,11 +1910,12 @@ struct address_space *COMPRESS_MAPPING(struct f2fs_sb_info *sbi)
	return sbi->compress_inode->i_mapping;
}

void f2fs_invalidate_compress_page(struct f2fs_sb_info *sbi, block_t blkaddr)
void f2fs_invalidate_compress_pages_range(struct f2fs_sb_info *sbi,
				block_t blkaddr, unsigned int len)
{
	if (!sbi->compress_inode)
		return;
	invalidate_mapping_pages(COMPRESS_MAPPING(sbi), blkaddr, blkaddr);
	invalidate_mapping_pages(COMPRESS_MAPPING(sbi), blkaddr, blkaddr + len - 1);
}

void f2fs_cache_compressed_page(struct f2fs_sb_info *sbi, struct page *page,
+25 −37
Original line number Diff line number Diff line
@@ -70,9 +70,9 @@ bool f2fs_is_cp_guaranteed(struct page *page)
	return false;
}

static enum count_type __read_io_type(struct page *page)
static enum count_type __read_io_type(struct folio *folio)
{
	struct address_space *mapping = page_file_mapping(page);
	struct address_space *mapping = folio->mapping;

	if (mapping) {
		struct inode *inode = mapping->host;
@@ -136,27 +136,22 @@ struct bio_post_read_ctx {
 */
static void f2fs_finish_read_bio(struct bio *bio, bool in_task)
{
	struct bio_vec *bv;
	struct bvec_iter_all iter_all;
	struct folio_iter fi;
	struct bio_post_read_ctx *ctx = bio->bi_private;

	bio_for_each_segment_all(bv, bio, iter_all) {
		struct page *page = bv->bv_page;
	bio_for_each_folio_all(fi, bio) {
		struct folio *folio = fi.folio;

		if (f2fs_is_compressed_page(page)) {
		if (f2fs_is_compressed_page(&folio->page)) {
			if (ctx && !ctx->decompression_attempted)
				f2fs_end_read_compressed_page(page, true, 0,
				f2fs_end_read_compressed_page(&folio->page, true, 0,
							in_task);
			f2fs_put_page_dic(page, in_task);
			f2fs_put_page_dic(&folio->page, in_task);
			continue;
		}

		if (bio->bi_status)
			ClearPageUptodate(page);
		else
			SetPageUptodate(page);
		dec_page_count(F2FS_P_SB(page), __read_io_type(page));
		unlock_page(page);
		dec_page_count(F2FS_F_SB(folio), __read_io_type(folio));
		folio_end_read(folio, bio->bi_status == 0);
	}

	if (ctx)
@@ -516,10 +511,6 @@ static void f2fs_submit_write_bio(struct f2fs_sb_info *sbi, struct bio *bio,
				  enum page_type type)
{
	WARN_ON_ONCE(is_read_io(bio_op(bio)));

	if (f2fs_lfs_mode(sbi) && current->plug && PAGE_TYPE_ON_MAIN(type))
		blk_finish_plug(current->plug);

	trace_f2fs_submit_write_bio(sbi->sb, type, bio);
	iostat_update_submit_ctx(bio, type);
	submit_bio(bio);
@@ -689,33 +680,29 @@ void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi)
int f2fs_submit_page_bio(struct f2fs_io_info *fio)
{
	struct bio *bio;
	struct page *page = fio->encrypted_page ?
			fio->encrypted_page : fio->page;
	struct folio *fio_folio = page_folio(fio->page);
	struct folio *data_folio = fio->encrypted_page ?
			page_folio(fio->encrypted_page) : fio_folio;

	if (!f2fs_is_valid_blkaddr(fio->sbi, fio->new_blkaddr,
			fio->is_por ? META_POR : (__is_meta_io(fio) ?
			META_GENERIC : DATA_GENERIC_ENHANCE)))
		return -EFSCORRUPTED;

	trace_f2fs_submit_page_bio(page, fio);
	trace_f2fs_submit_folio_bio(data_folio, fio);

	/* Allocate a new bio */
	bio = __bio_alloc(fio, 1);

	f2fs_set_bio_crypt_ctx(bio, fio->page->mapping->host,
			page_folio(fio->page)->index, fio, GFP_NOIO);

	if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
		bio_put(bio);
		return -EFAULT;
	}
	f2fs_set_bio_crypt_ctx(bio, fio_folio->mapping->host,
			fio_folio->index, fio, GFP_NOIO);
	bio_add_folio_nofail(bio, data_folio, folio_size(data_folio), 0);

	if (fio->io_wbc && !is_read_io(fio->op))
		wbc_account_cgroup_owner(fio->io_wbc, page_folio(fio->page),
					 PAGE_SIZE);
		wbc_account_cgroup_owner(fio->io_wbc, fio_folio, PAGE_SIZE);

	inc_page_count(fio->sbi, is_read_io(fio->op) ?
			__read_io_type(page) : WB_DATA_TYPE(fio->page, false));
			__read_io_type(data_folio) : WB_DATA_TYPE(fio->page, false));

	if (is_read_io(bio_op(bio)))
		f2fs_submit_read_bio(fio->sbi, bio, fio->type);
@@ -894,7 +881,7 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio)
			__is_meta_io(fio) ? META_GENERIC : DATA_GENERIC))
		return -EFSCORRUPTED;

	trace_f2fs_submit_page_bio(page, fio);
	trace_f2fs_submit_folio_bio(page_folio(page), fio);

	if (bio && !page_is_mergeable(fio->sbi, bio, *fio->last_block,
						fio->new_blkaddr))
@@ -1018,7 +1005,7 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)

	io->last_block_in_bio = fio->new_blkaddr;

	trace_f2fs_submit_page_write(fio->page, fio);
	trace_f2fs_submit_folio_write(page_folio(fio->page), fio);
#ifdef CONFIG_BLK_DEV_ZONED
	if (f2fs_sb_has_blkzoned(sbi) && btype < META &&
			is_end_zone_blkaddr(sbi, fio->new_blkaddr)) {
@@ -1289,7 +1276,7 @@ struct page *f2fs_find_data_page(struct inode *inode, pgoff_t index,
	struct address_space *mapping = inode->i_mapping;
	struct page *page;

	page = find_get_page(mapping, index);
	page = find_get_page_flags(mapping, index, FGP_ACCESSED);
	if (page && PageUptodate(page))
		return page;
	f2fs_put_page(page, 0);
@@ -1423,7 +1410,7 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
		return err;

	if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO)
		f2fs_invalidate_internal_cache(sbi, old_blkaddr);
		f2fs_invalidate_internal_cache(sbi, old_blkaddr, 1);

	f2fs_update_data_blkaddr(dn, dn->data_blkaddr);
	return 0;
@@ -2464,7 +2451,7 @@ static int f2fs_mpage_readpages(struct inode *inode,

static int f2fs_read_data_folio(struct file *file, struct folio *folio)
{
	struct inode *inode = folio_file_mapping(folio)->host;
	struct inode *inode = folio->mapping->host;
	int ret = -EAGAIN;

	trace_f2fs_readpage(folio, DATA);
@@ -3163,6 +3150,7 @@ static int f2fs_write_cache_pages(struct address_space *mapping,
				continue;
			}
#endif
			submitted = 0;
			ret = f2fs_write_single_data_page(folio,
					&submitted, &bio, &last_block,
					wbc, io_type, 0, true);
+38 −15
Original line number Diff line number Diff line
@@ -175,7 +175,8 @@ static unsigned long dir_block_index(unsigned int level,
static struct f2fs_dir_entry *find_in_block(struct inode *dir,
				struct page *dentry_page,
				const struct f2fs_filename *fname,
				int *max_slots)
				int *max_slots,
				bool use_hash)
{
	struct f2fs_dentry_block *dentry_blk;
	struct f2fs_dentry_ptr d;
@@ -183,7 +184,7 @@ static struct f2fs_dir_entry *find_in_block(struct inode *dir,
	dentry_blk = (struct f2fs_dentry_block *)page_address(dentry_page);

	make_dentry_ptr_block(dir, &d, dentry_blk);
	return f2fs_find_target_dentry(&d, fname, max_slots);
	return f2fs_find_target_dentry(&d, fname, max_slots, use_hash);
}

static inline int f2fs_match_name(const struct inode *dir,
@@ -208,7 +209,8 @@ static inline int f2fs_match_name(const struct inode *dir,
}

struct f2fs_dir_entry *f2fs_find_target_dentry(const struct f2fs_dentry_ptr *d,
			const struct f2fs_filename *fname, int *max_slots)
			const struct f2fs_filename *fname, int *max_slots,
			bool use_hash)
{
	struct f2fs_dir_entry *de;
	unsigned long bit_pos = 0;
@@ -231,7 +233,7 @@ struct f2fs_dir_entry *f2fs_find_target_dentry(const struct f2fs_dentry_ptr *d,
			continue;
		}

		if (de->hash_code == fname->hash) {
		if (!use_hash || de->hash_code == fname->hash) {
			res = f2fs_match_name(d->inode, fname,
					      d->filename[bit_pos],
					      le16_to_cpu(de->name_len));
@@ -258,11 +260,12 @@ struct f2fs_dir_entry *f2fs_find_target_dentry(const struct f2fs_dentry_ptr *d,
static struct f2fs_dir_entry *find_in_level(struct inode *dir,
					unsigned int level,
					const struct f2fs_filename *fname,
					struct page **res_page)
					struct page **res_page,
					bool use_hash)
{
	int s = GET_DENTRY_SLOTS(fname->disk_name.len);
	unsigned int nbucket, nblock;
	unsigned int bidx, end_block;
	unsigned int bidx, end_block, bucket_no;
	struct page *dentry_page;
	struct f2fs_dir_entry *de = NULL;
	pgoff_t next_pgofs;
@@ -272,8 +275,11 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,
	nbucket = dir_buckets(level, F2FS_I(dir)->i_dir_level);
	nblock = bucket_blocks(level);

	bucket_no = use_hash ? le32_to_cpu(fname->hash) % nbucket : 0;

start_find_bucket:
	bidx = dir_block_index(level, F2FS_I(dir)->i_dir_level,
			       le32_to_cpu(fname->hash) % nbucket);
			       bucket_no);
	end_block = bidx + nblock;

	while (bidx < end_block) {
@@ -290,7 +296,7 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,
			}
		}

		de = find_in_block(dir, dentry_page, fname, &max_slots);
		de = find_in_block(dir, dentry_page, fname, &max_slots, use_hash);
		if (IS_ERR(de)) {
			*res_page = ERR_CAST(de);
			de = NULL;
@@ -307,12 +313,18 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,
		bidx++;
	}

	if (!de && room && F2FS_I(dir)->chash != fname->hash) {
	if (de)
		return de;

	if (likely(use_hash)) {
		if (room && F2FS_I(dir)->chash != fname->hash) {
			F2FS_I(dir)->chash = fname->hash;
			F2FS_I(dir)->clevel = level;
		}

	return de;
	} else if (++bucket_no < nbucket) {
		goto start_find_bucket;
	}
	return NULL;
}

struct f2fs_dir_entry *__f2fs_find_entry(struct inode *dir,
@@ -323,11 +335,15 @@ struct f2fs_dir_entry *__f2fs_find_entry(struct inode *dir,
	struct f2fs_dir_entry *de = NULL;
	unsigned int max_depth;
	unsigned int level;
	bool use_hash = true;

	*res_page = NULL;

#if IS_ENABLED(CONFIG_UNICODE)
start_find_entry:
#endif
	if (f2fs_has_inline_dentry(dir)) {
		de = f2fs_find_in_inline_dir(dir, fname, res_page);
		de = f2fs_find_in_inline_dir(dir, fname, res_page, use_hash);
		goto out;
	}

@@ -343,11 +359,18 @@ struct f2fs_dir_entry *__f2fs_find_entry(struct inode *dir,
	}

	for (level = 0; level < max_depth; level++) {
		de = find_in_level(dir, level, fname, res_page);
		de = find_in_level(dir, level, fname, res_page, use_hash);
		if (de || IS_ERR(*res_page))
			break;
	}

out:
#if IS_ENABLED(CONFIG_UNICODE)
	if (IS_CASEFOLDED(dir) && !de && use_hash) {
		use_hash = false;
		goto start_find_entry;
	}
#endif
	/* This is to increase the speed of f2fs_create */
	if (!de)
		F2FS_I(dir)->task = current;
+19 −10
Original line number Diff line number Diff line
@@ -1985,9 +1985,14 @@ static inline struct f2fs_sb_info *F2FS_M_SB(struct address_space *mapping)
	return F2FS_I_SB(mapping->host);
}

static inline struct f2fs_sb_info *F2FS_F_SB(struct folio *folio)
{
	return F2FS_M_SB(folio->mapping);
}

static inline struct f2fs_sb_info *F2FS_P_SB(struct page *page)
{
	return F2FS_M_SB(page_file_mapping(page));
	return F2FS_F_SB(page_folio(page));
}

static inline struct f2fs_super_block *F2FS_RAW_SUPER(struct f2fs_sb_info *sbi)
@@ -3565,7 +3570,8 @@ int f2fs_prepare_lookup(struct inode *dir, struct dentry *dentry,
			struct f2fs_filename *fname);
void f2fs_free_filename(struct f2fs_filename *fname);
struct f2fs_dir_entry *f2fs_find_target_dentry(const struct f2fs_dentry_ptr *d,
			const struct f2fs_filename *fname, int *max_slots);
			const struct f2fs_filename *fname, int *max_slots,
			bool use_hash);
int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
			unsigned int start_pos, struct fscrypt_str *fstr);
void f2fs_do_make_empty_dir(struct inode *inode, struct inode *parent,
@@ -3700,7 +3706,8 @@ int f2fs_issue_flush(struct f2fs_sb_info *sbi, nid_t ino);
int f2fs_create_flush_cmd_control(struct f2fs_sb_info *sbi);
int f2fs_flush_device_cache(struct f2fs_sb_info *sbi);
void f2fs_destroy_flush_cmd_control(struct f2fs_sb_info *sbi, bool free);
void f2fs_invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr);
void f2fs_invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr,
						unsigned int len);
bool f2fs_is_checkpointed_data(struct f2fs_sb_info *sbi, block_t blkaddr);
int f2fs_start_discard_thread(struct f2fs_sb_info *sbi);
void f2fs_drop_discard_cmd(struct f2fs_sb_info *sbi);
@@ -4201,7 +4208,8 @@ int f2fs_write_inline_data(struct inode *inode, struct folio *folio);
int f2fs_recover_inline_data(struct inode *inode, struct page *npage);
struct f2fs_dir_entry *f2fs_find_in_inline_dir(struct inode *dir,
					const struct f2fs_filename *fname,
					struct page **res_page);
					struct page **res_page,
					bool use_hash);
int f2fs_make_empty_inline_dir(struct inode *inode, struct inode *parent,
			struct page *ipage);
int f2fs_add_inline_entry(struct inode *dir, const struct f2fs_filename *fname,
@@ -4368,7 +4376,8 @@ void f2fs_destroy_page_array_cache(struct f2fs_sb_info *sbi);
int __init f2fs_init_compress_cache(void);
void f2fs_destroy_compress_cache(void);
struct address_space *COMPRESS_MAPPING(struct f2fs_sb_info *sbi);
void f2fs_invalidate_compress_page(struct f2fs_sb_info *sbi, block_t blkaddr);
void f2fs_invalidate_compress_pages_range(struct f2fs_sb_info *sbi,
					block_t blkaddr, unsigned int len);
void f2fs_cache_compressed_page(struct f2fs_sb_info *sbi, struct page *page,
						nid_t ino, block_t blkaddr);
bool f2fs_load_compressed_page(struct f2fs_sb_info *sbi, struct page *page,
@@ -4423,8 +4432,8 @@ static inline int f2fs_init_page_array_cache(struct f2fs_sb_info *sbi) { return
static inline void f2fs_destroy_page_array_cache(struct f2fs_sb_info *sbi) { }
static inline int __init f2fs_init_compress_cache(void) { return 0; }
static inline void f2fs_destroy_compress_cache(void) { }
static inline void f2fs_invalidate_compress_page(struct f2fs_sb_info *sbi,
				block_t blkaddr) { }
static inline void f2fs_invalidate_compress_pages_range(struct f2fs_sb_info *sbi,
				block_t blkaddr, unsigned int len) { }
static inline void f2fs_cache_compressed_page(struct f2fs_sb_info *sbi,
				struct page *page, nid_t ino, block_t blkaddr) { }
static inline bool f2fs_load_compressed_page(struct f2fs_sb_info *sbi,
@@ -4740,10 +4749,10 @@ static inline void f2fs_truncate_meta_inode_pages(struct f2fs_sb_info *sbi,
}

static inline void f2fs_invalidate_internal_cache(struct f2fs_sb_info *sbi,
								block_t blkaddr)
						block_t blkaddr, unsigned int len)
{
	f2fs_truncate_meta_inode_pages(sbi, blkaddr, 1);
	f2fs_invalidate_compress_page(sbi, blkaddr);
	f2fs_truncate_meta_inode_pages(sbi, blkaddr, len);
	f2fs_invalidate_compress_pages_range(sbi, blkaddr, len);
}

#define EFSBADCRC	EBADMSG		/* Bad CRC detected */
+28 −9
Original line number Diff line number Diff line
@@ -621,8 +621,11 @@ void f2fs_truncate_data_blocks_range(struct dnode_of_data *dn, int count)
	int cluster_index = 0, valid_blocks = 0;
	int cluster_size = F2FS_I(dn->inode)->i_cluster_size;
	bool released = !atomic_read(&F2FS_I(dn->inode)->i_compr_blocks);
	block_t blkstart;
	int blklen = 0;

	addr = get_dnode_addr(dn->inode, dn->node_page) + ofs;
	blkstart = le32_to_cpu(*addr);

	/* Assumption: truncation starts with cluster */
	for (; count > 0; count--, addr++, dn->ofs_in_node++, cluster_index++) {
@@ -638,26 +641,44 @@ void f2fs_truncate_data_blocks_range(struct dnode_of_data *dn, int count)
		}

		if (blkaddr == NULL_ADDR)
			continue;
			goto next;

		f2fs_set_data_blkaddr(dn, NULL_ADDR);

		if (__is_valid_data_blkaddr(blkaddr)) {
			if (time_to_inject(sbi, FAULT_BLKADDR_CONSISTENCE))
				continue;
				goto next;
			if (!f2fs_is_valid_blkaddr_raw(sbi, blkaddr,
						DATA_GENERIC_ENHANCE))
				continue;
				goto next;
			if (compressed_cluster)
				valid_blocks++;
		}

		f2fs_invalidate_blocks(sbi, blkaddr);
		if (blkstart + blklen == blkaddr) {
			blklen++;
		} else {
			f2fs_invalidate_blocks(sbi, blkstart, blklen);
			blkstart = blkaddr;
			blklen = 1;
		}

		if (!released || blkaddr != COMPRESS_ADDR)
			nr_free++;

		continue;

next:
		if (blklen)
			f2fs_invalidate_blocks(sbi, blkstart, blklen);

		blkstart = le32_to_cpu(*(addr + 1));
		blklen = 0;
	}

	if (blklen)
		f2fs_invalidate_blocks(sbi, blkstart, blklen);

	if (compressed_cluster)
		f2fs_i_compr_blocks_update(dn->inode, valid_blocks, false);

@@ -747,10 +768,8 @@ int f2fs_do_truncate_blocks(struct inode *inode, u64 from, bool lock)
	if (IS_DEVICE_ALIASING(inode)) {
		struct extent_tree *et = F2FS_I(inode)->extent_tree[EX_READ];
		struct extent_info ei = et->largest;
		unsigned int i;

		for (i = 0; i < ei.len; i++)
			f2fs_invalidate_blocks(sbi, ei.blk + i);
		f2fs_invalidate_blocks(sbi, ei.blk, ei.len);

		dec_valid_block_count(sbi, inode, ei.len);
		f2fs_update_time(sbi, REQ_TIME);
@@ -1323,7 +1342,7 @@ static int __roll_back_blkaddrs(struct inode *inode, block_t *blkaddr,
		ret = f2fs_get_dnode_of_data(&dn, off + i, LOOKUP_NODE_RA);
		if (ret) {
			dec_valid_block_count(sbi, inode, 1);
			f2fs_invalidate_blocks(sbi, *blkaddr);
			f2fs_invalidate_blocks(sbi, *blkaddr, 1);
		} else {
			f2fs_update_data_blkaddr(&dn, *blkaddr);
		}
@@ -1575,7 +1594,7 @@ static int f2fs_do_zero_range(struct dnode_of_data *dn, pgoff_t start,
			break;
		}

		f2fs_invalidate_blocks(sbi, dn->data_blkaddr);
		f2fs_invalidate_blocks(sbi, dn->data_blkaddr, 1);
		f2fs_set_data_blkaddr(dn, NEW_ADDR);
	}

Loading