Whamcloud - gitweb
LU-17557 osd: only accounting inodes are special 91/54091/8
authorAlex Zhuravlev <bzzz@whamcloud.com>
Mon, 19 Feb 2024 08:18:45 +0000 (11:18 +0300)
committerOleg Drokin <green@whamcloud.com>
Tue, 2 Apr 2024 21:02:14 +0000 (21:02 +0000)
don't treat all inodes special (system) because 5.14 turns filesystem
read-only when we try to access an non-existing inode with
LDISKFS_IGET_SPECIAL flag.

Fixes: 2c0b2b7540 ("LU-13166 osd-ldiskfs: fix to allow to get system inode")
Signed-off-by: Alex Zhuravlev <bzzz@whamcloud.com>
Change-Id: I0c05adaf7b94e04c094cb069e8271bf478010b8c
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/54091
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Reviewed-by: Li Dongyang <dongyangli@ddn.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
lustre/osd-ldiskfs/osd_handler.c
lustre/osd-ldiskfs/osd_internal.h
lustre/tests/sanity-lfsck.sh

index 0fef3bd..7ef62b0 100644 (file)
@@ -505,10 +505,10 @@ 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,
-                              int *err)
+                              bool special, int *err)
 {
-       int rc = 0;
        struct inode *inode = NULL;
+       int rc = 0;
 
        /*
         * if we look for an inode withing a running
@@ -517,7 +517,7 @@ static struct inode *osd_iget2(struct osd_thread_info *info,
         */
         /* LASSERT(current->journal_info == NULL); */
 
-       inode = osd_ldiskfs_iget(osd_sb(dev), id->oii_ino);
+       inode = osd_ldiskfs_iget_special(osd_sb(dev), id->oii_ino, special);
        if (IS_ERR(inode)) {
                CDEBUG(D_INODE, "no inode: ino = %u, rc = %ld\n",
                       id->oii_ino, PTR_ERR(inode));
@@ -574,7 +574,7 @@ struct inode *osd_iget(struct osd_thread_info *info, struct osd_device *dev,
        struct inode *inode;
        int rc = 0;
 
-       inode = osd_iget2(info, dev, id, &rc);
+       inode = osd_iget2(info, dev, id, 0, &rc);
 
        if (rc) {
                iput(inode);
@@ -664,6 +664,7 @@ static struct inode *osd_iget_check(struct osd_thread_info *info,
                                    bool trusted)
 {
        struct inode *inode;
+       bool special = false;
        int rc = 0;
 
        ENTRY;
@@ -674,8 +675,10 @@ static struct inode *osd_iget_check(struct osd_thread_info *info,
         * directly without further OI checking.
         */
 
+       if (unlikely(fid_is_acct(fid)))
+               special = true;
 again:
-       inode = osd_iget2(info, dev, id, &rc);
+       inode = osd_iget2(info, dev, id, special, &rc);
        if (rc) {
                if (!trusted && (rc == -ENOENT || rc == -ESTALE))
                        goto check_oi;
index f804243..3cc562a 100644 (file)
@@ -972,11 +972,14 @@ static inline void i_projid_write(struct inode *inode, __u32 projid)
 #endif
 
 #ifdef HAVE_LDISKFS_IGET_WITH_FLAGS
-# define osd_ldiskfs_iget(sb, ino) \
-               ldiskfs_iget((sb), (ino), \
-                            LDISKFS_IGET_HANDLE | LDISKFS_IGET_SPECIAL)
+# 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))
 #else
-# define osd_ldiskfs_iget(sb, ino) ldiskfs_iget((sb), (ino))
+# define osd_ldiskfs_iget(sb, inum) ldiskfs_iget((sb), (inum))
+# define osd_ldiskfs_iget_special(sb, inum, special) ldiskfs_iget((sb), (inum))
 #endif
 
 #ifdef HAVE_LDISKFS_INFO_JINODE
index 3f5f68b..09c3f6f 100755 (executable)
@@ -4870,6 +4870,42 @@ test_29c()
 }
 run_test 29c "verify linkEA size limitation"
 
+test_29d() {
+       (( $MDS1_VERSION > $(version_code 2.6.50) )) ||
+               skip "MDS older than 2.6.50, LU-5517"
+       [[ $mds1_FSTYPE == ldiskfs ]] || skip "ldiskfs only problem"
+
+       echo "#####"
+       echo "The object's nlink attribute is smaller than the object's known"
+       echo "name entries count. The LFSCK will repair the object's nlink"
+       echo "attribute to match the known name entries count"
+       echo "#####"
+
+       check_mount_and_prep
+
+       $LFS mkdir -i 0 $DIR/$tdir/d0 || error "(1) Fail to mkdir d0"
+       touch $DIR/$tdir/d0/foo || error "(2) Fail to create foo"
+
+       echo "Inject failure stub on MDT0 to simulate the case that foo's"
+       echo "nlink attribute is smaller than its name entries count."
+
+       #define OBD_FAIL_LFSCK_LESS_NLINK       0x1626
+       do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1626
+       ln $DIR/$tdir/d0/foo $DIR/$tdir/d0/h1 ||
+               error "(3) Fail to hard link to $DIR/$tdir/d0/foo"
+       do_facet $SINGLEMDS $LCTL set_param fail_loc=0
+       rm $DIR/$tdir/d0/h1 || error "can't remove link"
+
+       cancel_lru_locks mdc
+       # try to access non-existing inode
+       stat $DIR/$tdir/d0/foo
+       touch $DIR/$tdir/d0/foo0 || error "can't create new file"
+       echo "rm_entry"
+       $LFS rm_entry $DIR/$tdir/d0/foo
+       ls -l $DIR/$tdir/d0
+}
+run_test 29d "accessing non-existing inode shouldn't turn fs read-only (ldiskfs)"
+
 test_30() {
        [[ $mds1_FSTYPE == ldiskfs ]] || skip "only ldiskfs has lost+found"
        [ -n "$FILESET" ] && skip "Not functional for FILESET set"