From a7239d80fc92380a5a56ff1b0adb99d349f9a0dc Mon Sep 17 00:00:00 2001 From: Li Dongyang Date: Wed, 31 Jul 2024 22:03:32 +1000 Subject: [PATCH] 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 Change-Id: I43c8da68b06c5592e197dd3b5e3f4f7c842cf7c4 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/55896 Tested-by: jenkins Tested-by: Shuichi Ihara Tested-by: Maloo Reviewed-by: Shaun Tancheff Reviewed-by: Li Xi Reviewed-by: James Simmons Reviewed-by: Oleg Drokin --- config/lustre-build-ldiskfs.m4 | 25 ++++++++++++++++++++ .../rhel9.4/ext4-add-IGET_NO_CHECKS-flag.patch | 27 ++++++++++++++++++++++ .../series/ldiskfs-5.14-rhel9.4.series | 1 + .../series/ldiskfs-5.15.0-106-ubuntu20.series | 1 + .../kernel_patches/series/ldiskfs-6.10-ml.series | 1 + .../kernel_patches/series/ldiskfs-6.6-ml.series | 1 + .../kernel_patches/series/ldiskfs-6.7-ml.series | 1 + lustre/osd-ldiskfs/osd_compat.c | 6 ++--- lustre/osd-ldiskfs/osd_handler.c | 25 ++++++++++---------- lustre/osd-ldiskfs/osd_internal.h | 17 +++++++------- lustre/osd-ldiskfs/osd_oi.c | 4 ++-- lustre/osd-ldiskfs/osd_scrub.c | 18 +++++++-------- 12 files changed, 93 insertions(+), 34 deletions(-) create mode 100644 ldiskfs/kernel_patches/patches/rhel9.4/ext4-add-IGET_NO_CHECKS-flag.patch diff --git a/config/lustre-build-ldiskfs.m4 b/config/lustre-build-ldiskfs.m4 index 4e29337..1ba84ec 100644 --- a/config/lustre-build-ldiskfs.m4 +++ b/config/lustre-build-ldiskfs.m4 @@ -357,6 +357,29 @@ AC_DEFUN([LB_LDISKFS_IGET_HAS_FLAGS_ARG], [ ]) # LB_LDISKFS_IGET_HAS_FLAGS_ARG # +# LB_LDISKFS_IGET_EA_INODE +# +# kernel 6.4 commit b3e6bcb94590dea45396b9481e47b809b1be4afa +# extra iget flag EXT4_IGET_NO_CHECKS introduced to relax the ea_inode check. +# +AC_DEFUN([LB_SRC_LDISKFS_IGET_EA_INODE], [ + LB2_LINUX_TEST_SRC([ext4_iget_ea_inode], [ + #include + #include "$EXT4_SRC_DIR/ext4.h" + ],[ + int f = EXT4_IGET_EA_INODE; + (void)f; + ],[-Werror]) +]) +AC_DEFUN([LB_LDISKFS_IGET_EA_INODE], [ + LB2_MSG_LINUX_TEST_RESULT([if 'EXT4_IGET_EA_INODE' exists], + [ext4_iget_ea_inode], [ + AC_DEFINE(HAVE_LDISKFS_IGET_EA_INODE, 1, + ['EXT4_IGET_EA_INODE' exists]) + ]) +]) # LB_LDISKFS_IGET_EA_INODE + +# # LDISKFS_AC_PATCH_PROGRAM # # Determine which program should be used to apply the patches to @@ -648,6 +671,7 @@ AC_DEFUN([LB_KABI_LDISKFS], [AS_IF([test x$enable_ldiskfs != xno],[ LB_SRC_EXT4_HAVE_I_CRYPT_INFO LB_SRC_LDISKFS_JOURNAL_ENSURE_CREDITS LB_SRC_LDISKFS_IGET_HAS_FLAGS_ARG + LB_SRC_LDISKFS_IGET_EA_INODE LB_SRC_LDISKFS_FIND_ENTRY_LOCKED_EXISTS LB_SRC_LDISKFSFS_DIRHASH_WANTS_DIR LB_SRC_JBD2_H_TOTAL_CREDITS @@ -660,6 +684,7 @@ AC_DEFUN([LB_KABI_LDISKFS], [AS_IF([test x$enable_ldiskfs != xno],[ LB_EXT4_HAVE_I_CRYPT_INFO LB_LDISKFS_JOURNAL_ENSURE_CREDITS LB_LDISKFS_IGET_HAS_FLAGS_ARG + LB_LDISKFS_IGET_EA_INODE LB_LDISKFS_FIND_ENTRY_LOCKED_EXISTS LB_LDISKFSFS_DIRHASH_WANTS_DIR LB_JBD2_H_TOTAL_CREDITS 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 new file mode 100644 index 0000000..a384290 --- /dev/null +++ b/ldiskfs/kernel_patches/patches/rhel9.4/ext4-add-IGET_NO_CHECKS-flag.patch @@ -0,0 +1,27 @@ +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 { + 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, +Index: linux-5.14.0-427.24.1.el9_4/fs/ext4/inode.c +=================================================================== +--- linux-5.14.0-427.24.1.el9_4.orig/fs/ext4/inode.c ++++ linux-5.14.0-427.24.1.el9_4/fs/ext4/inode.c +@@ -4834,6 +4834,8 @@ static inline void ext4_inode_set_iversi + 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 --git a/ldiskfs/kernel_patches/series/ldiskfs-5.14-rhel9.4.series b/ldiskfs/kernel_patches/series/ldiskfs-5.14-rhel9.4.series index a5d4ce7..ce45357 100644 --- a/ldiskfs/kernel_patches/series/ldiskfs-5.14-rhel9.4.series +++ b/ldiskfs/kernel_patches/series/ldiskfs-5.14-rhel9.4.series @@ -37,3 +37,4 @@ rhel9.2/ext4-filename-encode.patch rhel9.1/ext4-enc-flag.patch rhel9.2/ext4-encdata.patch rhel9/ext4-add-periodic-superblock-update.patch +rhel9.4/ext4-add-IGET_NO_CHECKS-flag.patch diff --git a/ldiskfs/kernel_patches/series/ldiskfs-5.15.0-106-ubuntu20.series b/ldiskfs/kernel_patches/series/ldiskfs-5.15.0-106-ubuntu20.series index 3a1201a..db9c46f 100644 --- a/ldiskfs/kernel_patches/series/ldiskfs-5.15.0-106-ubuntu20.series +++ b/ldiskfs/kernel_patches/series/ldiskfs-5.15.0-106-ubuntu20.series @@ -36,3 +36,4 @@ ubuntu20.04.5/ext4-filename-encode.patch rhel9.1/ext4-enc-flag.patch rhel9.2/ext4-encdata.patch rhel9/ext4-add-periodic-superblock-update.patch +rhel9.4/ext4-add-IGET_NO_CHECKS-flag.patch diff --git a/ldiskfs/kernel_patches/series/ldiskfs-6.10-ml.series b/ldiskfs/kernel_patches/series/ldiskfs-6.10-ml.series index 99db9cb..0767636 100644 --- a/ldiskfs/kernel_patches/series/ldiskfs-6.10-ml.series +++ b/ldiskfs/kernel_patches/series/ldiskfs-6.10-ml.series @@ -35,3 +35,4 @@ rhel8/ext4-old_ea_inodes_handling_fix.patch linux-6.10/ext4-filename-encode.patch rhel9.1/ext4-enc-flag.patch linux-6.6/ext4-encdata.patch +rhel9.4/ext4-add-IGET_NO_CHECKS-flag.patch diff --git a/ldiskfs/kernel_patches/series/ldiskfs-6.6-ml.series b/ldiskfs/kernel_patches/series/ldiskfs-6.6-ml.series index 3082474..b31263f 100644 --- a/ldiskfs/kernel_patches/series/ldiskfs-6.6-ml.series +++ b/ldiskfs/kernel_patches/series/ldiskfs-6.6-ml.series @@ -35,3 +35,4 @@ rhel8/ext4-old_ea_inodes_handling_fix.patch ubuntu20.04.5/ext4-filename-encode.patch rhel9.1/ext4-enc-flag.patch linux-6.6/ext4-encdata.patch +rhel9.4/ext4-add-IGET_NO_CHECKS-flag.patch diff --git a/ldiskfs/kernel_patches/series/ldiskfs-6.7-ml.series b/ldiskfs/kernel_patches/series/ldiskfs-6.7-ml.series index 8e99c44..dd4911a 100644 --- a/ldiskfs/kernel_patches/series/ldiskfs-6.7-ml.series +++ b/ldiskfs/kernel_patches/series/ldiskfs-6.7-ml.series @@ -35,3 +35,4 @@ rhel8/ext4-old_ea_inodes_handling_fix.patch ubuntu20.04.5/ext4-filename-encode.patch rhel9.1/ext4-enc-flag.patch linux-6.6/ext4-encdata.patch +rhel9.4/ext4-add-IGET_NO_CHECKS-flag.patch diff --git a/lustre/osd-ldiskfs/osd_compat.c b/lustre/osd-ldiskfs/osd_compat.c index 1ed220b..154a717 100644 --- a/lustre/osd-ldiskfs/osd_compat.c +++ b/lustre/osd-ldiskfs/osd_compat.c @@ -448,7 +448,7 @@ int osd_lookup_in_remote_parent(struct osd_thread_info *oti, osd_id_gen(id, le32_to_cpu(de->inode), OSD_OII_NOGEN); brelse(bh); - inode = osd_iget(oti, osd, id); + inode = osd_iget(oti, osd, id, 0); if (IS_ERR(inode)) { rc = PTR_ERR(inode); if (rc == -ESTALE) @@ -704,7 +704,7 @@ static int osd_obj_update_entry(struct osd_thread_info *info, GOTO(out, rc = 1); osd_id_gen(oi_id, le32_to_cpu(de->inode), OSD_OII_NOGEN); - inode = osd_iget(info, osd, oi_id); + inode = osd_iget(info, osd, oi_id, 0); if (IS_ERR(inode)) { rc = PTR_ERR(inode); if (rc == -ENOENT || rc == -ESTALE) @@ -1086,7 +1086,7 @@ int osd_obj_map_lookup(struct osd_thread_info *info, struct osd_device *dev, osd_id_gen(id, le32_to_cpu(de->inode), OSD_OII_NOGEN); brelse(bh); - inode = osd_iget(info, dev, id); + inode = osd_iget(info, dev, id, 0); if (IS_ERR(inode)) { int rc = PTR_ERR(inode); diff --git a/lustre/osd-ldiskfs/osd_handler.c b/lustre/osd-ldiskfs/osd_handler.c index c2f9a7d..1c0cca0 100644 --- a/lustre/osd-ldiskfs/osd_handler.c +++ b/lustre/osd-ldiskfs/osd_handler.c @@ -297,7 +297,7 @@ static void osd_idc_dump_lma(const struct lu_env *env, struct inode *inode; int rc; - inode = osd_ldiskfs_iget(osd_sb(osd), ino); + inode = osd_ldiskfs_iget(osd_sb(osd), ino, 0); if (IS_ERR(inode)) { CERROR("%s: can't get inode %lu: rc = %d\n", osd->od_svname, ino, (int)PTR_ERR(inode)); @@ -485,7 +485,7 @@ int osd_get_lma(struct osd_thread_info *info, struct inode *inode, **/ static struct inode *osd_iget2(struct osd_thread_info *info, struct osd_device *dev, struct osd_inode_id *id, - bool special, int *err) + int flags, int *err) { struct inode *inode = NULL; int rc = 0; @@ -497,7 +497,7 @@ static struct inode *osd_iget2(struct osd_thread_info *info, */ /* LASSERT(current->journal_info == NULL); */ - inode = osd_ldiskfs_iget_special(osd_sb(dev), id->oii_ino, special); + inode = osd_ldiskfs_iget(osd_sb(dev), id->oii_ino, flags); if (IS_ERR(inode)) { CDEBUG(D_INODE, "no inode: ino = %u, rc = %ld\n", id->oii_ino, PTR_ERR(inode)); @@ -549,12 +549,12 @@ static struct inode *osd_iget2(struct osd_thread_info *info, } struct inode *osd_iget(struct osd_thread_info *info, struct osd_device *dev, - struct osd_inode_id *id) + struct osd_inode_id *id, int flags) { struct inode *inode; int rc = 0; - inode = osd_iget2(info, dev, id, 0, &rc); + inode = osd_iget2(info, dev, id, flags, &rc); if (rc) { iput(inode); @@ -618,7 +618,7 @@ osd_iget_fid(struct osd_thread_info *info, struct osd_device *dev, struct inode *inode; int rc; - inode = osd_iget(info, dev, id); + inode = osd_iget(info, dev, id, 0); if (IS_ERR(inode)) return inode; @@ -658,7 +658,8 @@ static struct inode *osd_iget_check(struct osd_thread_info *info, if (unlikely(fid_is_acct(fid))) special = true; again: - inode = osd_iget2(info, dev, id, special, &rc); + inode = osd_iget2(info, dev, id, + special ? LDISKFS_IGET_SPECIAL : 0, &rc); if (rc) { if (!trusted && (rc == -ENOENT || rc == -ESTALE)) goto check_oi; @@ -952,7 +953,7 @@ static int osd_stripe_dir_filldir(void *buf, return 0; osd_id_gen(id, ino, OSD_OII_NOGEN); - inode = osd_iget(oti, dev, id); + inode = osd_iget(oti, dev, id, 0); if (IS_ERR(inode)) return PTR_ERR(inode); @@ -6176,7 +6177,7 @@ again: if (inode != NULL) goto trigger; - inode = osd_iget(oti, dev, id); + inode = osd_iget(oti, dev, id, 0); /* The inode has been removed (by race maybe). */ if (IS_ERR(inode)) { rc = PTR_ERR(inode); @@ -6202,7 +6203,7 @@ again: trigger: if (scrub->os_running) { if (inode == NULL) { - inode = osd_iget(oti, dev, id); + inode = osd_iget(oti, dev, id, 0); /* The inode has been removed (by race maybe). */ if (IS_ERR(inode)) { rc = PTR_ERR(inode); @@ -6258,7 +6259,7 @@ static int osd_fail_fid_lookup(struct osd_thread_info *oti, int rc; osd_id_gen(&oic->oic_lid, ino, OSD_OII_NOGEN); - inode = osd_iget(oti, dev, &oic->oic_lid); + inode = osd_iget(oti, dev, &oic->oic_lid, 0); if (IS_ERR(inode)) { fid_zero(&oic->oic_fid); return PTR_ERR(inode); @@ -7466,7 +7467,7 @@ osd_dirent_check_repair(const struct lu_env *env, struct osd_object *obj, } osd_id_gen(id, ent->oied_ino, OSD_OII_NOGEN); - inode = osd_iget(info, dev, id); + inode = osd_iget(info, dev, id, 0); if (IS_ERR(inode)) { rc = PTR_ERR(inode); if (rc == -ENOENT || rc == -ESTALE) { diff --git a/lustre/osd-ldiskfs/osd_internal.h b/lustre/osd-ldiskfs/osd_internal.h index b4737e2..1dd86545 100644 --- a/lustre/osd-ldiskfs/osd_internal.h +++ b/lustre/osd-ldiskfs/osd_internal.h @@ -809,7 +809,7 @@ int osd_register_proc_index_in_idif(struct osd_device *osd); int osd_statfs(const struct lu_env *env, struct dt_device *dev, struct obd_statfs *sfs, struct obd_statfs_info *info); struct inode *osd_iget(struct osd_thread_info *info, struct osd_device *dev, - struct osd_inode_id *id); + 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); @@ -949,14 +949,15 @@ static inline void i_projid_write(struct inode *inode, __u32 projid) #endif #ifdef HAVE_LDISKFS_IGET_WITH_FLAGS -# define osd_ldiskfs_iget(sb, inum) \ - ldiskfs_iget((sb), (inum), LDISKFS_IGET_HANDLE) -# define osd_ldiskfs_iget_special(sb, inum, special) \ - ldiskfs_iget((sb), (inum), LDISKFS_IGET_HANDLE | \ - ((special) ? LDISKFS_IGET_SPECIAL : 0)) +# define osd_ldiskfs_iget(sb, inum, flags) \ + ldiskfs_iget((sb), (inum), LDISKFS_IGET_HANDLE | flags) #else -# define osd_ldiskfs_iget(sb, inum) ldiskfs_iget((sb), (inum)) -# define osd_ldiskfs_iget_special(sb, inum, special) ldiskfs_iget((sb), (inum)) +# define osd_ldiskfs_iget(sb, inum, flags) ldiskfs_iget((sb), (inum)) +# define LDISKFS_IGET_SPECIAL 0 +#endif + +#ifndef HAVE_LDISKFS_IGET_EA_INODE +# define LDISKFS_IGET_NO_CHECKS 0 #endif #ifdef HAVE_LDISKFS_INFO_JINODE diff --git a/lustre/osd-ldiskfs/osd_oi.c b/lustre/osd-ldiskfs/osd_oi.c index b1bd2f3..fa05cac 100644 --- a/lustre/osd-ldiskfs/osd_oi.c +++ b/lustre/osd-ldiskfs/osd_oi.c @@ -90,7 +90,7 @@ static int osd_oi_index_create_one(struct osd_thread_info *info, if (!IS_ERR(bh)) { osd_id_gen(id, le32_to_cpu(de->inode), OSD_OII_NOGEN); brelse(bh); - inode = osd_iget(info, osd, id); + inode = osd_iget(info, osd, id, 0); if (!IS_ERR(inode)) { iput(inode); inode = ERR_PTR(-EEXIST); @@ -715,7 +715,7 @@ int osd_oi_insert(struct osd_thread_info *info, struct osd_device *osd, return 1; /* Check whether the mapping for oi_id is valid or not. */ - inode = osd_iget(info, osd, oi_id); + inode = osd_iget(info, osd, oi_id, 0); if (IS_ERR(inode)) { rc = PTR_ERR(inode); if (rc == -ENOENT || rc == -ESTALE) diff --git a/lustre/osd-ldiskfs/osd_scrub.c b/lustre/osd-ldiskfs/osd_scrub.c index 559c4d8..446f8c3 100644 --- a/lustre/osd-ldiskfs/osd_scrub.c +++ b/lustre/osd-ldiskfs/osd_scrub.c @@ -311,7 +311,7 @@ osd_scrub_check_update(struct osd_thread_info *info, struct osd_device *dev, sf->sf_items_igif++; /* verify inode */ - inode = osd_iget(info, dev, lid); + inode = osd_iget(info, dev, lid, 0); if (IS_ERR(inode)) { rc = PTR_ERR(inode); /* someone removed the inode. */ @@ -376,7 +376,7 @@ osd_scrub_check_update(struct osd_thread_info *info, struct osd_device *dev, GOTO(skip, rc = 0); /* verify existing mapping */ - inode2 = osd_iget(info, dev, lid2); + inode2 = osd_iget(info, dev, lid2, 0); if (IS_ERR(inode2)) { rc = PTR_ERR(inode2); if (rc == -ENOENT || rc == -ESTALE) @@ -653,7 +653,7 @@ static int osd_iit_iget(struct osd_thread_info *info, struct osd_device *dev, #endif osd_id_gen(lid, pos, OSD_OII_NOGEN); - inode = osd_iget(info, dev, lid); + inode = osd_iget(info, dev, lid, LDISKFS_IGET_NO_CHECKS); if (IS_ERR(inode)) { rc = PTR_ERR(inode); /* The inode may be removed after bitmap searching, or the @@ -3119,7 +3119,7 @@ static int osd_scan_ml_file(const struct lu_env *env, struct osd_device *dev, if (!fid_is_sane(fid)) inode = osd_iget_fid(info, dev, &id, fid); else - inode = osd_iget(info, dev, &id); + inode = osd_iget(info, dev, &id, 0); if (IS_ERR(inode)) RETURN(PTR_ERR(inode)); @@ -3170,7 +3170,7 @@ static int osd_scan_ml_file_dir(const struct lu_env *env, ENTRY; osd_id_gen(&id, oie->oie_dirent->oied_ino, OSD_OII_NOGEN); - inode = osd_iget(info, dev, &id); + inode = osd_iget(info, dev, &id, 0); if (IS_ERR(inode)) RETURN(PTR_ERR(inode)); @@ -3198,7 +3198,7 @@ static int osd_scan_ml_file_seq(const struct lu_env *env, ENTRY; osd_id_gen(&id, oie->oie_dirent->oied_ino, OSD_OII_NOGEN); - inode = osd_iget(info, dev, &id); + inode = osd_iget(info, dev, &id, 0); if (IS_ERR(inode)) RETURN(PTR_ERR(inode)); @@ -3310,7 +3310,7 @@ static int osd_scan_lastid_dir(const struct lu_env *env, struct osd_device *dev, ENTRY; osd_id_gen(&id, oie->oie_dirent->oied_ino, OSD_OII_NOGEN); - inode = osd_iget(info, dev, &id); + inode = osd_iget(info, dev, &id, 0); if (IS_ERR(inode)) RETURN(PTR_ERR(inode)); @@ -3352,7 +3352,7 @@ static int osd_scan_lastid_seq(const struct lu_env *env, struct osd_device *dev, ENTRY; osd_id_gen(&id, oie->oie_dirent->oied_ino, OSD_OII_NOGEN); - inode = osd_iget(info, dev, &id); + inode = osd_iget(info, dev, &id, 0); if (IS_ERR(inode)) RETURN(PTR_ERR(inode)); @@ -3477,7 +3477,7 @@ static int osd_scan_O_seq(const struct lu_env *env, struct osd_device *dev, ENTRY; osd_id_gen(&id, oie->oie_dirent->oied_ino, OSD_OII_NOGEN); - inode = osd_iget(info, dev, &id); + inode = osd_iget(info, dev, &id, 0); if (IS_ERR(inode)) RETURN(PTR_ERR(inode)); -- 1.8.3.1