Commit 5ad7ff87 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull f2fs updates from Jaegeuk Kim:
 "A pretty small update including mostly minor bug fixes in zoned
  storage along with the large section support.

  Enhancements:
   - add support for FS_IOC_GETFSSYSFSPATH
   - enable atgc dynamically if conditions are met
   - use new ioprio Macro to get ckpt thread ioprio level
   - remove unreachable lazytime mount option parsing

  Bug fixes:
   - fix null reference error when checking end of zone
   - fix start segno of large section
   - fix to cover read extent cache access with lock
   - don't dirty inode for readonly filesystem
   - allocate a new section if curseg is not the first seg in its zone
   - only fragment segment in the same section
   - truncate preallocated blocks in f2fs_file_open()
   - fix to avoid use SSR allocate when do defragment
   - fix to force buffered IO on inline_data inode

  And some minor code clean-ups and sanity checks"

* tag 'f2fs-for-6.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (26 commits)
  f2fs: clean up addrs_per_{inode,block}()
  f2fs: clean up F2FS_I()
  f2fs: use meta inode for GC of COW file
  f2fs: use meta inode for GC of atomic file
  f2fs: only fragment segment in the same section
  f2fs: fix to update user block counts in block_operations()
  f2fs: remove unreachable lazytime mount option parsing
  f2fs: fix null reference error when checking end of zone
  f2fs: fix start segno of large section
  f2fs: remove redundant sanity check in sanity_check_inode()
  f2fs: assign CURSEG_ALL_DATA_ATGC if blkaddr is valid
  f2fs: fix to use mnt_{want,drop}_write_file replace file_{start,end}_wrtie
  f2fs: clean up set REQ_RAHEAD given rac
  f2fs: enable atgc dynamically if conditions are met
  f2fs: fix to truncate preallocated blocks in f2fs_file_open()
  f2fs: fix to cover read extent cache access with lock
  f2fs: fix return value of f2fs_convert_inline_inode()
  f2fs: use new ioprio Macro to get ckpt thread ioprio level
  f2fs: fix to don't dirty inode for readonly filesystem
  f2fs: fix to avoid use SSR allocate when do defragment
  ...
parents 371c1414 bed6b031
Loading
Loading
Loading
Loading
+6 −5
Original line number Diff line number Diff line
@@ -1186,6 +1186,11 @@ static void __prepare_cp_block(struct f2fs_sb_info *sbi)
	ckpt->valid_node_count = cpu_to_le32(valid_node_count(sbi));
	ckpt->valid_inode_count = cpu_to_le32(valid_inode_count(sbi));
	ckpt->next_free_nid = cpu_to_le32(last_nid);

	/* update user_block_counts */
	sbi->last_valid_block_count = sbi->total_valid_block_count;
	percpu_counter_set(&sbi->alloc_valid_block_count, 0);
	percpu_counter_set(&sbi->rf_node_block_count, 0);
}

static bool __need_flush_quota(struct f2fs_sb_info *sbi)
@@ -1575,11 +1580,6 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
		start_blk += NR_CURSEG_NODE_TYPE;
	}

	/* update user_block_counts */
	sbi->last_valid_block_count = sbi->total_valid_block_count;
	percpu_counter_set(&sbi->alloc_valid_block_count, 0);
	percpu_counter_set(&sbi->rf_node_block_count, 0);

	/* Here, we have one bio having CP pack except cp pack 2 page */
	f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_CP_META_IO);
	/* Wait for all dirty meta pages to be submitted for IO */
@@ -1718,6 +1718,7 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
	}

	f2fs_restore_inmem_curseg(sbi);
	f2fs_reinit_atgc_curseg(sbi);
	stat_inc_cp_count(sbi);
stop:
	unblock_operations(sbi);
+1 −1
Original line number Diff line number Diff line
@@ -1100,7 +1100,7 @@ static int prepare_compress_overwrite(struct compress_ctx *cc,
		struct bio *bio = NULL;

		ret = f2fs_read_multi_pages(cc, &bio, cc->cluster_size,
					&last_block_in_bio, false, true);
					&last_block_in_bio, NULL, true);
		f2fs_put_rpages(cc);
		f2fs_destroy_compress_ctx(cc, true);
		if (ret)
