From 333c7518f18fad80fe504766ae9645f2ede0108c Mon Sep 17 00:00:00 2001 From: Alex Zhuravlev Date: Mon, 19 Feb 2024 11:18:45 +0300 Subject: [PATCH] LU-17557 osd: only accounting inodes are special 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 Change-Id: I0c05adaf7b94e04c094cb069e8271bf478010b8c Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/54091 Reviewed-by: Oleg Drokin Reviewed-by: Li Dongyang Reviewed-by: Andreas Dilger Tested-by: jenkins Tested-by: Maloo --- lustre/osd-ldiskfs/osd_handler.c | 13 ++++++++----- lustre/osd-ldiskfs/osd_internal.h | 11 +++++++---- lustre/tests/sanity-lfsck.sh | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/lustre/osd-ldiskfs/osd_handler.c b/lustre/osd-ldiskfs/osd_handler.c index 0fef3bd..7ef62b0 100644 --- a/lustre/osd-ldiskfs/osd_handler.c +++ b/lustre/osd-ldiskfs/osd_handler.c @@ -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; diff --git a/lustre/osd-ldiskfs/osd_internal.h b/lustre/osd-ldiskfs/osd_internal.h index f804243..3cc562a 100644 --- a/lustre/osd-ldiskfs/osd_internal.h +++ b/lustre/osd-ldiskfs/osd_internal.h @@ -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 diff --git a/lustre/tests/sanity-lfsck.sh b/lustre/tests/sanity-lfsck.sh index 3f5f68b..09c3f6f 100755 --- a/lustre/tests/sanity-lfsck.sh +++ b/lustre/tests/sanity-lfsck.sh @@ -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" -- 1.8.3.1