Whamcloud - gitweb
LU-18453 quota: show default quota in lfs quota -a 53/57053/7
authorHongchao Zhang <hongchao@whamcloud.com>
Sun, 24 Nov 2024 10:01:46 +0000 (18:01 +0800)
committerOleg Drokin <green@whamcloud.com>
Sat, 18 Jan 2025 22:04:29 +0000 (22:04 +0000)
When getting all quota info by "lfs quota -a", the default quota
should also be printed if some specific quota ID is using it.

Signed-off-by: Hongchao Zhang <hongchao@whamcloud.com>
Change-Id: Ib6cb42fe6ec62df0c2239c7098eabaf012f02b2e
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/57053
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Sergey Cheremencev <scherementsev@ddn.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/osd-zfs/osd_quota.c
lustre/quota/lquota_internal.h
lustre/quota/lquota_lib.c
lustre/quota/qmt_handler.c
lustre/tests/sanity-quota.sh

index 4363565..c9e4645 100644 (file)
@@ -289,6 +289,7 @@ static int osd_zap_cursor_retrieve_value(const struct lu_env *env,
        zap_attribute_t *za = &osd_oti_get(env)->oti_za;
        zap_cursor_t *zc = it->oiq_zc;
        struct osd_device *osd = osd_obj2dev(it->oiq_obj);
+       uint64_t acct_obj;
        int rc, actual_size;
 
        rc = -zap_cursor_retrieve(zc, za);
@@ -308,9 +309,15 @@ static int osd_zap_cursor_retrieve_value(const struct lu_env *env,
        }
 
        /* use correct special ID to request bytes used */
-       rc = osd_zap_lookup(osd, fid_oid(fid) == ACCT_GROUP_OID ?
-                           DMU_GROUPUSED_OBJECT : DMU_USERUSED_OBJECT, NULL,
-                           za->za_name, za->za_integer_length, buf_size, buf);
+       if (fid_oid(fid) == ACCT_USER_OID)
+               acct_obj = DMU_USERUSED_OBJECT;
+       else if (fid_oid(fid) == ACCT_GROUP_OID)
+               acct_obj = DMU_GROUPUSED_OBJECT;
+       else
+               acct_obj = DMU_PROJECTUSED_OBJECT;
+
+       rc = osd_zap_lookup(osd, acct_obj, NULL, za->za_name,
+                           za->za_integer_length, buf_size, buf);
        if (likely(rc == 0))
                *bytes_read = actual_size;
 
index efde391..c0ea3e5 100644 (file)
@@ -431,8 +431,9 @@ int lquota_extract_fid(const struct lu_fid *, enum lquota_res_type *,
                       enum lquota_type *);
 const struct dt_index_features *glb_idx_feature(struct lu_fid *);
 int lquota_obj_iter(const struct lu_env *env, struct dt_device *dev,
-                   struct dt_object *obj, struct obd_quotactl *oqctl,
-                   char *buffer, int size, bool is_glb, bool is_md);
+                   struct dt_object *obj, struct lquota_entry *lqe_def,
+                   struct obd_quotactl *oqctl, char *buffer, int size,
+                   bool is_glb, bool is_md);
 
 /* lquota_entry.c */
 /* site create/destroy */
