Commit d615b541 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull f2fs fixes from Jaegeuk Kim:
 "This includes major bug fixes introduced in 5.18-rc1 and 5.17+:

   - Remove obsolete whint_mode (5.18-rc1)

   - Fix IO split issue caused by op_flags change in f2fs (5.18-rc1)

   - Fix a wrong condition check to detect IO failure loop (5.18-rc1)

   - Fix wrong data truncation during roll-forward (5.17+)"

* tag 'f2fs-fix-5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs:
  f2fs: should not truncate blocks during roll-forward recovery
  f2fs: fix wrong condition check when failing metapage read
  f2fs: keep io_flags to avoid IO split due to different op_flags in two fio holders
  f2fs: remove obsolete whint_mode
parents 0fc74d82 4d8ec912
Loading
Loading
Loading
Loading
+0 −70
Original line number Diff line number Diff line
@@ -235,12 +235,6 @@ offgrpjquota Turn off group journalled quota.
offprjjquota		 Turn off project journalled quota.
quota			 Enable plain user disk quota accounting.
noquota			 Disable all plain disk quota option.
whint_mode=%s		 Control which write hints are passed down to block
			 layer. This supports "off", "user-based", and
			 "fs-based".  In "off" mode (default), f2fs does not pass
			 down hints. In "user-based" mode, f2fs tries to pass
			 down hints given by users. And in "fs-based" mode, f2fs
			 passes down hints with its policy.
alloc_mode=%s		 Adjust block allocation policy, which supports "reuse"
			 and "default".
fsync_mode=%s		 Control the policy of fsync. Currently supports "posix",
@@ -751,70 +745,6 @@ In order to identify whether the data in the victim segment are valid or not,
F2FS manages a bitmap. Each bit represents the validity of a block, and the
bitmap is composed of a bit stream covering whole blocks in main area.

Write-hint Policy
-----------------

1) whint_mode=off. F2FS only passes down WRITE_LIFE_NOT_SET.

2) whint_mode=user-based. F2FS tries to pass down hints given by
users.

===================== ======================== ===================
User                  F2FS                     Block
===================== ======================== ===================
N/A                   META                     WRITE_LIFE_NOT_SET
N/A                   HOT_NODE                 "
N/A                   WARM_NODE                "
N/A                   COLD_NODE                "
ioctl(COLD)           COLD_DATA                WRITE_LIFE_EXTREME
extension list        "                        "

-- buffered io
WRITE_LIFE_EXTREME    COLD_DATA                WRITE_LIFE_EXTREME
WRITE_LIFE_SHORT      HOT_DATA                 WRITE_LIFE_SHORT
WRITE_LIFE_NOT_SET    WARM_DATA                WRITE_LIFE_NOT_SET
WRITE_LIFE_NONE       "                        "
WRITE_LIFE_MEDIUM     "                        "
WRITE_LIFE_LONG       "                        "

-- direct io
WRITE_LIFE_EXTREME    COLD_DATA                WRITE_LIFE_EXTREME
WRITE_LIFE_SHORT      HOT_DATA                 WRITE_LIFE_SHORT
WRITE_LIFE_NOT_SET    WARM_DATA                WRITE_LIFE_NOT_SET
WRITE_LIFE_NONE       "                        WRITE_LIFE_NONE
WRITE_LIFE_MEDIUM     "                        WRITE_LIFE_MEDIUM
WRITE_LIFE_LONG       "                        WRITE_LIFE_LONG
===================== ======================== ===================

3) whint_mode=fs-based. F2FS passes down hints with its policy.

===================== ======================== ===================
User                  F2FS                     Block
===================== ======================== ===================
N/A                   META                     WRITE_LIFE_MEDIUM;
N/A                   HOT_NODE                 WRITE_LIFE_NOT_SET
N/A                   WARM_NODE                "
N/A                   COLD_NODE                WRITE_LIFE_NONE
ioctl(COLD)           COLD_DATA                WRITE_LIFE_EXTREME
extension list        "                        "

-- buffered io
WRITE_LIFE_EXTREME    COLD_DATA                WRITE_LIFE_EXTREME
WRITE_LIFE_SHORT      HOT_DATA                 WRITE_LIFE_SHORT
WRITE_LIFE_NOT_SET    WARM_DATA                WRITE_LIFE_LONG
WRITE_LIFE_NONE       "                        "
WRITE_LIFE_MEDIUM     "                        "
WRITE_LIFE_LONG       "                        "

-- direct io
WRITE_LIFE_EXTREME    COLD_DATA                WRITE_LIFE_EXTREME
WRITE_LIFE_SHORT      HOT_DATA                 WRITE_LIFE_SHORT
WRITE_LIFE_NOT_SET    WARM_DATA                WRITE_LIFE_NOT_SET
WRITE_LIFE_NONE       "                        WRITE_LIFE_NONE
WRITE_LIFE_MEDIUM     "                        WRITE_LIFE_MEDIUM
WRITE_LIFE_LONG       "                        WRITE_LIFE_LONG
===================== ======================== ===================

Fallocate(2) Policy
-------------------

