Whamcloud - gitweb
LU-13971 quota: report Pool Quotas for a user 75/39975/12
authorSergey Cheremencev <sergey.cheremencev@hpe.com>
Fri, 18 Sep 2020 13:24:10 +0000 (16:24 +0300)
committerOleg Drokin <green@whamcloud.com>
Mon, 14 Jun 2021 16:43:39 +0000 (16:43 +0000)
Patch adds ability to show quota limits and usage
from all pools per user. Since this patch
long option --pool without argument results
in printing Pool Quotas for all known pools:
lfs quota -u quota_usr --pool /mnt/testfs
Pools from lustre:
Quotas for pool: qpool1
Disk quotas for usr quota_usr (uid 60000):
     Filesystem  kbytes   quota   limit   grace   files   quota   limit   grace
    /mnt/lustre       0       0   10240       -       0       0       0       -
Quotas for pool: qpool2
Disk quotas for usr quota_usr (uid 60000):
     Filesystem  kbytes   quota   limit   grace   files   quota   limit   grace
    /mnt/lustre       0       0   20480       -       0       0       0       -

To get information for specific pool you still
need to set pool name after --pool:
lfs quota -u quota_usr --pool flash /mnt/testfs

Patch also adds sanity-quota_74 to check new
feature.

Test-Parameters: trivial testlist=sanity-quota
HPE-bug-id: LUS-8720
Change-Id: Ib918eef84c2352946ce13342471f36e2b500df32
Signed-off-by: Sergey Cheremencev <sergey.cheremencev@hpe.com>
Reviewed-on: https://review.whamcloud.com/39975
Reviewed-by: Petros Koutoupis <petros.koutoupis@hpe.com>
Tested-by: jenkins <devops@whamcloud.com>
Reviewed-by: Wang Shilong <wshilong@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/lustre/lustreapi.h
lustre/tests/sanity-quota.sh
lustre/utils/lfs.c
lustre/utils/liblustreapi.c

index abd42bd..0e00c23 100644 (file)
@@ -166,6 +166,8 @@ int llapi_file_open_pool(const char *name, int flags, int mode,
                         unsigned long long stripe_size, int stripe_offset,
                         int stripe_count, int stripe_pattern, char *pool_name);
 int llapi_poollist(const char *name);
                         unsigned long long stripe_size, int stripe_offset,
                         int stripe_count, int stripe_pattern, char *pool_name);
 int llapi_poollist(const char *name);
+int llapi_get_poolbuf(const char *name, char **buf,
+                     char ***poolist, int *poolcount);
 int llapi_get_poollist(const char *name, char **poollist, int list_size,
                       char *buffer, int buffer_size);
 int llapi_get_poolmembers(const char *poolname, char **members, int list_size,
 int llapi_get_poollist(const char *name, char **poollist, int list_size,
                       char *buffer, int buffer_size);
 int llapi_get_poolmembers(const char *poolname, char **members, int list_size,
index 89552fd..3d24f75 100755 (executable)
@@ -4862,6 +4862,61 @@ test_73()
 }
 run_test 73 "default limits at OST Pool Quotas"
 
 }
 run_test 73 "default limits at OST Pool Quotas"
 
