mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-16 09:13:55 +08:00
f2fs-fix-5.18
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+) -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE00UqedjCtOrGVvQiQBSofoJIUNIFAmJmzzYACgkQQBSofoJI UNKuLw/+M3J/WCNH8Zuysgt3eJ6K9e2jtT/xfj+p/s52lileP4ljtnWJ7x8YaViX sMbzLkDL4tPip2SuNEQifW2EmMCJ6BCCWV5+SIK5/rEiwRYuhFygVqQIHn2S8g5O gWixusQ/NYaUN6e3Bi/7WjUhWmeV4oyhv6WB+sS3f0zaNs9RGoe/K3yNGeLLWm+/ 0Pz6P2LAARs/N/iSw03KWv+1BzMJxbLC1w38boPbysv5oT59+gtxKGVSxie1cce8 F5mMt1Z7JplPUKhbjrqYo9LzNzAFIgIt3P6mbclE7ASKi9UYOtiT3nvikj6lygbM i9FHIcP6bqtjU7GZ5vVbYDW43pGZN+6Hlz7Fu1I3ix4Z2eyFWc/W1Fl6OmjvjVpj t/iafwvvdqm1NChLkJx3EXquDDuhxvKhbuuaTwLpuNt+56OvFJ0e91kZhWwbB3dY 7y80N+VgB0MvFStWeZD85lMvSYfXmv5dnjCu6+nAxRzlsx+JVs8STN6+KHSiVeoY LbtyR1sViO0UGNVZAd8XLs8CIScfxatx059ui0wW+Bh2JOy2p5RW0vUKxFzm9/ZJ OtRT2W0fdyutYpfwERxny706cV3wOOOP20a/2NC4HgUVWLYNO6hnLeDK7+WlOMqP XHWKpkRzwLtZQKVyFNDtFHoYgQKCltQNNp6t/qJnSGC1Q1Cchfo= =nBQL -----END PGP SIGNATURE----- Merge tag 'f2fs-fix-5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs 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
This commit is contained in:
commit
d615b5416f
@ -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
|
||||
-------------------
|
||||
|
||||
|
@ -98,9 +98,9 @@ repeat:
|
||||
}
|
||||
|
||||
if (unlikely(!PageUptodate(page))) {
|
||||
if (page->index == sbi->metapage_eio_ofs &&
|
||||
sbi->metapage_eio_cnt++ == MAX_RETRY_META_PAGE_EIO) {
|
||||
set_ckpt_flags(sbi, CP_ERROR_FLAG);
|
||||
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;
|
||||
sbi->metapage_eio_cnt = 0;
|
||||
|
@ -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, §or);
|
||||
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;
|
||||
|
@ -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,
|
||||
|
@ -550,7 +550,8 @@ make_now:
|
||||
}
|
||||
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;
|
||||
|
@ -3243,101 +3243,6 @@ int f2fs_rw_hint_to_seg_type(enum rw_hint hint)
|
||||
}
|
||||
}
|
||||
|
||||
/* This returns write hints for each segment type. This hints will be
|
||||
* passed down to block layer. There are mapping tables which depend on
|
||||
* the mount option 'whint_mode'.
|
||||
*
|
||||
* 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
|
||||
* ---- ---- -----
|
||||
* META WRITE_LIFE_NOT_SET
|
||||
* HOT_NODE "
|
||||
* WARM_NODE "
|
||||
* 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
|
||||
* ---- ---- -----
|
||||
* META WRITE_LIFE_MEDIUM;
|
||||
* HOT_NODE WRITE_LIFE_NOT_SET
|
||||
* WARM_NODE "
|
||||
* 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
|
||||
*/
|
||||
|
||||
enum rw_hint f2fs_io_type_to_rw_hint(struct f2fs_sb_info *sbi,
|
||||
enum page_type type, enum temp_type temp)
|
||||
{
|
||||
if (F2FS_OPTION(sbi).whint_mode == WHINT_MODE_USER) {
|
||||
if (type == DATA) {
|
||||
if (temp == WARM)
|
||||
return WRITE_LIFE_NOT_SET;
|
||||
else if (temp == HOT)
|
||||
return WRITE_LIFE_SHORT;
|
||||
else if (temp == COLD)
|
||||
return WRITE_LIFE_EXTREME;
|
||||
} else {
|
||||
return WRITE_LIFE_NOT_SET;
|
||||
}
|
||||
} else if (F2FS_OPTION(sbi).whint_mode == WHINT_MODE_FS) {
|
||||
if (type == DATA) {
|
||||
if (temp == WARM)
|
||||
return WRITE_LIFE_LONG;
|
||||
else if (temp == HOT)
|
||||
return WRITE_LIFE_SHORT;
|
||||
else if (temp == COLD)
|
||||
return WRITE_LIFE_EXTREME;
|
||||
} else if (type == NODE) {
|
||||
if (temp == WARM || temp == HOT)
|
||||
return WRITE_LIFE_NOT_SET;
|
||||
else if (temp == COLD)
|
||||
return WRITE_LIFE_NONE;
|
||||
} else if (type == META) {
|
||||
return WRITE_LIFE_MEDIUM;
|
||||
}
|
||||
}
|
||||
return WRITE_LIFE_NOT_SET;
|
||||
}
|
||||
|
||||
static int __get_segment_type_2(struct f2fs_io_info *fio)
|
||||
{
|
||||
if (fio->type == DATA)
|
||||
|
@ -138,7 +138,6 @@ enum {
|
||||
Opt_jqfmt_vfsold,
|
||||
Opt_jqfmt_vfsv0,
|
||||
Opt_jqfmt_vfsv1,
|
||||
Opt_whint,
|
||||
Opt_alloc,
|
||||
Opt_fsync,
|
||||
Opt_test_dummy_encryption,
|
||||
@ -214,7 +213,6 @@ static match_table_t f2fs_tokens = {
|
||||
{Opt_jqfmt_vfsold, "jqfmt=vfsold"},
|
||||
{Opt_jqfmt_vfsv0, "jqfmt=vfsv0"},
|
||||
{Opt_jqfmt_vfsv1, "jqfmt=vfsv1"},
|
||||
{Opt_whint, "whint_mode=%s"},
|
||||
{Opt_alloc, "alloc_mode=%s"},
|
||||
{Opt_fsync, "fsync_mode=%s"},
|
||||
{Opt_test_dummy_encryption, "test_dummy_encryption=%s"},
|
||||
@ -975,22 +973,6 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
|
||||
f2fs_info(sbi, "quota operations not supported");
|
||||
break;
|
||||
#endif
|
||||
case Opt_whint:
|
||||
name = match_strdup(&args[0]);
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
if (!strcmp(name, "user-based")) {
|
||||
F2FS_OPTION(sbi).whint_mode = WHINT_MODE_USER;
|
||||
} else if (!strcmp(name, "off")) {
|
||||
F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
|
||||
} else if (!strcmp(name, "fs-based")) {
|
||||
F2FS_OPTION(sbi).whint_mode = WHINT_MODE_FS;
|
||||
} else {
|
||||
kfree(name);
|
||||
return -EINVAL;
|
||||
}
|
||||
kfree(name);
|
||||
break;
|
||||
case Opt_alloc:
|
||||
name = match_strdup(&args[0]);
|
||||
if (!name)
|
||||
@ -1328,12 +1310,6 @@ default_check:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Not pass down write hints if the number of active logs is lesser
|
||||
* than NR_CURSEG_PERSIST_TYPE.
|
||||
*/
|
||||
if (F2FS_OPTION(sbi).active_logs != NR_CURSEG_PERSIST_TYPE)
|
||||
F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
|
||||
|
||||
if (f2fs_sb_has_readonly(sbi) && !f2fs_readonly(sbi->sb)) {
|
||||
f2fs_err(sbi, "Allow to mount readonly mode only");
|
||||
return -EROFS;
|
||||
@ -1978,10 +1954,6 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
|
||||
seq_puts(seq, ",prjquota");
|
||||
#endif
|
||||
f2fs_show_quota_options(seq, sbi->sb);
|
||||
if (F2FS_OPTION(sbi).whint_mode == WHINT_MODE_USER)
|
||||
seq_printf(seq, ",whint_mode=%s", "user-based");
|
||||
else if (F2FS_OPTION(sbi).whint_mode == WHINT_MODE_FS)
|
||||
seq_printf(seq, ",whint_mode=%s", "fs-based");
|
||||
|
||||
fscrypt_show_test_dummy_encryption(seq, ',', sbi->sb);
|
||||
|
||||
@ -2033,7 +2005,6 @@ static void default_options(struct f2fs_sb_info *sbi)
|
||||
F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
|
||||
|
||||
F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
|
||||
F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
|
||||
F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
|
||||
F2FS_OPTION(sbi).fsync_mode = FSYNC_MODE_POSIX;
|
||||
F2FS_OPTION(sbi).s_resuid = make_kuid(&init_user_ns, F2FS_DEF_RESUID);
|
||||
@ -2314,8 +2285,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
|
||||
need_stop_gc = true;
|
||||
}
|
||||
|
||||
if (*flags & SB_RDONLY ||
|
||||
F2FS_OPTION(sbi).whint_mode != org_mount_opt.whint_mode) {
|
||||
if (*flags & SB_RDONLY) {
|
||||
sync_inodes_sb(sb);
|
||||
|
||||
set_sbi_flag(sbi, SBI_IS_DIRTY);
|
||||
|
Loading…
Reference in New Issue
Block a user