Viewing: ext4-add-IGET_NO_CHECKS-flag.patch
commit a7239d80fc92380a5a56ff1b0adb99d349f9a0dc
Author: Li Dongyang <dongyangli@ddn.com>
AuthorDate: Wed Jul 31 22:03:32 2024 +1000
LU-18080 ldiskfs: add NO_CHECKS flags for ext4_iget
Since v6.4-rc4-1-gb3e6bcb94590, the upstream kernel introduced
a strict checking of EXT4_IGET_EA_INODE and it has to match the
EXT4_EA_INODE_FL from the inode.
This creates a problem for osd scrub as we iterate over the inodes
according to bitmap we have no idea if the inode is an ea_inode or
not.
Add a new flag EXT4_IGET_NO_CHECKS and relax the strict checking
when the flag is used.
Cleanup osd_ldiskfs_iget_special(), the caller of osd_iget() now are
passing in the additional flags to ext4_iget().
Test-Parameters: trivial
Test-Parameters: fstype=ldiskfs serverdistro=el9.4 testlist=conf-sanity env=ONLY=32a
Signed-off-by: Li Dongyang <dongyangli@ddn.com>
Tested-by: Shuichi Ihara <sihara@ddn.com>
Reviewed-by: Shaun Tancheff <shaun.tancheff@hpe.com>
Reviewed-by: Li Xi <lixi@ddn.com>
Reviewed-by: James Simmons <jsimmons@infradead.org>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Change-Id: I43c8da68b06c5592e197dd3b5e3f4f7c842cf7c4
Reviewed-on: https://review.whamcloud.com/55896
diff -ur b/fs/ext4/ext4.h a/fs/ext4/ext4.h
--- b/fs/ext4/ext4.h 2024-09-15 15:04:20.463952510 -0600
+++ a/fs/ext4/ext4.h 2024-09-15 15:13:46.530227093 -0600
@@ -1776,6 +1776,7 @@
int s_fc_debug_max_replay;
#endif
struct ext4_fc_replay_state s_fc_replay_state;
+ unsigned long s_lpf_ino;
};
static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb)
@@ -3184,7 +3185,8 @@
EXT4_IGET_SPECIAL = 0x0001, /* OK to iget a system inode */
EXT4_IGET_HANDLE = 0x0002, /* Inode # is from a handle */
EXT4_IGET_BAD = 0x0004, /* Allow to iget a bad inode */
- EXT4_IGET_EA_INODE = 0x0008 /* Inode should contain an EA value */
+ EXT4_IGET_EA_INODE = 0x0008, /* Inode should contain an EA value */
+ EXT4_IGET_NO_CHECKS = 0x0010 /* Allow iget without checking */
} ext4_iget_flags;
extern struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
diff -ur b/fs/ext4/inode.c a/fs/ext4/inode.c
--- b/fs/ext4/inode.c 2024-09-15 15:04:20.471952424 -0600
+++ a/fs/ext4/inode.c 2024-09-15 15:13:46.530227093 -0600
@@ -4598,6 +4598,8 @@
static const char *check_igot_inode(struct inode *inode, ext4_iget_flags flags)
{
+ if (flags & EXT4_IGET_NO_CHECKS)
+ return NULL;
if (flags & EXT4_IGET_EA_INODE) {
if (!(EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL))
return "missing EA_INODE flag";
diff -ur b/fs/ext4/namei.c a/fs/ext4/namei.c
--- b/fs/ext4/namei.c 2024-09-15 15:04:20.463952510 -0600
+++ a/fs/ext4/namei.c 2024-09-15 15:13:46.530227093 -0600
@@ -2211,6 +2211,7 @@
struct inode *inode;
struct ext4_dir_entry_2 *de;
struct buffer_head *bh;
+ struct ext4_sb_info *sbi = EXT4_SB(dir->i_sb);
if (dentry->d_name.len > EXT4_NAME_LEN)
return ERR_PTR(-ENAMETOOLONG);
@@ -2231,7 +2232,9 @@
dentry);
return ERR_PTR(-EFSCORRUPTED);
}
- inode = ext4_iget(dir->i_sb, ino, EXT4_IGET_NORMAL);
+ inode = ext4_iget(dir->i_sb, ino,
+ dir->i_ino == sbi->s_lpf_ino ?
+ EXT4_IGET_NO_CHECKS : EXT4_IGET_NORMAL);
if (inode == ERR_PTR(-ESTALE)) {
EXT4_ERROR_INODE(dir,
"deleted inode referenced: %u",
diff -ur b/fs/ext4/super.c a/fs/ext4/super.c
--- b/fs/ext4/super.c 2024-09-15 15:04:20.475952380 -0600
+++ a/fs/ext4/super.c 2024-09-15 15:21:28.621861173 -0600
@@ -3949,6 +3949,8 @@
struct ext4_super_block *es = NULL;
struct ext4_sb_info *sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
struct flex_groups **flex_groups;
+ const struct qstr lpf = QSTR_INIT("lost+found", 10);
+ struct ext4_dir_entry_2 *de;
ext4_fsblk_t block;
ext4_fsblk_t sb_block = get_sb_block(&data);
ext4_fsblk_t logical_sb_block;
@@ -5041,6 +5043,14 @@
if (err)
goto failed_mount10;
}
+
+ bh = ext4_find_entry_locked(d_inode(sb->s_root), &lpf, &de, NULL, NULL);
+ if (!IS_ERR(bh) && bh) {
+ if (ext4_valid_inum(sb, le32_to_cpu(de->inode)))
+ sbi->s_lpf_ino = le32_to_cpu(de->inode);
+ brelse(bh);
+ }
+
if (EXT4_SB(sb)->s_journal) {
if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
descr = " journalled data mode";