+test_74()
+{
+       local global_limit=200 # 200M
+       local limit=10 # 10M
+       local limit2=50 # 50M
+       local qpool="qpool1"
+       local qpool2="qpool2"
+       local tmp=0
+
+       mds_supports_qp
+       setup_quota_test || error "setup quota failed with $?"
+       stack_trap cleanup_quota_test EXIT
+
+       # enable ost quota
+       set_ost_qtype $QTYPE || error "enable ost quota failed"
+
+       $LFS setquota -u $TSTUSR -b 0 -B ${global_limit}M -i 0 -I 0 $DIR ||
+               error "set user quota failed"
+
+       pool_add $qpool || error "pool_add failed"
+       pool_add_targets $qpool 0 1 ||
+               error "pool_add_targets failed"
+
+       $LFS setquota -u $TSTUSR -B ${limit}M --pool $qpool $DIR ||
+               error "set user quota failed"
+
+       pool_add $qpool2 || error "pool_add failed"
+       pool_add_targets $qpool2 1 1 ||
+               error "pool_add_targets failed"
+
+       $LFS setquota -u $TSTUSR -B ${limit2}M --pool $qpool2 $DIR ||
+               error "set user quota failed"
+
+       tmp=$(getquota -u $TSTUSR global bhardlimit)
+       [ $tmp -eq $((global_limit * 1024)) ] ||
+               error "wrong global limit $global_limit"
+
+       tmp=$(getquota -u $TSTUSR global bhardlimit $qpool)
+       [ $tmp -eq $((limit * 1024)) ] || error "wrong limit $tmp for $qpool"
+
+       tmp=$(getquota -u $TSTUSR global bhardlimit $qpool2)
+       [ $tmp -eq $((limit2 * 1024)) ] || error "wrong limit $tmp for $qpool2"
+
+       # check limits in pools
+       tmp=$($LFS quota -u $TSTUSR --pool $DIR | \
+             grep -A4 $qpool | awk 'NR == 4{print $4}')
+       echo "pool limit for $qpool $tmp"
+       [ $tmp -eq $((limit * 1024)) ] || error "wrong limit:tmp for $qpool"
+       tmp=$($LFS quota -u $TSTUSR --pool $DIR | \
+             grep -A4 $qpool2 | awk 'NR == 4{print $4}')
+       echo "pool limit for $qpool2 $tmp"
+       [ $tmp -eq $((limit2 * 1024)) ] || error "wrong limit:$tmp for $qpool2"
+}
+run_test 74 "check quota pools per user"
+
 quota_fini()
 {
        do_nodes $(comma_list $(nodes_list)) \
 quota_fini()
 {
        do_nodes $(comma_list $(nodes_list)) \
index 3216a09..b32c6d1 100644 (file)
@@ -8449,9 +8449,13 @@ static int lfs_quota(int argc, char **argv)
        bool human_readable = false;
        bool show_default = false;
        int qtype;
        bool human_readable = false;
        bool show_default = false;
        int qtype;
+       bool show_pools = false;
        struct option long_opts[] = {
        struct option long_opts[] = {
-       { .val = LFS_POOL_OPT, .name = "pool", .has_arg = required_argument },
+       { .val = LFS_POOL_OPT, .name = "pool", .has_arg = optional_argument },
        { .name = NULL } };
        { .name = NULL } };
+       char **poollist = NULL;
+       char *buf = NULL;
+       int poolcount, i;
 
        qctl = calloc(1, sizeof(*qctl) + LOV_MAXPOOLNAME + 1);
        if (!qctl)
 
        qctl = calloc(1, sizeof(*qctl) + LOV_MAXPOOLNAME + 1);
        if (!qctl)
@@ -8527,14 +8531,26 @@ quota_type:
                        human_readable = true;
                        break;
                case LFS_POOL_OPT:
                        human_readable = true;
                        break;
                case LFS_POOL_OPT:
-                       if (lfs_verify_poolarg(optarg)) {
-                               rc = -1;
-                               goto out;
+                       if ((!optarg) && (argv[optind] != NULL) &&
+                               (argv[optind][0] != '-') &&
+                               (argv[optind][0] != '/')) {
+                               optarg = argv[optind++];
+                               if (lfs_verify_poolarg(optarg)) {
+                                       rc = -EINVAL;
+                                       goto out;
+                               }
+                               strncpy(qctl->qc_poolname, optarg,
+                                       LOV_MAXPOOLNAME);
+                               if (qctl->qc_cmd == LUSTRE_Q_GETINFO)
+                                       qctl->qc_cmd = LUSTRE_Q_GETINFOPOOL;
+                               else
+                                       qctl->qc_cmd = LUSTRE_Q_GETQUOTAPOOL;
+                               break;
                        }
                        }
-                       strncpy(qctl->qc_poolname, optarg, LOV_MAXPOOLNAME);
-                       qctl->qc_cmd = qctl->qc_cmd == LUSTRE_Q_GETINFO ?
-                                               LUSTRE_Q_GETINFOPOOL :
-                                               LUSTRE_Q_GETQUOTAPOOL;
+
+                       /* optarg is NULL */
+                       show_pools = true;
+                       qctl->qc_cmd = LUSTRE_Q_GETQUOTAPOOL;
                        break;
                default:
                        fprintf(stderr, "%s quota: unrecognized option '%s'\n",
                        break;
                default:
                        fprintf(stderr, "%s quota: unrecognized option '%s'\n",
@@ -8626,9 +8642,37 @@ quota_type:
        }
 
        mnt = argv[optind];
        }
 
        mnt = argv[optind];
+       if (show_pools) {
+               char *p;
+
+               i = 0;
+               rc = llapi_get_poolbuf(mnt, &buf, &poollist, &poolcount);
+               if (rc)
+                       goto out;
+
+               for (i = 0; i < poolcount; i++) {
+                       p = memchr(poollist[i], '.', MAXNAMLEN);
+                       if (!p) {
+                               fprintf(stderr, "bad string format %.*s\n",
+                                       MAXNAMLEN, poollist[i]);
+                               rc = -EINVAL;
+                               goto out;
+                       }
+                       p++;
+                       printf("Quotas for pool: %s\n", p);
+                       strncpy(qctl->qc_poolname, p, LOV_MAXPOOLNAME);
+                       rc = get_print_quota(mnt, name, qctl, verbose, quiet,
+                                            human_readable, show_default);
+                       if (rc)
+                               break;
+               }
+               goto out;
+       }
+
        rc = get_print_quota(mnt, name, qctl, verbose, quiet,
                             human_readable, show_default);
 out:
        rc = get_print_quota(mnt, name, qctl, verbose, quiet,
                             human_readable, show_default);
 out:
+       free(buf);
        free(qctl);
        return rc;
 }
        free(qctl);
        return rc;
 }
