selftests/resctrl: Rename CQM test as CMT test
authorFenghua Yu <fenghua.yu@intel.com>
Wed, 17 Mar 2021 02:22:41 +0000 (02:22 +0000)
committerShuah Khan <skhan@linuxfoundation.org>
Fri, 2 Apr 2021 19:53:54 +0000 (13:53 -0600)
CMT (Cache Monitoring Technology) [1] is a H/W feature that reports cache
occupancy of a process. resctrl selftest suite has a unit test to test CMT
for LLC but the test is named as CQM (Cache Quality Monitoring).
Furthermore, the unit test source file is named as cqm_test.c and several
functions, variables, comments, preprocessors and statements widely use
"cqm" as either suffix or prefix. This rampant misusage of CQM for CMT
might confuse someone who is newly looking at resctrl selftests because
this feature is named CMT in the Intel Software Developer's Manual.

Hence, rename all the occurrences (unit test source file name, functions,
variables, comments and preprocessors) of cqm with cmt.

[1] Please see Intel SDM, Volume 3, chapter 17 and section 18 for more
    information on CMT: https://software.intel.com/content/www/us/en/develop/articles/intel-sdm.html

Suggested-by: Reinette Chatre <reinette.chatre@intel.com>
Tested-by: Babu Moger <babu.moger@amd.com>
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
tools/testing/selftests/resctrl/README
tools/testing/selftests/resctrl/cache.c
tools/testing/selftests/resctrl/cmt_test.c [new file with mode: 0644]
tools/testing/selftests/resctrl/cqm_test.c [deleted file]
tools/testing/selftests/resctrl/resctrl.h
tools/testing/selftests/resctrl/resctrl_tests.c
tools/testing/selftests/resctrl/resctrl_val.c
tools/testing/selftests/resctrl/resctrlfs.c

index 6e5a0ff..4b36b25 100644 (file)
@@ -46,8 +46,8 @@ ARGUMENTS
 Parameter '-h' shows usage information.
 
 usage: resctrl_tests [-h] [-b "benchmark_cmd [options]"] [-t test list] [-n no_of_bits]
-        -b benchmark_cmd [options]: run specified benchmark for MBM, MBA and CQM default benchmark is builtin fill_buf
-        -t test list: run tests specified in the test list, e.g. -t mbm, mba, cqm, cat
+        -b benchmark_cmd [options]: run specified benchmark for MBM, MBA and CMT default benchmark is builtin fill_buf
+        -t test list: run tests specified in the test list, e.g. -t mbm, mba, cmt, cat
         -n no_of_bits: run cache tests using specified no of bits in cache bit mask
         -p cpu_no: specify CPU number to run the test. 1 is default
         -h: help
index 5922cc1..2aa1b5c 100644 (file)
@@ -111,7 +111,7 @@ static int get_llc_perf(unsigned long *llc_perf_miss)
 
 /*
  * Get LLC Occupancy as reported by RESCTRL FS
- * For CQM,
+ * For CMT,
  * 1. If con_mon grp and mon grp given, then read from mon grp in
  * con_mon grp
  * 2. If only con_mon grp given, then read from con_mon grp
@@ -192,7 +192,7 @@ int measure_cache_vals(struct resctrl_val_param *param, int bm_pid)
        /*
         * Measure llc occupancy from resctrl.
         */
