Whamcloud - gitweb
LU-18195 osd-ldiskfs: use IGET_NO_CHECKS for objects under lost+found 76/56276/3
authorLi Dongyang <dongyangli@ddn.com>
Fri, 6 Sep 2024 11:20:24 +0000 (21:20 +1000)
committerOleg Drokin <green@whamcloud.com>
Mon, 16 Sep 2024 15:11:55 +0000 (15:11 +0000)
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 <dongyangli@ddn.com>
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/56276
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Alex Zhuravlev <bzzz@whamcloud.com>
Reviewed-by: Li Xi <lixi@ddn.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
ldiskfs/kernel_patches/patches/rhel9.4/ext4-add-IGET_NO_CHECKS-flag.patch
lustre/osd-ldiskfs/osd_handler.c
lustre/osd-ldiskfs/osd_internal.h
lustre/osd-ldiskfs/osd_scrub.c

index a384290..56ca2bb 100644 (file)
@@ -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";
index 5ec20fc..4892f1b 100644 (file)
@@ -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;
 
index 1dd8654..09ebcef 100644 (file)
@@ -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,
index 446f8c3..12609ab 100644 (file)
@@ -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);