From: coreytesdahl Date: Wed, 4 Dec 2024 22:37:06 +0000 (-0600) Subject: LU-18791 lmv: report an overflowed nlink correctly X-Git-Tag: 2.16.54~69 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=b968372d746012a868c742d75ac8062cc361a07a;p=fs%2Flustre-release.git LU-18791 lmv: report an overflowed nlink correctly inode nlink count should be set to 1 if any component stripe in stripped dir has overflowed and been set to 1 HPE-bug-id: LUS-12747 Signed-off-by: Corey Tesdahl Change-Id: I2a3b6f5bd846d11d768ee1979b7f11f0e7cf1c88 Signed-off-by: Alexander Zarochentsev Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/58357 Reviewed-by: Andrew Perepechko Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Tested-by: jenkins Tested-by: Maloo --- diff --git a/lustre/lmv/lmv_obd.c b/lustre/lmv/lmv_obd.c index 9b7d205..2d34110 100644 --- a/lustre/lmv/lmv_obd.c +++ b/lustre/lmv/lmv_obd.c @@ -4215,6 +4215,7 @@ static int lmv_merge_attr(struct obd_export *exp, const struct lmv_stripe_md *lsm = &lso->lso_lsm; int rc; int i; + int nlink_overflow = 0; if (!lmv_dir_striped(lso)) return 0; @@ -4237,11 +4238,12 @@ static int lmv_merge_attr(struct obd_export *exp, (s64)inode_get_ctime_sec(inode), (s64)inode_get_mtime_sec(inode)); - /* for slave stripe, it needs to subtract nlink for . and .. */ - if (i != 0) - attr->cat_nlink += inode->i_nlink - 2; - else - attr->cat_nlink = inode->i_nlink; + /* nlink==1 is a special value meaning nlink overflow + * for directories on Ldiskfs. + */ + nlink_overflow |= (inode->i_nlink == 1); + /* not counting . and .. for each stripe */ + attr->cat_nlink += inode->i_nlink - 2; attr->cat_size += i_size_read(inode); attr->cat_blocks += inode->i_blocks; @@ -4255,6 +4257,14 @@ static int lmv_merge_attr(struct obd_export *exp, if (attr->cat_mtime < inode_get_mtime_sec(inode)) attr->cat_mtime = inode_get_mtime_sec(inode); } + if (nlink_overflow) + /* Indicate that nlink is not correct for a striped dir the + * same way it is done in Ldiskfs by setting nlink = 1. + */ + attr->cat_nlink = 1; + else + /* add 2 for . and .. */ + attr->cat_nlink += 2; return 0; } diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 9e21ed2..a6484aa 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -6247,7 +6247,7 @@ test_51b() { # create files createmany -d $dir/d $nrdirs || { - unlinkmany $dir/d $nrdirs + unlinkmany -d $dir/d $nrdirs error "failed to create $nrdirs subdirs in MDT$mdtidx:$dir" } @@ -6284,6 +6284,39 @@ test_51b() { } run_test 51b "exceed 64k subdirectory nlink limit on create, verify unlink" +test_51c() { + (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs" + local dir=$DIR/$tdir-c2 + local nrdirs=$((65536 * 2 + 2000)) + local mdtidx + + trap cleanup_print_lfs_df EXIT + + $LFS mkdir -c 2 -H fnv_1a_64 $dir + while read mtdidx rest; do + local mdtname=$FSNAME-MDT$(printf "%04x" $mdtidx) + local numfree=$(lctl get_param -n mdc.$mdtname*.filesfree) + local blkfree=$(lctl get_param -n mdc.$mdtname*.kbytesavail) + + (( numfree < nrdirs / 2 || blkfree / $(fs_inode_ksize) < nrdirs / 2 )) && + skip "not enough inodes or blocks for mdt$mdtidx" + done < <( $LFS getdirstripe $dir | awk '{ if ($2 ~ /\[0x.*:0x.*:0x.*\]/) { print $1; } }' ) + + createmany -d $dir/d $nrdirs || + error "failed to create $nrdirs subdirs in $dir" + # nlink for the striped dir should be either 1 + # (ldiskfs, nlink is overflowed at least in one stripe) + # or $ndirs + 2 + local nlinks=$(stat -c %h $dir) + (( nlinks == 1 || nlinks == nrdirs + 2 )) || + error "Wrong nlink count of $nlinks" + + unlinkmany -d $dir/d $nrdirs || error "Removal of the subdirs failed" + rmdir $dir || error "rmdir failed" + cleanup_print_lfs_df +} +run_test 51c "exceed 64k subdirectory count per dir stripe, verify nlink count" + test_51d_sub() { local stripecount=$1 local nfiles=$2