+17 −10
Original line number Diff line number Diff line
@@ -925,6 +925,7 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio)
#ifdef CONFIG_BLK_DEV_ZONED
static bool is_end_zone_blkaddr(struct f2fs_sb_info *sbi, block_t blkaddr)
{
	struct block_device *bdev = sbi->sb->s_bdev;
	int devi = 0;

	if (f2fs_is_multi_device(sbi)) {
@@ -935,8 +936,9 @@ static bool is_end_zone_blkaddr(struct f2fs_sb_info *sbi, block_t blkaddr)
			return false;
		}
		blkaddr -= FDEV(devi).start_blk;
		bdev = FDEV(devi).bdev;
	}
	return bdev_is_zoned(FDEV(devi).bdev) &&
	return bdev_is_zoned(bdev) &&
		f2fs_blkz_is_seq(sbi, devi, blkaddr) &&
		(blkaddr % sbi->blocks_per_blkz == sbi->blocks_per_blkz - 1);
}
@@ -2067,12 +2069,17 @@ static inline loff_t f2fs_readpage_limit(struct inode *inode)
	return i_size_read(inode);
}

static inline blk_opf_t f2fs_ra_op_flags(struct readahead_control *rac)
{
	return rac ? REQ_RAHEAD : 0;
}

static int f2fs_read_single_page(struct inode *inode, struct folio *folio,
					unsigned nr_pages,
					struct f2fs_map_blocks *map,
					struct bio **bio_ret,
					sector_t *last_block_in_bio,
					bool is_readahead)
					struct readahead_control *rac)
{
	struct bio *bio = *bio_ret;
	const unsigned blocksize = blks_to_bytes(inode, 1);
@@ -2148,7 +2155,7 @@ static int f2fs_read_single_page(struct inode *inode, struct folio *folio,
	}
	if (bio == NULL) {
		bio = f2fs_grab_read_bio(inode, block_nr, nr_pages,
				is_readahead ? REQ_RAHEAD : 0, index,
				f2fs_ra_op_flags(rac), index,
				false);
		if (IS_ERR(bio)) {
			ret = PTR_ERR(bio);
@@ -2178,7 +2185,7 @@ static int f2fs_read_single_page(struct inode *inode, struct folio *folio,
#ifdef CONFIG_F2FS_FS_COMPRESSION
int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
				unsigned nr_pages, sector_t *last_block_in_bio,
				bool is_readahead, bool for_write)
				struct readahead_control *rac, bool for_write)
{
	struct dnode_of_data dn;
	struct inode *inode = cc->inode;
@@ -2301,7 +2308,7 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,

		if (!bio) {
			bio = f2fs_grab_read_bio(inode, blkaddr, nr_pages,
					is_readahead ? REQ_RAHEAD : 0,
					f2fs_ra_op_flags(rac),
					page->index, for_write);
			if (IS_ERR(bio)) {
				ret = PTR_ERR(bio);
@@ -2399,7 +2406,7 @@ static int f2fs_mpage_readpages(struct inode *inode,
			ret = f2fs_read_multi_pages(&cc, &bio,
						max_nr_pages,
						&last_block_in_bio,
						rac != NULL, false);
						rac, false);
			f2fs_destroy_compress_ctx(&cc, false);
			if (ret)
				goto set_error_page;
@@ -2449,7 +2456,7 @@ static int f2fs_mpage_readpages(struct inode *inode,
				ret = f2fs_read_multi_pages(&cc, &bio,
							max_nr_pages,
							&last_block_in_bio,
							rac != NULL, false);
							rac, false);
				f2fs_destroy_compress_ctx(&cc, false);
			}
		}
@@ -2601,7 +2608,7 @@ bool f2fs_should_update_outplace(struct inode *inode, struct f2fs_io_info *fio)
		return true;
	if (IS_NOQUOTA(inode))
		return true;
	if (f2fs_is_atomic_file(inode))
	if (f2fs_used_in_atomic_write(inode))
		return true;
	/* rewrite low ratio compress data w/ OPU mode to avoid fragmentation */
	if (f2fs_compressed_file(inode) &&
@@ -2688,7 +2695,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
	}

	/* wait for GCed page writeback via META_MAPPING */
	if (fio->post_read)
	if (fio->meta_gc)
		f2fs_wait_on_block_writeback(inode, fio->old_blkaddr);

	/*
@@ -2783,7 +2790,7 @@ int f2fs_write_single_data_page(struct page *page, int *submitted,
		.submitted = 0,
		.compr_blocks = compr_blocks,
		.need_lock = compr_blocks ? LOCK_DONE : LOCK_RETRY,
		.post_read = f2fs_post_read_required(inode) ? 1 : 0,
		.meta_gc = f2fs_meta_inode_gc_required(inode) ? 1 : 0,
		.io_type = io_type,
		.io_wbc = wbc,
		.bio = bio,
+19 −29
Original line number Diff line number Diff line
@@ -19,33 +19,23 @@
#include "node.h"
#include <trace/events/f2fs.h>

bool sanity_check_extent_cache(struct inode *inode)
bool sanity_check_extent_cache(struct inode *inode, struct page *ipage)
{
	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
	struct f2fs_inode_info *fi = F2FS_I(inode);
	struct extent_tree *et = fi->extent_tree[EX_READ];
	struct extent_info *ei;

	if (!et)
		return true;
	struct f2fs_extent *i_ext = &F2FS_INODE(ipage)->i_ext;
	struct extent_info ei;

	ei = &et->largest;
	if (!ei->len)
		return true;
	get_read_extent_info(&ei, i_ext);

	/* Let's drop, if checkpoint got corrupted. */
	if (is_set_ckpt_flags(sbi, CP_ERROR_FLAG)) {
		ei->len = 0;
		et->largest_updated = true;
	if (!ei.len)
		return true;
	}

	if (!f2fs_is_valid_blkaddr(sbi, ei->blk, DATA_GENERIC_ENHANCE) ||
	    !f2fs_is_valid_blkaddr(sbi, ei->blk + ei->len - 1,
	if (!f2fs_is_valid_blkaddr(sbi, ei.blk, DATA_GENERIC_ENHANCE) ||
	    !f2fs_is_valid_blkaddr(sbi, ei.blk + ei.len - 1,
					DATA_GENERIC_ENHANCE)) {
		f2fs_warn(sbi, "%s: inode (ino=%lx) extent info [%u, %u, %u] is incorrect, run fsck to fix",
			  __func__, inode->i_ino,
			  ei->blk, ei->fofs, ei->len);
			  ei.blk, ei.fofs, ei.len);
		return false;
	}
	return true;
@@ -394,24 +384,22 @@ void f2fs_init_read_extent_tree(struct inode *inode, struct page *ipage)

	if (!__may_extent_tree(inode, EX_READ)) {
		/* drop largest read extent */
		if (i_ext && i_ext->len) {
		if (i_ext->len) {
			f2fs_wait_on_page_writeback(ipage, NODE, true, true);
			i_ext->len = 0;
			set_page_dirty(ipage);
		}
		goto out;
		set_inode_flag(inode, FI_NO_EXTENT);
		return;
	}

	et = __grab_extent_tree(inode, EX_READ);

	if (!i_ext || !i_ext->len)
		goto out;

	get_read_extent_info(&ei, i_ext);

	write_lock(&et->lock);
	if (atomic_read(&et->node_cnt))
		goto unlock_out;
	if (atomic_read(&et->node_cnt) || !ei.len)
		goto skip;

	en = __attach_extent_node(sbi, et, &ei, NULL,
				&et->root.rb_root.rb_node, true);
@@ -423,11 +411,13 @@ void f2fs_init_read_extent_tree(struct inode *inode, struct page *ipage)
		list_add_tail(&en->list, &eti->extent_list);
		spin_unlock(&eti->extent_lock);
	}
unlock_out:
skip:
	/* Let's drop, if checkpoint got corrupted. */
	if (f2fs_cp_error(sbi)) {
		et->largest.len = 0;
		et->largest_updated = true;
	}
	write_unlock(&et->lock);
out:
	if (!F2FS_I(inode)->extent_tree[EX_READ])
		set_inode_flag(inode, FI_NO_EXTENT);
}

void f2fs_init_age_extent_tree(struct inode *inode)
+42 −36
Original line number Diff line number Diff line
@@ -803,6 +803,7 @@ enum {
	FI_COW_FILE,		/* indicate COW file */
	FI_ATOMIC_COMMITTED,	/* indicate atomic commit completed except disk sync */
	FI_ATOMIC_REPLACE,	/* indicate atomic replace */
	FI_OPENED_FILE,		/* indicate file has been opened */
	FI_MAX,			/* max flag, never be used */
};

@@ -842,7 +843,11 @@ struct f2fs_inode_info {
	struct task_struct *atomic_write_task;	/* store atomic write task */
	struct extent_tree *extent_tree[NR_EXTENT_CACHES];
					/* cached extent_tree entry */
	union {
		struct inode *cow_inode;	/* copy-on-write inode for atomic write */
		struct inode *atomic_inode;
					/* point to atomic_inode, available only for cow_inode */
	};

	/* avoid racing between foreground op and gc */
	struct f2fs_rwsem i_gc_rwsem[2];
@@ -1210,7 +1215,7 @@ struct f2fs_io_info {
	unsigned int in_list:1;		/* indicate fio is in io_list */
	unsigned int is_por:1;		/* indicate IO is from recovery or not */
	unsigned int encrypted:1;	/* indicate file is encrypted */
	unsigned int post_read:1;	/* require post read */
	unsigned int meta_gc:1;		/* require meta inode GC */
	enum iostat_type io_type;	/* io type */
	struct writeback_control *io_wbc; /* writeback control */
	struct bio **bio;		/* bio for ipu */
@@ -3222,21 +3227,15 @@ static inline bool f2fs_need_compress_data(struct inode *inode)
	return false;
}

static inline unsigned int addrs_per_inode(struct inode *inode)
static inline unsigned int addrs_per_page(struct inode *inode,
							bool is_inode)
{
	unsigned int addrs = CUR_ADDRS_PER_INODE(inode) -
				get_inline_xattr_addrs(inode);
	unsigned int addrs = is_inode ? (CUR_ADDRS_PER_INODE(inode) -
			get_inline_xattr_addrs(inode)) : DEF_ADDRS_PER_BLOCK;

	if (!f2fs_compressed_file(inode))
		return addrs;
	if (f2fs_compressed_file(inode))
		return ALIGN_DOWN(addrs, F2FS_I(inode)->i_cluster_size);
}

static inline unsigned int addrs_per_block(struct inode *inode)
{
	if (!f2fs_compressed_file(inode))
		return DEF_ADDRS_PER_BLOCK;
	return ALIGN_DOWN(DEF_ADDRS_PER_BLOCK, F2FS_I(inode)->i_cluster_size);
	return addrs;
}

static inline void *inline_xattr_addr(struct inode *inode, struct page *page)
@@ -3706,6 +3705,7 @@ void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
bool f2fs_segment_has_free_slot(struct f2fs_sb_info *sbi, int segno);
int f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi);
int f2fs_reinit_atgc_curseg(struct f2fs_sb_info *sbi);
void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi);
void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi);
int f2fs_allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type,
@@ -4163,7 +4163,7 @@ extern struct kmem_cache *f2fs_inode_entry_slab;
 * inline.c
 */
bool f2fs_may_inline_data(struct inode *inode);
bool f2fs_sanity_check_inline_data(struct inode *inode);
bool f2fs_sanity_check_inline_data(struct inode *inode, struct page *ipage);
bool f2fs_may_inline_dentry(struct inode *inode);
void f2fs_do_read_inline_data(struct folio *folio, struct page *ipage);
void f2fs_truncate_inline_inode(struct inode *inode,
@@ -4204,7 +4204,7 @@ void f2fs_leave_shrinker(struct f2fs_sb_info *sbi);
/*
 * extent_cache.c
 */
bool sanity_check_extent_cache(struct inode *inode);
bool sanity_check_extent_cache(struct inode *inode, struct page *ipage);
void f2fs_init_extent_tree(struct inode *inode);
void f2fs_drop_extent_tree(struct inode *inode);
void f2fs_destroy_extent_node(struct inode *inode);
@@ -4275,6 +4275,16 @@ static inline bool f2fs_post_read_required(struct inode *inode)
		f2fs_compressed_file(inode);
}

static inline bool f2fs_used_in_atomic_write(struct inode *inode)
{
	return f2fs_is_atomic_file(inode) || f2fs_is_cow_file(inode);
}

static inline bool f2fs_meta_inode_gc_required(struct inode *inode)
{
	return f2fs_post_read_required(inode) || f2fs_used_in_atomic_write(inode);
}

/*
 * compress.c
 */
@@ -4310,7 +4320,7 @@ void f2fs_update_read_extent_tree_range_compressed(struct inode *inode,
				unsigned int llen, unsigned int c_len);
int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
				unsigned nr_pages, sector_t *last_block_in_bio,
				bool is_readahead, bool for_write);
				struct readahead_control *rac, bool for_write);
