From 1045c6433c50055c58c1bbdab10a1d447cdb00c2 Mon Sep 17 00:00:00 2001 From: Li Dongyang Date: Fri, 6 Sep 2024 21:20:24 +1000 Subject: [PATCH] LU-18195 osd-ldiskfs: use IGET_NO_CHECKS for objects under lost+found With e2fsck older than v1.47.1-rc2-10-g849a9e6e1, e2fsck could link ea inode under lost+found, and this creates problems on kernels enforce ea_inode flag checks. Check for lost+found fid and use NO_CHECKS flag in the lfsck code path. Add s_lpf_ino in sbi, and set it by find the lost+found entry during ext4_fill_super(). In ext4_lookup, check if the parent is the lost+found dir. Note lost+found won't be changed when target mounted as lustre, so we only lookup once during mount and don't monitor lost+found entry. Even if it's changed duing e2fsck or mounted as ldiskfs, we could still detect at next mount. Test-Parameters: trivial Test-Parameters: fstype=ldiskfs serverdistro=el9.4 testlist=conf-sanity env=ONLY=61b Change-Id: I95492fcc2f0ec4188dfb92b1dc1aa6055cab6ca8 Signed-off-by: Li Dongyang Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/56276 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Alex Zhuravlev Reviewed-by: Li Xi Reviewed-by: Oleg Drokin --- .../rhel9.4/ext4-add-IGET_NO_CHECKS-flag.patch | 61 +++++++++++++++++++++- lustre/osd-ldiskfs/osd_handler.c | 11 ++-- lustre/osd-ldiskfs/osd_internal.h | 2 +- lustre/osd-ldiskfs/osd_scrub.c | 4 +- 4 files changed, 70 insertions(+), 8 deletions(-) diff --git a/ldiskfs/kernel_patches/patches/rhel9.4/ext4-add-IGET_NO_CHECKS-flag.patch b/ldiskfs/kernel_patches/patches/rhel9.4/ext4-add-IGET_NO_CHECKS-flag.patch index a384290..56ca2bb 100644 --- a/ldiskfs/kernel_patches/patches/rhel9.4/ext4-add-IGET_NO_CHECKS-flag.patch +++ b/ldiskfs/kernel_patches/patches/rhel9.4/ext4-add-IGET_NO_CHECKS-flag.patch @@ -2,7 +2,15 @@ Index: linux-5.14.0-427.24.1.el9_4/fs/ext4/ext4.h =================================================================== --- linux-5.14.0-427.24.1.el9_4.orig/fs/ext4/ext4.h +++ linux-5.14.0-427.24.1.el9_4/fs/ext4/ext4.h -@@ -3176,7 +3176,8 @@ typedef enum { +@@ -1801,6 +1801,7 @@ struct ext4_sb_info { + 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) +@@ -3176,7 +3177,8 @@ typedef enum { 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 */ @@ -25,3 +33,54 @@ Index: linux-5.14.0-427.24.1.el9_4/fs/ext4/inode.c if (flags & EXT4_IGET_EA_INODE) { if (!(EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) return "missing EA_INODE flag"; +Index: linux-5.14.0-427.24.1.el9_4/fs/ext4/namei.c +=================================================================== +--- linux-5.14.0-427.24.1.el9_4.orig/fs/ext4/namei.c ++++ linux-5.14.0-427.24.1.el9_4/fs/ext4/namei.c +@@ -2214,6 +2214,7 @@ static struct dentry *ext4_lookup(struct + 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); +@@ -2234,7 +2235,9 @@ static struct dentry *ext4_lookup(struct + 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", +Index: linux-5.14.0-427.24.1.el9_4/fs/ext4/super.c +=================================================================== +--- linux-5.14.0-427.24.1.el9_4.orig/fs/ext4/super.c ++++ linux-5.14.0-427.24.1.el9_4/fs/ext4/super.c +@@ -5740,6 +5740,9 @@ static int ext4_fill_super(struct super_ + { + struct ext4_fs_context *ctx = fc->fs_private; + struct ext4_sb_info *sbi; ++ struct buffer_head *bh; ++ struct ext4_dir_entry_2 *de; ++ const struct qstr lpf = QSTR_INIT("lost+found", 10); + const char *descr; + int ret; + +@@ -5760,6 +5763,13 @@ static int ext4_fill_super(struct super_ + if (ret < 0) + goto free_sbi; + ++ 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 (sbi->s_journal) { + if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) + descr = " journalled data mode"; diff --git a/lustre/osd-ldiskfs/osd_handler.c b/lustre/osd-ldiskfs/osd_handler.c index 5ec20fc6..4892f1b 100644 --- a/lustre/osd-ldiskfs/osd_handler.c +++ b/lustre/osd-ldiskfs/osd_handler.c @@ -612,13 +612,13 @@ int osd_ldiskfs_add_entry(struct osd_thread_info *info, struct osd_device *osd, struct inode * osd_iget_fid(struct osd_thread_info *info, struct osd_device *dev, - struct osd_inode_id *id, struct lu_fid *fid) + struct osd_inode_id *id, struct lu_fid *fid, int flags) { struct lustre_ost_attrs *loa = &info->oti_ost_attrs; struct inode *inode; int rc; - inode = osd_iget(info, dev, id, 0); + inode = osd_iget(info, dev, id, flags); if (IS_ERR(inode)) return inode; @@ -4171,11 +4171,14 @@ static int osd_ea_fid_get(const struct lu_env *env, struct osd_object *obj, { struct osd_thread_info *info = osd_oti_get(env); struct inode *inode; + struct lu_fid *parent_fid = &obj->oo_dt.do_lu.lo_header->loh_fid; + int flags = lu_fid_eq(parent_fid, &LU_BACKEND_LPF_FID) ? + LDISKFS_IGET_NO_CHECKS : 0; ENTRY; osd_id_gen(id, ino, OSD_OII_NOGEN); - inode = osd_iget_fid(info, osd_obj2dev(obj), id, fid); + inode = osd_iget_fid(info, osd_obj2dev(obj), id, fid, flags); if (IS_ERR(inode)) RETURN(PTR_ERR(inode)); @@ -4380,7 +4383,7 @@ static int osd_process_scheduled_agent_removals(const struct lu_env *env, OBD_FREE_PTR(oor); osd_id_gen(&id, ino, OSD_OII_NOGEN); - inode = osd_iget_fid(info, osd, &id, &fid); + inode = osd_iget_fid(info, osd, &id, &fid, 0); if (IS_ERR(inode)) continue; diff --git a/lustre/osd-ldiskfs/osd_internal.h b/lustre/osd-ldiskfs/osd_internal.h index 1dd86545..09ebcef 100644 --- a/lustre/osd-ldiskfs/osd_internal.h +++ b/lustre/osd-ldiskfs/osd_internal.h @@ -812,7 +812,7 @@ struct inode *osd_iget(struct osd_thread_info *info, struct osd_device *dev, struct osd_inode_id *id, int flags); struct inode * osd_iget_fid(struct osd_thread_info *info, struct osd_device *dev, - struct osd_inode_id *id, struct lu_fid *fid); + struct osd_inode_id *id, struct lu_fid *fid, int flags); int osd_ea_fid_set(struct osd_thread_info *info, struct inode *inode, const struct lu_fid *fid, __u32 compat, __u32 incompat); struct osd_obj_seq *osd_seq_load(struct osd_thread_info *info, diff --git a/lustre/osd-ldiskfs/osd_scrub.c b/lustre/osd-ldiskfs/osd_scrub.c index 446f8c3..12609ab 100644 --- a/lustre/osd-ldiskfs/osd_scrub.c +++ b/lustre/osd-ldiskfs/osd_scrub.c @@ -1820,7 +1820,7 @@ static void osd_index_restore(const struct lu_env *env, struct osd_device *dev, osd_id_gen(id, le32_to_cpu(de->inode), OSD_OII_NOGEN); brelse(bh); - bak_inode = osd_iget_fid(info, dev, id, &bak_fid); + bak_inode = osd_iget_fid(info, dev, id, &bak_fid, 0); if (IS_ERR(bak_inode)) GOTO(log, rc = PTR_ERR(bak_inode)); @@ -3117,7 +3117,7 @@ static int osd_scan_ml_file(const struct lu_env *env, struct osd_device *dev, osd_id_gen(&id, oie->oie_dirent->oied_ino, OSD_OII_NOGEN); if (!fid_is_sane(fid)) - inode = osd_iget_fid(info, dev, &id, fid); + inode = osd_iget_fid(info, dev, &id, fid, 0); else inode = osd_iget(info, dev, &id, 0); -- 1.8.3.1