-       if (!strncmp(param->resctrl_val, CQM_STR, sizeof(CQM_STR))) {
+       if (!strncmp(param->resctrl_val, CMT_STR, sizeof(CMT_STR))) {
                ret = get_llc_occu_resctrl(&llc_occu_resc);
                if (ret < 0)
                        return ret;
diff --git a/tools/testing/selftests/resctrl/cmt_test.c b/tools/testing/selftests/resctrl/cmt_test.c
new file mode 100644 (file)
index 0000000..4b63838
--- /dev/null
@@ -0,0 +1,176 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Cache Monitoring Technology (CMT) test
+ *
+ * Copyright (C) 2018 Intel Corporation
+ *
+ * Authors:
+ *    Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>,
+ *    Fenghua Yu <fenghua.yu@intel.com>
+ */
+#include "resctrl.h"
+#include <unistd.h>
+
+#define RESULT_FILE_NAME       "result_cmt"
+#define NUM_OF_RUNS            5
+#define MAX_DIFF               2000000
+#define MAX_DIFF_PERCENT       15
+
+static int count_of_bits;
+static char cbm_mask[256];
+static unsigned long long_mask;
+static unsigned long cache_size;
+
+static int cmt_setup(int num, ...)
+{
+       struct resctrl_val_param *p;
+       va_list param;
+
+       va_start(param, num);
+       p = va_arg(param, struct resctrl_val_param *);
+       va_end(param);
+
+       /* Run NUM_OF_RUNS times */
+       if (p->num_of_runs >= NUM_OF_RUNS)
+               return -1;
+
+       p->num_of_runs++;
+
+       return 0;
+}
+
+static void show_cache_info(unsigned long sum_llc_occu_resc, int no_of_bits,
+                           unsigned long span)
+{
+       unsigned long avg_llc_occu_resc = 0;
+       float diff_percent;
+       long avg_diff = 0;
+       bool res;
+
+       avg_llc_occu_resc = sum_llc_occu_resc / (NUM_OF_RUNS - 1);
+       avg_diff = (long)abs(span - avg_llc_occu_resc);
+
+       diff_percent = (((float)span - avg_llc_occu_resc) / span) * 100;
+
+       if ((abs((int)diff_percent) <= MAX_DIFF_PERCENT) ||
+           (abs(avg_diff) <= MAX_DIFF))
+               res = true;
+       else
+               res = false;
+
+       printf("%sok CMT: diff within %d, %d\%%\n", res ? "" : "not",
+              MAX_DIFF, (int)MAX_DIFF_PERCENT);
+
+       printf("# diff: %ld\n", avg_diff);
+       printf("# percent diff=%d\n", abs((int)diff_percent));
+       printf("# Results are displayed in (Bytes)\n");
+       printf("# Number of bits: %d\n", no_of_bits);
+       printf("# Avg_llc_occu_resc: %lu\n", avg_llc_occu_resc);
+       printf("# llc_occu_exp (span): %lu\n", span);
+
+       tests_run++;
+}
+
+static int check_results(struct resctrl_val_param *param, int no_of_bits)
+{
+       char *token_array[8], temp[512];
+       unsigned long sum_llc_occu_resc = 0;
+       int runs = 0;
+       FILE *fp;
+
+       printf("# checking for pass/fail\n");
+       fp = fopen(param->filename, "r");
+       if (!fp) {
+               perror("# Error in opening file\n");
+
+               return errno;
+       }
+
+       while (fgets(temp, sizeof(temp), fp)) {
+               char *token = strtok(temp, ":\t");
+               int fields = 0;
+
+               while (token) {
+                       token_array[fields++] = token;
+                       token = strtok(NULL, ":\t");
+               }
+
+               /* Field 3 is llc occ resc value */
+               if (runs > 0)
+                       sum_llc_occu_resc += strtoul(token_array[3], NULL, 0);
+               runs++;
+       }
+       fclose(fp);
+       show_cache_info(sum_llc_occu_resc, no_of_bits, param->span);
+
+       return 0;
+}
+
+void cmt_test_cleanup(void)
+{
+       remove(RESULT_FILE_NAME);
+}
+
+int cmt_resctrl_val(int cpu_no, int n, char **benchmark_cmd)
+{
+       int ret, mum_resctrlfs;
+
+       cache_size = 0;
+       mum_resctrlfs = 1;
+
+       ret = remount_resctrlfs(mum_resctrlfs);
+       if (ret)
+               return ret;
+
+       if (!validate_resctrl_feature_request(CMT_STR))
+               return -1;
+
+       ret = get_cbm_mask("L3", cbm_mask);
+       if (ret)
+               return ret;
+
+       long_mask = strtoul(cbm_mask, NULL, 16);
+
+       ret = get_cache_size(cpu_no, "L3", &cache_size);
+       if (ret)
+               return ret;
+       printf("cache size :%lu\n", cache_size);
+
+       count_of_bits = count_bits(long_mask);
+
+       if (n < 1 || n > count_of_bits) {
+               printf("Invalid input value for numbr_of_bits n!\n");
+               printf("Please Enter value in range 1 to %d\n", count_of_bits);
+               return -1;
+       }
+
+       struct resctrl_val_param param = {
+               .resctrl_val    = CMT_STR,
+               .ctrlgrp        = "c1",
+               .mongrp         = "m1",
+               .cpu_no         = cpu_no,
+               .mum_resctrlfs  = 0,
+               .filename       = RESULT_FILE_NAME,
+               .mask           = ~(long_mask << n) & long_mask,
+               .span           = cache_size * n / count_of_bits,
+               .num_of_runs    = 0,
+               .setup          = cmt_setup,
+       };
+
+       if (strcmp(benchmark_cmd[0], "fill_buf") == 0)
+               sprintf(benchmark_cmd[1], "%lu", param.span);
+
+       remove(RESULT_FILE_NAME);
+
+       ret = resctrl_val(benchmark_cmd, &param);
+       if (ret)
+               return ret;
+
+       ret = check_results(&param, n);
+       if (ret)
+               return ret;
+
+       cmt_test_cleanup();
+
+       return 0;
+}
diff --git a/tools/testing/selftests/resctrl/cqm_test.c b/tools/testing/selftests/resctrl/cqm_test.c
deleted file mode 100644 (file)
index 271752e..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Cache Monitoring Technology (CQM) test
- *
- * Copyright (C) 2018 Intel Corporation
- *
- * Authors:
- *    Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>,
- *    Fenghua Yu <fenghua.yu@intel.com>
- */
-#include "resctrl.h"
-#include <unistd.h>
-
-#define RESULT_FILE_NAME       "result_cqm"
-#define NUM_OF_RUNS            5
-#define MAX_DIFF               2000000
-#define MAX_DIFF_PERCENT       15
-
-static int count_of_bits;
-static char cbm_mask[256];
-static unsigned long long_mask;
-static unsigned long cache_size;
-
-static int cqm_setup(int num, ...)
-{
-       struct resctrl_val_param *p;
-       va_list param;
-
-       va_start(param, num);
-       p = va_arg(param, struct resctrl_val_param *);
-       va_end(param);
-
-       /* Run NUM_OF_RUNS times */
-       if (p->num_of_runs >= NUM_OF_RUNS)
-               return -1;
-
-       p->num_of_runs++;
-
-       return 0;
-}
-
-static void show_cache_info(unsigned long sum_llc_occu_resc, int no_of_bits,
-                           unsigned long span)
-{
-       unsigned long avg_llc_occu_resc = 0;
-       float diff_percent;
-       long avg_diff = 0;
-       bool res;
-
-       avg_llc_occu_resc = sum_llc_occu_resc / (NUM_OF_RUNS - 1);
-       avg_diff = (long)abs(span - avg_llc_occu_resc);
-
-       diff_percent = (((float)span - avg_llc_occu_resc) / span) * 100;
-
-       if ((abs((int)diff_percent) <= MAX_DIFF_PERCENT) ||
-           (abs(avg_diff) <= MAX_DIFF))
-               res = true;
-       else
-               res = false;
-
-       printf("%sok CQM: diff within %d, %d\%%\n", res ? "" : "not",
-              MAX_DIFF, (int)MAX_DIFF_PERCENT);
-
-       printf("# diff: %ld\n", avg_diff);
-       printf("# percent diff=%d\n", abs((int)diff_percent));
-       printf("# Results are displayed in (Bytes)\n");
-       printf("# Number of bits: %d\n", no_of_bits);
-       printf("# Avg_llc_occu_resc: %lu\n", avg_llc_occu_resc);
-       printf("# llc_occu_exp (span): %lu\n", span);
-
-       tests_run++;
-}
-
-static int check_results(struct resctrl_val_param *param, int no_of_bits)
-{
-       char *token_array[8], temp[512];
-       unsigned long sum_llc_occu_resc = 0;
-       int runs = 0;
-       FILE *fp;
-
-       printf("# checking for pass/fail\n");
-       fp = fopen(param->filename, "r");
-       if (!fp) {
-               perror("# Error in opening file\n");
-
-               return errno;
-       }
-
-       while (fgets(temp, sizeof(temp), fp)) {
-               char *token = strtok(temp, ":\t");
-               int fields = 0;
-
-               while (token) {
-                       token_array[fields++] = token;
-                       token = strtok(NULL, ":\t");
-               }
-
-               /* Field 3 is llc occ resc value */
-               if (runs > 0)
-                       sum_llc_occu_resc += strtoul(token_array[3], NULL, 0);
-               runs++;
-       }
-       fclose(fp);
-       show_cache_info(sum_llc_occu_resc, no_of_bits, param->span);
-
-       return 0;
-}
-
-void cqm_test_cleanup(void)
-{
-       remove(RESULT_FILE_NAME);
-}
-
-int cqm_resctrl_val(int cpu_no, int n, char **benchmark_cmd)
-{
-       int ret, mum_resctrlfs;
-
-       cache_size = 0;
-       mum_resctrlfs = 1;
-
-       ret = remount_resctrlfs(mum_resctrlfs);
-       if (ret)
-               return ret;
-
-       if (!validate_resctrl_feature_request("cqm"))
-               return -1;
-
-       ret = get_cbm_mask("L3", cbm_mask);
-       if (ret)
-               return ret;
-
-       long_mask = strtoul(cbm_mask, NULL, 16);
-
-       ret = get_cache_size(cpu_no, "L3", &cache_size);
-       if (ret)
-               return ret;
-       printf("cache size :%lu\n", cache_size);
-
-       count_of_bits = count_bits(long_mask);
-
-       if (n < 1 || n > count_of_bits) {
-               printf("Invalid input value for numbr_of_bits n!\n");
-               printf("Please Enter value in range 1 to %d\n", count_of_bits);
-               return -1;
-       }
-
-       struct resctrl_val_param param = {
-               .resctrl_val    = CQM_STR,
-               .ctrlgrp        = "c1",
-               .mongrp         = "m1",
-               .cpu_no         = cpu_no,
-               .mum_resctrlfs  = 0,
-               .filename       = RESULT_FILE_NAME,
-               .mask           = ~(long_mask << n) & long_mask,
-               .span           = cache_size * n / count_of_bits,
-               .num_of_runs    = 0,
-               .setup          = cqm_setup,
-       };
-
-       if (strcmp(benchmark_cmd[0], "fill_buf") == 0)
-               sprintf(benchmark_cmd[1], "%lu", param.span);
-
-       remove(RESULT_FILE_NAME);
-
-       ret = resctrl_val(benchmark_cmd, &param);
-       if (ret)
-               return ret;
-
-       ret = check_results(&param, n);
-       if (ret)
-               return ret;
-
-       cqm_test_cleanup();
-
-       return 0;
-}
index 36da613..1a58767 100644 (file)
@@ -64,7 +64,7 @@ struct resctrl_val_param {
 
 #define MBM_STR                        "mbm"
 #define MBA_STR                        "mba"
-#define CQM_STR                        "cqm"
+#define CMT_STR                        "cmt"
 #define CAT_STR                        "cat"
 
 extern pid_t bm_pid, ppid;
@@ -103,9 +103,9 @@ void ctrlc_handler(int signum, siginfo_t *info, void *ptr);
 int cat_val(struct resctrl_val_param *param);
 void cat_test_cleanup(void);
 int cat_perf_miss_val(int cpu_no, int no_of_bits, char *cache_type);
-int cqm_resctrl_val(int cpu_no, int n, char **benchmark_cmd);
+int cmt_resctrl_val(int cpu_no, int n, char **benchmark_cmd);
 unsigned int count_bits(unsigned long n);
-void cqm_test_cleanup(void);
+void cmt_test_cleanup(void);
 int get_core_sibling(int cpu_no);
 int measure_cache_vals(struct resctrl_val_param *param, int bm_pid);
 
index ac22696..6b2ed2e 100644 (file)
@@ -37,10 +37,10 @@ void detect_amd(void)
 static void cmd_help(void)
 {
        printf("usage: resctrl_tests [-h] [-b \"benchmark_cmd [options]\"] [-t test list] [-n no_of_bits]\n");
-       printf("\t-b benchmark_cmd [options]: run specified benchmark for MBM, MBA and CQM");
+       printf("\t-b benchmark_cmd [options]: run specified benchmark for MBM, MBA and CMT");
        printf("\t default benchmark is builtin fill_buf\n");
        printf("\t-t test list: run tests specified in the test list, ");
-       printf("e.g. -t mbm, mba, cqm, cat\n");
+       printf("e.g. -t mbm, mba, cmt, cat\n");
        printf("\t-n no_of_bits: run cache tests using specified no of bits in cache bit mask\n");
        printf("\t-p cpu_no: specify CPU number to run the test. 1 is default\n");
        printf("\t-h: help\n");
@@ -50,13 +50,13 @@ void tests_cleanup(void)
 {
        mbm_test_cleanup();
        mba_test_cleanup();
-       cqm_test_cleanup();
+       cmt_test_cleanup();
        cat_test_cleanup();
 }
 
 int main(int argc, char **argv)
 {
-       bool has_ben = false, mbm_test = true, mba_test = true, cqm_test = true;
+       bool has_ben = false, mbm_test = true, mba_test = true, cmt_test = true;
        int res, c, cpu_no = 1, span = 250, argc_new = argc, i, no_of_bits = 5;
        char *benchmark_cmd[BENCHMARK_ARGS], bw_report[64], bm_type[64];
        char benchmark_cmd_area[BENCHMARK_ARGS][BENCHMARK_ARG_SIZE];
@@ -82,15 +82,15 @@ int main(int argc, char **argv)
 
                        mbm_test = false;
                        mba_test = false;
-                       cqm_test = false;
+                       cmt_test = false;
                        cat_test = false;
                        while (token) {
                                if (!strncmp(token, MBM_STR, sizeof(MBM_STR))) {
                                        mbm_test = true;
                                } else if (!strncmp(token, MBA_STR, sizeof(MBA_STR))) {
                                        mba_test = true;
-                               } else if (!strncmp(token, CQM_STR, sizeof(CQM_STR))) {
-                                       cqm_test = true;
+                               } else if (!strncmp(token, CMT_STR, sizeof(CMT_STR))) {
+                                       cmt_test = true;
                                } else if (!strncmp(token, CAT_STR, sizeof(CAT_STR))) {
                                        cat_test = true;
                                } else {
@@ -178,13 +178,13 @@ int main(int argc, char **argv)
                tests_run++;
        }
 
-       if (cqm_test) {
-               printf("# Starting CQM test ...\n");
+       if (cmt_test) {
+               printf("# Starting CMT test ...\n");
                if (!has_ben)
-                       sprintf(benchmark_cmd[5], "%s", CQM_STR);
-               res = cqm_resctrl_val(cpu_no, no_of_bits, benchmark_cmd);
-               printf("%sok CQM: test\n", res ? "not " : "");
-               cqm_test_cleanup();
+                       sprintf(benchmark_cmd[5], "%s", CMT_STR);
+               res = cmt_resctrl_val(cpu_no, no_of_bits, benchmark_cmd);
+               printf("%sok CMT: test\n", res ? "not " : "");
+               cmt_test_cleanup();
                tests_run++;
        }
 
index aed71fd..1777009 100644 (file)
@@ -492,7 +492,7 @@ static int print_results_bw(char *filename,  int bm_pid, float bw_imc,
        return 0;
 }
 
-static void set_cqm_path(const char *ctrlgrp, const char *mongrp, char sock_num)
+static void set_cmt_path(const char *ctrlgrp, const char *mongrp, char sock_num)
 {
        if (strlen(ctrlgrp) && strlen(mongrp))
                sprintf(llc_occup_path, CON_MON_LCC_OCCUP_PATH, RESCTRL_PATH,
@@ -512,7 +512,7 @@ static void set_cqm_path(const char *ctrlgrp, const char *mongrp, char sock_num)
  * @ctrlgrp:                   Name of the control monitor group (con_mon grp)
  * @mongrp:                    Name of the monitor group (mon grp)
  * @cpu_no:                    CPU number that the benchmark PID is binded to
- * @resctrl_val:               Resctrl feature (Eg: cat, cqm.. etc)
+ * @resctrl_val:               Resctrl feature (Eg: cat, cmt.. etc)
  */
 static void initialize_llc_occu_resctrl(const char *ctrlgrp, const char *mongrp,
                                        int cpu_no, char *resctrl_val)
@@ -524,8 +524,8 @@ static void initialize_llc_occu_resctrl(const char *ctrlgrp, const char *mongrp,
                return;
        }
 
-       if (!strncmp(resctrl_val, CQM_STR, sizeof(CQM_STR)))
-               set_cqm_path(ctrlgrp, mongrp, resource_id);
+       if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR)))
+               set_cmt_path(ctrlgrp, mongrp, resource_id);
 }
 
 static int
@@ -682,7 +682,7 @@ int resctrl_val(char **benchmark_cmd, struct resctrl_val_param *param)
 
                initialize_mem_bw_resctrl(param->ctrlgrp, param->mongrp,
                                          param->cpu_no, resctrl_val);
-       } else if (!strncmp(resctrl_val, CQM_STR, sizeof(CQM_STR)))
+       } else if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR)))
                initialize_llc_occu_resctrl(param->ctrlgrp, param->mongrp,
                                            param->cpu_no, resctrl_val);
 
