Whamcloud - gitweb
LU-16771 llite: cache statfs data for projects 81/58781/11
authorAlex Zhuravlev <bzzz@whamcloud.com>
Mon, 14 Apr 2025 16:51:35 +0000 (19:51 +0300)
committerOleg Drokin <green@whamcloud.com>
Wed, 21 May 2025 05:17:37 +0000 (05:17 +0000)
use per-fs rhashtable to cache project-related statfs

Test-Parameters: fstype=ldiskfs testlist=sanity
Test-Parameters: fstype=ldiskfs testlist=sanity-quota
Signed-off-by: Alex Zhuravlev <bzzz@whamcloud.com>
Change-Id: I0bcac75afb9ab74535e2c553c575a812116b14d4
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/58781
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Reviewed-by: Sergey Cheremencev <scherementsev@ddn.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
lustre/llite/llite_internal.h
lustre/llite/llite_lib.c

index 5f9febb..6c07c85 100644 (file)
@@ -1031,6 +1031,8 @@ struct ll_sb_info {
 
        /* LU-14535: the list of "lfs quota -a" */
        struct list_head         ll_all_quota_list;
+
+       struct rhashtable        ll_proj_sfs_htable;
 };
 
 #define SBI_DEFAULT_HEAT_DECAY_WEIGHT  ((80 * 256 + 50) / 100)
index 3ef6650..a0119fc 100644 (file)
@@ -60,6 +60,20 @@ struct kmem_cache *ll_file_data_slab;
 #define log2(n) ffz(~(n))
 #endif
 
+struct proj_sfs_cache {
+       unsigned int            psc_id;
+       struct rhash_head       psc_linkage;
+       struct kstatfs          psc_sfs;
+       time64_t                psc_age;
+       struct mutex            psc_mutex;
+};
+
+static const struct rhashtable_params proj_sfs_cache_params = {
+       .key_len        = sizeof(unsigned int),
+       .key_offset     = offsetof(struct proj_sfs_cache, psc_id),
+       .head_offset    = offsetof(struct proj_sfs_cache, psc_linkage),
+};
+
 /*
  * If there is only one number of core visible to Lustre,
  * async readahead will be disabled, to avoid massive over
@@ -218,6 +232,10 @@ static struct ll_sb_info *ll_init_sbi(struct lustre_sb_info *lsi)
        sbi->ll_enable_setstripe_gid = -1;
 
        INIT_LIST_HEAD(&sbi->ll_all_quota_list);
+
+       rc = rhashtable_init(&sbi->ll_proj_sfs_htable, &proj_sfs_cache_params);
+       LASSERT(rc == 0);
+
        RETURN(sbi);
 out_destroy_ra:
        OBD_FREE(sbi->ll_foreign_symlink_prefix, sizeof("/mnt/"));
@@ -233,6 +251,13 @@ out_sbi:
        RETURN(ERR_PTR(rc));
 }
 
+static void proj_sfs_free(void *psa, void *arg)
+{
+       struct proj_sfs_cache *ps = psa;
+
+       OBD_FREE_PTR(ps);
+}
+
 static void ll_free_sbi(struct super_block *sb)
 {
        struct ll_sb_info *sbi = ll_s2sbi(sb);
@@ -240,6 +265,8 @@ static void ll_free_sbi(struct super_block *sb)
        ENTRY;
 
        if (sbi != NULL) {
+               rhashtable_free_and_destroy(&sbi->ll_proj_sfs_htable,
+                                           proj_sfs_free, NULL);
                if (!list_empty(&sbi->ll_squash.rsi_nosquash_nids))
                        cfs_free_nidlist(&sbi->ll_squash.rsi_nosquash_nids);
                if (sbi->ll_ra_info.ll_readahead_wq)
@@ -2621,14 +2648,50 @@ out:
 
 static int ll_statfs_project(struct inode *inode, struct kstatfs *sfs)
 {
+       struct ll_inode_info *lli = ll_i2info(inode);
+       struct ll_sb_info *sbi = ll_s2sbi(inode->i_sb);
        struct if_quotactl qctl = {
                .qc_cmd = LUSTRE_Q_GETQUOTA,
                .qc_type = PRJQUOTA,
                .qc_valid = QC_GENERAL,
        };
+       struct proj_sfs_cache *ps, *orig;
        u64 limit, curblock;
        int ret;
 
+       LASSERT(S_ISDIR(inode->i_mode));
+
+       ps = rhashtable_lookup_fast(&sbi->ll_proj_sfs_htable,
+                                   &lli->lli_projid,
+                                   proj_sfs_cache_params);
+       if (!ps) {
+               OBD_ALLOC_PTR(ps);
+               if (!ps)
+                       return -ENOMEM;
+               ps->psc_id = lli->lli_projid;
+               mutex_init(&ps->psc_mutex);
+               orig = rhashtable_lookup_get_insert_fast(&sbi->ll_proj_sfs_htable,
+                                                       &ps->psc_linkage,
+                                                       proj_sfs_cache_params);
+               if (orig) {
+                       OBD_FREE_PTR(ps);
+                       if (IS_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;
+       }
+
+       mutex_lock(&ps->psc_mutex);
+       if (ktime_get_seconds() - ps->psc_age < sbi->ll_statfs_max_age) {
+               *sfs = ps->psc_sfs;
+               GOTO(out, ret = 0);
+       }
+
        qctl.qc_id = ll_i2info(inode)->lli_projid;
        ret = quotactl_ioctl(inode->i_sb, &qctl);
        if (ret) {
@@ -2637,7 +2700,7 @@ static int ll_statfs_project(struct inode *inode, struct kstatfs *sfs)
                 */
                if (ret == -ESRCH || ret == -EOPNOTSUPP)
                        ret = 0;
-               return ret;
+               GOTO(out, ret);
        }
 
        limit = ((qctl.qc_dqblk.dqb_bsoftlimit ?
@@ -2662,7 +2725,13 @@ static int ll_statfs_project(struct inode *inode, struct kstatfs *sfs)
                        (sfs->f_files - qctl.qc_dqblk.dqb_curinodes) : 0;
        }
 
-       return 0;
+       ps->psc_sfs = *sfs;
+       ps->psc_age = ktime_get_seconds();
+
+out:
+       mutex_unlock(&ps->psc_mutex);
+
+       return ret;
 }
 
 int ll_statfs(struct dentry *de, struct kstatfs *sfs)