+3 −3
Original line number Diff line number Diff line
@@ -98,8 +98,8 @@ static struct page *__get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index,
	}

	if (unlikely(!PageUptodate(page))) {
		if (page->index == sbi->metapage_eio_ofs &&
			sbi->metapage_eio_cnt++ == MAX_RETRY_META_PAGE_EIO) {
		if (page->index == sbi->metapage_eio_ofs) {
			if (sbi->metapage_eio_cnt++ == MAX_RETRY_META_PAGE_EIO)
				set_ckpt_flags(sbi, CP_ERROR_FLAG);
		} else {
			sbi->metapage_eio_ofs = page->index;
+21 −12
Original line number Diff line number Diff line
@@ -388,11 +388,23 @@ int f2fs_target_device_index(struct f2fs_sb_info *sbi, block_t blkaddr)
	return 0;
}

static void __attach_io_flag(struct f2fs_io_info *fio, unsigned int io_flag)
static unsigned int f2fs_io_flags(struct f2fs_io_info *fio)
{
	unsigned int temp_mask = (1 << NR_TEMP_TYPE) - 1;
	unsigned int fua_flag = io_flag & temp_mask;
	unsigned int meta_flag = (io_flag >> NR_TEMP_TYPE) & temp_mask;
	unsigned int fua_flag, meta_flag, io_flag;
	unsigned int op_flags = 0;

	if (fio->op != REQ_OP_WRITE)
		return 0;
	if (fio->type == DATA)
		io_flag = fio->sbi->data_io_flag;
	else if (fio->type == NODE)
		io_flag = fio->sbi->node_io_flag;
	else
		return 0;

	fua_flag = io_flag & temp_mask;
	meta_flag = (io_flag >> NR_TEMP_TYPE) & temp_mask;

	/*
	 * data/node io flag bits per temp:
@@ -401,9 +413,10 @@ static void __attach_io_flag(struct f2fs_io_info *fio, unsigned int io_flag)
	 * Cold | Warm | Hot | Cold | Warm | Hot |
	 */
	if ((1 << fio->temp) & meta_flag)
		fio->op_flags |= REQ_META;
		op_flags |= REQ_META;
	if ((1 << fio->temp) & fua_flag)
		fio->op_flags |= REQ_FUA;
		op_flags |= REQ_FUA;
	return op_flags;
}

static struct bio *__bio_alloc(struct f2fs_io_info *fio, int npages)
@@ -413,14 +426,10 @@ static struct bio *__bio_alloc(struct f2fs_io_info *fio, int npages)
	sector_t sector;
	struct bio *bio;

	if (fio->type == DATA)
		__attach_io_flag(fio, sbi->data_io_flag);
	else if (fio->type == NODE)
		__attach_io_flag(fio, sbi->node_io_flag);

	bdev = f2fs_target_device(sbi, fio->new_blkaddr, &sector);
	bio = bio_alloc_bioset(bdev, npages, fio->op | fio->op_flags, GFP_NOIO,
			       &f2fs_bioset);
	bio = bio_alloc_bioset(bdev, npages,
				fio->op | fio->op_flags | f2fs_io_flags(fio),
				GFP_NOIO, &f2fs_bioset);
	bio->bi_iter.bi_sector = sector;
	if (is_read_io(fio->op)) {
		bio->bi_end_io = f2fs_read_end_io;
+0 −9
Original line number Diff line number Diff line
@@ -154,7 +154,6 @@ struct f2fs_mount_info {
	int s_jquota_fmt;			/* Format of quota to use */
#endif
	/* For which write hints are passed down to block layer */
	int whint_mode;
	int alloc_mode;			/* segment allocation policy */
	int fsync_mode;			/* fsync policy */
	int fs_mode;			/* fs mode: LFS or ADAPTIVE */
@@ -1333,12 +1332,6 @@ enum {
	FS_MODE_FRAGMENT_BLK,		/* block fragmentation mode */
};

enum {
	WHINT_MODE_OFF,		/* not pass down write hints */
	WHINT_MODE_USER,	/* try to pass down hints given by users */
	WHINT_MODE_FS,		/* pass down hints with F2FS policy */
};

enum {
	ALLOC_MODE_DEFAULT,	/* stay default */
	ALLOC_MODE_REUSE,	/* reuse segments as much as possible */
@@ -3657,8 +3650,6 @@ void f2fs_destroy_segment_manager(struct f2fs_sb_info *sbi);
int __init f2fs_create_segment_manager_caches(void);
void f2fs_destroy_segment_manager_caches(void);
int f2fs_rw_hint_to_seg_type(enum rw_hint hint);
enum rw_hint f2fs_io_type_to_rw_hint(struct f2fs_sb_info *sbi,
			enum page_type type, enum temp_type temp);
unsigned int f2fs_usable_segs_in_sec(struct f2fs_sb_info *sbi,
			unsigned int segno);
unsigned int f2fs_usable_blks_in_seg(struct f2fs_sb_info *sbi,
+2 −1
Original line number Diff line number Diff line
@@ -550,7 +550,8 @@ struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
	}
	f2fs_set_inode_flags(inode);

	if (file_should_truncate(inode)) {
	if (file_should_truncate(inode) &&
			!is_sbi_flag_set(sbi, SBI_POR_DOING)) {
		ret = f2fs_truncate(inode);
		if (ret)
			goto bad_inode;
Loading