index b6096e6..80544d4 100644 (file)
@@ -162,8 +162,9 @@ static struct dt_object *quota_obj_lookup(const struct lu_env *env,
  * \param is_md          - true to iterate LQUOTA_MD quota settings
  */
 int lquota_obj_iter(const struct lu_env *env, struct dt_device *dev,
-                   struct dt_object *obj, struct obd_quotactl *oqctl,
-                   char *buf, int size, bool is_glb, bool is_md)
+                   struct dt_object *obj, struct lquota_entry *lqe_def,
+                   struct obd_quotactl *oqctl, char *buf, int size,
+                   bool is_glb, bool is_md)
 {
        struct lquota_thread_info *qti = lquota_info(env);
        const struct dt_it_ops *iops;
@@ -262,6 +263,20 @@ get_setting:
                memcpy(buf + cur, key, sizeof(__u64));
                cur += sizeof(__u64);
 
+               if (is_glb && lqe_def != NULL) {
+                       struct lquota_glb_rec *glb_rec;
+
+                       glb_rec = (struct lquota_glb_rec *)rec;
+
+                       if (glb_rec->qbr_hardlimit == 0 &&
+                           glb_rec->qbr_softlimit == 0 &&
+                           (LQUOTA_FLAG(glb_rec->qbr_time) &
+                                               LQUOTA_FLAG_DEFAULT)) {
+                               glb_rec->qbr_softlimit = lqe_def->lqe_softlimit;
+                               glb_rec->qbr_hardlimit = lqe_def->lqe_hardlimit;
+                       }
+               }
+
                memcpy(buf + cur, rec, rec_size);
                cur += rec_size;
 
@@ -350,11 +365,11 @@ int lquotactl_slv(const struct lu_env *env, struct dt_device *dev,
 
        if (oqctl->qc_cmd == LUSTRE_Q_ITEROQUOTA) {
                if (lu_device_is_md(dev->dd_lu_dev.ld_site->ls_top_dev))
-                       rc = lquota_obj_iter(env, dev, obj, oqctl, buffer, size,
-                                        false, true);
+                       rc = lquota_obj_iter(env, dev, obj, NULL, oqctl, buffer,
+                                            size, false, true);
                else
-                       rc = lquota_obj_iter(env, dev, obj, oqctl, buffer, size,
-                                        false, false);
+                       rc = lquota_obj_iter(env, dev, obj, NULL, oqctl, buffer,
+                                            size, false, false);
 
                GOTO(out, rc);
        }
index ed1b74f..6918f65 100644 (file)
@@ -541,6 +541,7 @@ static int qmt_quotactl(const struct lu_env *env, struct lu_device *ld,
        struct obd_dqblk *dqb = &oqctl->qc_dqblk;
        struct qmt_pool_info *pool;
        char *poolname;
+       int qtype = oqctl->qc_type;
        int rc = 0;
        bool is_default = false;
        bool is_first_iter = false;
@@ -614,9 +615,10 @@ static int qmt_quotactl(const struct lu_env *env, struct lu_device *ld,
                        if (IS_ERR(pool))
                                RETURN(PTR_ERR(pool));
 
-                       glb_obj = pool->qpi_glb_obj[oqctl->qc_type];
+                       glb_obj = pool->qpi_glb_obj[qtype];
                        rc = lquota_obj_iter(env, lu2dt_dev(ld), glb_obj,
-                                        oqctl, buffer, size / 2, true, true);
+                                            pool->qpi_grace_lqe[qtype], oqctl,
+                                            buffer, size / 2, true, true);
 
                        qpi_putref(env, pool);
 
@@ -634,10 +636,11 @@ static int qmt_quotactl(const struct lu_env *env, struct lu_device *ld,
                        if (IS_ERR(pool))
                                RETURN(PTR_ERR(pool));
 
-                       glb_obj = pool->qpi_glb_obj[oqctl->qc_type];
+                       glb_obj = pool->qpi_glb_obj[qtype];
                        rc = lquota_obj_iter(env, lu2dt_dev(ld), glb_obj,
-                                        oqctl, buffer + size / 2, size / 2,
-                                        true, false);
+                                            pool->qpi_grace_lqe[qtype], oqctl,
+                                            buffer + size / 2, size / 2,
+                                            true, false);
                        qpi_putref(env, pool);
 
                        if (rc < 0 && rc != -ENOENT)
index 2548d02..d4078fe 100755 (executable)
@@ -6428,6 +6428,129 @@ test_86()
 }
 run_test 86 "Pre-acquired quota should be released if quota is over limit"
 
+test_87()
+{
+       (( $MDS1_VERSION >= $(version_code 2.16.50) )) ||
+               skip "need MDS >= 2.16.50 to add default value in lfs quota -a"
+
+       local blimit=102400
+       local ilimit=10240
+       local d_blimit=409600
+       local d_ilimit=40960
+       local u_blimits
+       local u_ilimits
+       local g_blimits
+       local g_ilimits
+       local p_blimits
+       local p_ilimits
+
+       setup_quota_test || error "setup quota failed with $?"
+
+       echo "test user quota for 'lfs quota -a' to print default quota"
+       $LFS setquota -U -b $d_blimit -B $d_blimit $MOUNT ||
+               error "failed to set USR default block quota setting"
+       $LFS setquota -U -i $d_ilimit -I $d_ilimit $MOUNT ||
+               error "failed to set USR default file quota setting"
+       $LFS setquota -G -b $d_blimit -B $d_blimit $MOUNT ||
+               error "failed to set GRP default block quota setting"
+       $LFS setquota -G -i $d_ilimit -I $d_ilimit $MOUNT ||
+               error "failed to set GRP default file quota setting"
+
+       is_project_quota_supported && {
+               $LFS setquota -P -b $d_blimit -B $d_blimit $MOUNT ||
+                       error "failed to set PRJ default block quota setting"
+               $LFS setquota -P -i $d_ilimit -I $d_ilimit $MOUNT ||
+                       error "failed to set PRJ default file quota setting"
+       }
+
+       #define OBD_FAIL_QUOTA_NOSYNC           0xA09
+       do_facet mds1 $LCTL set_param fail_loc=0xa09
+
+       for ((i = 100; i < 150; i++)); do
+               $LFS setquota -u $i -b $blimit -B $blimit $MOUNT ||
+                       error "failed to set USR $i block quota setting"
+               $LFS setquota -u $i -i $ilimit -I $ilimit $MOUNT ||
+                       error "failed to set USR $i file quota setting"
+
+               $LFS setquota -g $i -b $blimit -B $blimit $MOUNT ||
+                       error "failed to set GRP $i block quota setting"
+               $LFS setquota -g $i -i $ilimit -I $ilimit $MOUNT ||
+                       error "failed to set GRP $i file quota setting"
+
+               is_project_quota_supported && {
+                       $LFS setquota -p $i -b $blimit -B $blimit $MOUNT ||
+                               error "failed to set PRJ $i block quota setting"
+                       $LFS setquota -p $i -i $ilimit -I $ilimit $MOUNT ||
+                               error "failed to set PRJ $i file quota setting"
+               }
+       done
+
+       for ((i = 150; i < 200; i++)); do
+               $LFS setquota -u $i -D $MOUNT ||
+                       error "failed to set USR $i to use default quota"
+               $LFS setquota -g $i -D $MOUNT ||
+                       error "failed to set GRP $i to use default quota"
+               is_project_quota_supported && {
+                       $LFS setquota -p $i -D $MOUNT ||
+                       error "failed to set PRJ $i to use default quota"
+               }
+       done
+
+       do_facet mds1 $LCTL set_param fail_loc=0
+       sync; sync_all_data || true
+       sleep 5
+
+       eval $($LFS quota -q -a -s 100 -e 199 -u $MOUNT |
+           awk '{printf("u_blimits[%d]=%d;u_ilimits[%d]=%d;", \
+               NR, $5, NR, $9)}')
+       eval $($LFS quota -q -a -s 100 -e 199 -g $MOUNT |
+           awk '{printf("g_blimits[%d]=%d;g_ilimits[%d]=%d;", \
+                NR, $5, NR, $9)}')
+       is_project_quota_supported &&
+               eval $($LFS quota -q -a -s 100 -e 199 -p $MOUNT |
+                   awk '{printf("p_blimits[%d]=%d;p_ilimits[%d]=%d;", \
+                               NR, $5, NR, $9)}')
+
+       for i in $(seq 50); do
+               [ ${u_ilimits[$i]} -eq $ilimit ] ||
+               error "file limit for USR ID $((100 + i - 1)) is wrong"
+               [ ${u_blimits[$i]} -eq $blimit ] ||
+               error "block limit for USR ID $((100 + i - 1)) is wrong"
+
+               [ ${g_ilimits[$i]} -eq $ilimit ] ||
+               error "file limit for GRP ID $((100 + i - 1)) is wrong"
+               [ ${g_blimits[$i]} -eq $blimit ] ||
+               error "block limit for GRP ID $((100 + i - 1)) is wrong"
+
+               is_project_quota_supported && {
+                       [ ${p_ilimits[$i]} -eq $ilimit ] ||
+                       error "file limit for PRJ ID $((100 + i - 1)) is wrong"
+                       [ ${p_blimits[$i]} -eq $blimit ] ||
+                       error "block limit for PRJ ID $((100 + i - 1)) is wrong"
+               }
+       done
+
+       for i in $(seq 50); do
+               [ ${u_ilimits[$((i + 50))]} -eq $d_ilimit ] ||
+               error "file limit for USR ID $((150 + i - 1)) is wrong"
+               [ ${u_blimits[$((i + 50))]} -eq $d_blimit ] ||
+               error "block limit for USR ID $((150 + i - 1)) is wrong"
+
+               [ ${g_ilimits[$((i + 50))]} -eq $d_ilimit ] ||
+               error "file limit for GRP ID $((150 + i - 1)) is wrong"
+               [ ${g_blimits[$((i + 50))]} -eq $d_blimit ] ||
+               error "block limit for GRP ID $((150 + i - 1)) is wrong"
+
+               is_project_quota_supported && {
+                       [ ${p_ilimits[$((i + 50))]} -eq $d_ilimit ] ||
+                       error "file limit for PRJ ID $((150 + i - 1)) is wrong"
+                       [ ${p_blimits[$((i + 50))]} -eq $d_blimit ] ||
+                       error "block limit for PRJ ID $((150 + i - 1)) is wrong"
+               }
+       done
+}
+run_test 87 "lfs quota -a should print default quota setting"
+
 check_quota_no_mount()
 {
        local opts="$1"