index 52a9b1c..80ca61e 100644 (file)
@@ -1699,6 +1699,34 @@ free_path:
 /* wrapper for lfs.c and obd.c */
 int llapi_poollist(const char *name)
 {
 /* wrapper for lfs.c and obd.c */
 int llapi_poollist(const char *name)
 {
+       int poolcount, rc, i;
+       char *buf, **pools;
+
+       rc = llapi_get_poolbuf(name, &buf, &pools, &poolcount);
+       if (rc)
+               return rc;
+
+       for (i = 0; i < poolcount; i++)
+               llapi_printf(LLAPI_MSG_NORMAL, "%s\n", pools[i]);
+       free(buf);
+
+       return 0;
+}
+
+/**
+ * Get buffer that holds uuids and the list of pools in a filesystem.
+ *
+ * \param name         filesystem name or path
+ * \param buf          bufffer that has to be freed if function returns 0
+ * \param pools                pointer to the list of pools in buffer
+ * \param poolcount    number of pools
+ *
+ * \return 0 when found at least 1 pool, i.e. poolcount  > 0
+ * \retval -error failure
+ */
+int llapi_get_poolbuf(const char *name, char **buf,
+                     char ***pools, int *poolcount)
+{
        /*
         * list of pool names (assume that pool count is smaller
         * than OST count)
        /*
         * list of pool names (assume that pool count is smaller
         * than OST count)
@@ -1706,7 +1734,7 @@ int llapi_poollist(const char *name)
        char **list, *buffer = NULL, *fsname = (char *)name;
        char *poolname = NULL, *tmp = NULL, data[16];
        enum param_filter type = FILTER_BY_PATH;
        char **list, *buffer = NULL, *fsname = (char *)name;
        char *poolname = NULL, *tmp = NULL, data[16];
        enum param_filter type = FILTER_BY_PATH;
-       int obdcount, bufsize, rc, nb, i;
+       int obdcount, bufsize, rc, nb;
 
        if (name == NULL)
                return -EINVAL;
 
        if (name == NULL)
                return -EINVAL;
@@ -1758,11 +1786,15 @@ retry_get_pools:
                goto retry_get_pools;
        }
 
                goto retry_get_pools;
        }
 
-       for (i = 0; i < nb; i++)
-               llapi_printf(LLAPI_MSG_NORMAL, "%s\n", list[i]);
        rc = (nb < 0 ? nb : 0);
        rc = (nb < 0 ? nb : 0);
+       if (!rc) {
+               *buf = buffer;
+               *pools = list;
+               *poolcount = nb;
+       }
 err:
 err:
-       if (buffer)
+       /* Don't free buffer, it will be used later */
+       if (rc && buffer)
                free(buffer);
        if (fsname != NULL && type == FILTER_BY_FS_NAME)
                free(fsname);
                free(buffer);
        if (fsname != NULL && type == FILTER_BY_FS_NAME)
                free(fsname);