@@ -721,7 +721,7 @@ int resctrl_val(char **benchmark_cmd, struct resctrl_val_param *param)
                        ret = measure_vals(param, &bw_resc_start);
                        if (ret)
                                break;
-               } else if (!strncmp(resctrl_val, CQM_STR, sizeof(CQM_STR))) {
+               } else if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR))) {
                        ret = param->setup(1, param);
                        if (ret) {
                                ret = 0;
index bc52076..b47f4f1 100644 (file)
@@ -334,7 +334,7 @@ void run_benchmark(int signum, siginfo_t *info, void *ucontext)
                operation = atoi(benchmark_cmd[4]);
                sprintf(resctrl_val, "%s", benchmark_cmd[5]);
 
-               if (strncmp(resctrl_val, CQM_STR, sizeof(CQM_STR)))
+               if (strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR)))
                        buffer_span = span * MB;
                else
                        buffer_span = span;
@@ -458,8 +458,8 @@ int write_bm_pid_to_resctrl(pid_t bm_pid, char *ctrlgrp, char *mongrp,
        if (ret)
                goto out;
 
-       /* Create mon grp and write pid into it for "mbm" and "cqm" test */
-       if (!strncmp(resctrl_val, CQM_STR, sizeof(CQM_STR)) ||
+       /* Create mon grp and write pid into it for "mbm" and "cmt" test */
+       if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR)) ||
            !strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR))) {
                if (strlen(mongrp)) {
                        sprintf(monitorgroup_p, "%s/mon_groups", controlgroup);
@@ -507,7 +507,7 @@ int write_schemata(char *ctrlgrp, char *schemata, int cpu_no, char *resctrl_val)
 
        if (strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR)) &&
            strncmp(resctrl_val, CAT_STR, sizeof(CAT_STR)) &&
-           strncmp(resctrl_val, CQM_STR, sizeof(CQM_STR)))
+           strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR)))
                return -ENOENT;
 
        if (!schemata) {
@@ -529,7 +529,7 @@ int write_schemata(char *ctrlgrp, char *schemata, int cpu_no, char *resctrl_val)
                sprintf(controlgroup, "%s/schemata", RESCTRL_PATH);
 
        if (!strncmp(resctrl_val, CAT_STR, sizeof(CAT_STR)) ||
-           !strncmp(resctrl_val, CQM_STR, sizeof(CQM_STR)))
+           !strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR)))
                sprintf(schema, "%s%d%c%s", "L3:", resource_id, '=', schemata);
        if (!strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR)))
                sprintf(schema, "%s%d%c%s", "MB:", resource_id, '=', schemata);