From: Andreas Dilger Date: Mon, 23 Jun 2025 19:21:23 +0000 (-0600) Subject: LU-16771 llite: statfs on regular files is OK X-Git-Url: https://git.whamcloud.com/gitweb?a=commitdiff_plain;h=7efafec4bd8944b8d5123b73583989383446fbcd;p=fs%2Flustre-release.git LU-16771 llite: statfs on regular files is OK It shouldn't be considered a bug to statfs() a regular file. There doesn't appear to be anything directory-specific in ll_statfs_project() that would warrant this LASSERT(), and it can be trivially triggered from userspace. Fixes: 2354f2f040 ("LU-16771 llite: cache statfs data for projects") Signed-off-by: Andreas Dilger Change-Id: I3cf6b123e7ff40d233b4bb247935835a582b4a8f Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/59898 Reviewed-by: Timothy Day Reviewed-by: Alex Zhuravlev Reviewed-by: Li Dongyang Reviewed-by: Oleg Drokin Tested-by: jenkins Tested-by: Maloo --- diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 5771bfd..092d42b 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -2659,7 +2659,7 @@ static int ll_statfs_project(struct inode *inode, struct kstatfs *sfs) u64 limit, curblock; int ret; - LASSERT(S_ISDIR(inode->i_mode)); + ENTRY; ps = rhashtable_lookup_fast(&sbi->ll_proj_sfs_htable, &lli->lli_projid, @@ -2667,7 +2667,7 @@ static int ll_statfs_project(struct inode *inode, struct kstatfs *sfs) if (!ps) { OBD_ALLOC_PTR(ps); if (!ps) - return -ENOMEM; + RETURN(-ENOMEM); ps->psc_id = lli->lli_projid; mutex_init(&ps->psc_mutex); orig = rhashtable_lookup_get_insert_fast(&sbi->ll_proj_sfs_htable, @@ -2676,14 +2676,14 @@ static int ll_statfs_project(struct inode *inode, struct kstatfs *sfs) if (orig) { OBD_FREE_PTR(ps); if (IS_ERR(orig)) - return PTR_ERR(orig); + RETURN(PTR_ERR(orig)); ps = orig; } } if (ktime_get_seconds() - ps->psc_age < sbi->ll_statfs_max_age) { *sfs = ps->psc_sfs; - return 0; + RETURN(0); } mutex_lock(&ps->psc_mutex); @@ -2731,7 +2731,7 @@ static int ll_statfs_project(struct inode *inode, struct kstatfs *sfs) out: mutex_unlock(&ps->psc_mutex); - return ret; + RETURN(ret); } int ll_statfs(struct dentry *de, struct kstatfs *sfs) @@ -2743,7 +2743,8 @@ int ll_statfs(struct dentry *de, struct kstatfs *sfs) ktime_t kstart = ktime_get(); int rc; - CDEBUG(D_VFSTRACE, "VFS Op:sb=%s (%p)\n", sb->s_id, sb); + CDEBUG(D_VFSTRACE, "VFS Op:sb=%s (%p) "DNAME" proj=%u\n", sb->s_id, sb, + encode_fn_dentry(de), ll_i2info(de->d_inode)->lli_projid); /* Some amount of caching on the client is allowed */ rc = ll_statfs_internal(sbi, &osfs, OBD_STATFS_SUM); diff --git a/lustre/tests/sanity-quota.sh b/lustre/tests/sanity-quota.sh index 498d651..4a59233 100755 --- a/lustre/tests/sanity-quota.sh +++ b/lustre/tests/sanity-quota.sh @@ -3921,6 +3921,7 @@ test_41() { skip "Project quota is not supported" setup_quota_test || error "setup quota failed with $?" local dir="$DIR/$tdir/dir" + local file="$dir/$tfile" local blimit=102400 local ilimit=4096 local projid=$((testnum * 1000)) @@ -3939,6 +3940,10 @@ test_41() { test_mkdir -p $dir && change_project -sp $projid $dir $LFS setquota -p $projid -b 0 -B ${blimit}K -i 0 -I $ilimit $dir || error "set project quota failed" + touch $file || error "touch $file failed" + $LFS project $file + local file_proj=($($LFS project $file)) + [[ ${file_proj[0]} == $projid ]] || error "project not set on $file" sync; sync_all_data sleep_maxage @@ -3953,9 +3958,8 @@ test_41() { local iused=$(getquota -p $projid global curinodes) local expected="$ilimit$iused" - wait_update $HOSTNAME \ - "df -iP $dir | awk \\\"/$FSNAME/\\\"'{print \\\$2 \\\$3}'" \ - "$expected" || + wait_update $HOSTNAME "df -iP $dir | + awk \\\"/$FSNAME/\\\"'{print \\\$2 \\\$3}'" "$expected" || error "failed to get correct statfs for project quota" expected=$(df -kP $dir | awk "/$FSNAME/"' {print $2}') @@ -3967,16 +3971,26 @@ test_41() { expected=$(df -kP $dir | awk "/$FSNAME/"' {print $3}') (( expected - bused < 4)) || error "bused mismatch: $expected != $bused" + # check if df output on regular file works as expected + echo "== project statfs on file (prjid=$projid): $file ==" + df -kP $file; df -iP $file; $LFS quota -p $projid $dir + local bused=$(getquota -p $projid global curspace) + local iused=$(getquota -p $projid global curinodes) + local expected="$ilimit$iused" + + wait_update $HOSTNAME "df -iP $dir | + awk \\\"/$FSNAME/\\\"'{print \\\$2 \\\$3}'" "$expected" || + error "failed to get correct statfs for project quota" + # disable statfs_project and check again $LCTL set_param llite.*.statfs_project=0 expected=$({ df -kP $MOUNT; df -iP $MOUNT; } | \ awk '/'$FSNAME'/ { printf "%d %d ", $2,$3 }') - wait_update $HOSTNAME \ - "{ df -kP $dir; df -iP $dir; } | - awk '/$FSNAME/ { printf \\\"%d %d \\\", \\\$2,\\\$3 }'" \ - "$expected" || + wait_update $HOSTNAME "{ df -kP $dir; df -iP $dir; } | + awk '/$FSNAME/ { printf \\\"%d %d \\\", \\\$2,\\\$3 }'" \ + "$expected" || error "failed to get correct statfs when statfs_project=0" } run_test 41 "df should return projid-specific values"