struct decompress_io_ctx *f2fs_alloc_dic(struct compress_ctx *cc);
void f2fs_decompress_end_io(struct decompress_io_ctx *dic, bool failed,
				bool in_task);
@@ -4401,22 +4411,18 @@ static inline int set_compress_context(struct inode *inode)
{
#ifdef CONFIG_F2FS_FS_COMPRESSION
	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
	struct f2fs_inode_info *fi = F2FS_I(inode);

	F2FS_I(inode)->i_compress_algorithm =
			F2FS_OPTION(sbi).compress_algorithm;
	F2FS_I(inode)->i_log_cluster_size =
			F2FS_OPTION(sbi).compress_log_size;
	F2FS_I(inode)->i_compress_flag =
			F2FS_OPTION(sbi).compress_chksum ?
	fi->i_compress_algorithm = F2FS_OPTION(sbi).compress_algorithm;
	fi->i_log_cluster_size = F2FS_OPTION(sbi).compress_log_size;
	fi->i_compress_flag = F2FS_OPTION(sbi).compress_chksum ?
					BIT(COMPRESS_CHKSUM) : 0;
	F2FS_I(inode)->i_cluster_size =
			BIT(F2FS_I(inode)->i_log_cluster_size);
	if ((F2FS_I(inode)->i_compress_algorithm == COMPRESS_LZ4 ||
		F2FS_I(inode)->i_compress_algorithm == COMPRESS_ZSTD) &&
	fi->i_cluster_size = BIT(fi->i_log_cluster_size);
	if ((fi->i_compress_algorithm == COMPRESS_LZ4 ||
		fi->i_compress_algorithm == COMPRESS_ZSTD) &&
			F2FS_OPTION(sbi).compress_level)
		F2FS_I(inode)->i_compress_level =
				F2FS_OPTION(sbi).compress_level;
	F2FS_I(inode)->i_flags |= F2FS_COMPR_FL;
		fi->i_compress_level = F2FS_OPTION(sbi).compress_level;
	fi->i_flags |= F2FS_COMPR_FL;
	set_inode_flag(inode, FI_COMPRESSED_FILE);
	stat_inc_compr_inode(inode);
	inc_compr_inode_stat(inode);
@@ -4431,15 +4437,15 @@ static inline bool f2fs_disable_compressed_file(struct inode *inode)
{
	struct f2fs_inode_info *fi = F2FS_I(inode);

	f2fs_down_write(&F2FS_I(inode)->i_sem);
	f2fs_down_write(&fi->i_sem);

	if (!f2fs_compressed_file(inode)) {
		f2fs_up_write(&F2FS_I(inode)->i_sem);
		f2fs_up_write(&fi->i_sem);
		return true;
	}
	if (f2fs_is_mmap_file(inode) ||
		(S_ISREG(inode->i_mode) && F2FS_HAS_BLOCKS(inode))) {
		f2fs_up_write(&F2FS_I(inode)->i_sem);
		f2fs_up_write(&fi->i_sem);
		return false;
	}

@@ -4448,7 +4454,7 @@ static inline bool f2fs_disable_compressed_file(struct inode *inode)
	clear_inode_flag(inode, FI_COMPRESSED_FILE);
	f2fs_mark_inode_dirty_sync(inode, true);

	f2fs_up_write(&F2FS_I(inode)->i_sem);
	f2fs_up_write(&fi->i_sem);
	return true;
}

Loading