Whamcloud - gitweb
LU-11407 tgt: cleanup job_stats output printing 64/37764/24
authorAndreas Dilger <adilger@whamcloud.com>
Fri, 10 Jan 2020 21:18:53 +0000 (14:18 -0700)
committerOleg Drokin <green@whamcloud.com>
Tue, 26 Jul 2022 04:53:27 +0000 (04:53 +0000)
Escape non-printable and other special characters in the JobID
name, which may be passed from the client environment, to avoid
breaking YAML format parsing.  We can't use the kernel "%*pE"
escape format, because that doesn't have any option to escape
printable characters like quotes or regular spaces.

Signed-off-by: Andreas Dilger <adilger@whamcloud.com>
Change-Id: If6a0bc4276fae03305f94e8c85d8f109913ebbe5
Reviewed-on: https://review.whamcloud.com/37764
Tested-by: jenkins <devops@whamcloud.com>
Reviewed-by: Ben Evans <beevans@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Arshad Hussain <arshad.hussain@aeoncomputing.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/obdclass/lprocfs_jobstats.c
lustre/tests/sanity.sh

index ca5ae3b..5eca82e 100644 (file)
@@ -439,24 +439,35 @@ static int lprocfs_jobstats_seq_show(struct seq_file *p, void *v)
        struct lprocfs_stats *s;
        struct lprocfs_counter ret;
        struct lprocfs_counter_header *cntr_header;
-       int i;
+       char escaped[LUSTRE_JOBID_SIZE * 4] = "";
+       char *quote = "", *c, *end;
+       int i, joblen = 0;
 
        if (v == SEQ_START_TOKEN) {
                seq_printf(p, "job_stats:\n");
                return 0;
        }
 
-       /* Replace the non-printable character in jobid with '?', so
-        * that the output of jobid will be confined in single line. */
-       seq_printf(p, "- %-16s ", "job_id:");
-       for (i = 0; i < strlen(job->js_jobid); i++) {
-               if (isprint(job->js_jobid[i]) != 0)
-                       seq_putc(p, job->js_jobid[i]);
-               else
-                       seq_putc(p, '?');
+       /* Quote and escape jobid characters to escape hex codes "\xHH" if
+        * it contains any non-standard characters (space, newline, etc),
+        * so it will be confined to single line and not break parsing.
+        */
+       for (c = job->js_jobid, end = job->js_jobid + sizeof(job->js_jobid);
+            c < end && *c != '\0';
+            c++, joblen++) {
+               if (!isalnum(*c) &&
+                   *c != '.' && *c != '@' && *c != '-' && *c != '_') {
+                       quote = "\"";
+                       snprintf(escaped + joblen, sizeof(escaped), "\\x%02X",
+                                (unsigned char)*c);
+                       joblen += 3;
+               } else {
+                       escaped[joblen] = *c;
+               }
        }
-       seq_putc(p, '\n');
 
+       seq_printf(p, "- %-16s %s%*s%s\n",
+                  "job_id:", quote, joblen, escaped, quote);
        lprocfs_stats_header(p, job->js_time_latest, job->js_time_init, 16,
                             ":", true);
 
@@ -486,6 +497,7 @@ static int lprocfs_jobstats_seq_show(struct seq_file *p, void *v)
                seq_printf(p, " }\n");
 
        }
+
        return 0;
 }
 
index a63333d..e098c80 100755 (executable)
@@ -18807,18 +18807,32 @@ test_205b() {
        (( $MDS1_VERSION >= $(version_code 2.13.54.91) )) ||
                skip "Need MDS version at least 2.13.54.91"
 
-       job_stats="mdt.*.job_stats"
-       $LCTL set_param $job_stats=clear
+       local job_stats="mdt.*.job_stats"
+       local old_jobid=$(do_facet mds1 $LCTL get_param jobid_var)
+
+       do_facet mds1 $LCTL set_param $job_stats=clear
+
        # Setting jobid_var to USER might not be supported
+       [[ -n "$old_jobid" ]] && stack_trap "$LCTL set_param $old_jobid"
        $LCTL set_param jobid_var=USER || true
-       $LCTL set_param jobid_name="%e.%u"
+       stack_trap "$LCTL set_param $($LCTL get_param jobid_name)"
+       $LCTL set_param jobid_name="%j.%e.%u"
+
        env -i USERTESTJOBSTATS=foolish touch $DIR/$tfile.1
-       do_facet $SINGLEMDS $LCTL get_param $job_stats |
-               grep "job_id:.*foolish" &&
-                       error "Unexpected jobid found"
-       do_facet $SINGLEMDS $LCTL get_param $job_stats |
-               grep "open:.*min.*max.*sum" ||
-                       error "wrong job_stats format found"
+       do_facet mds1 $LCTL get_param $job_stats | grep "job_id:.*foolish" &&
+               { do_facet mds1 $LCTL get_param $job_stats;
+                 error "Unexpected jobid found"; }
+       do_facet mds1 $LCTL get_param $job_stats | grep "open:.*min.*max.*sum"||
+               { do_facet mds1 $LCTL get_param $job_stats;
+                 error "wrong job_stats format found"; }
+
+       (( $MDS1_VERSION <= $(version_code 2.15.0) )) &&
+               echo "MDS does not yet escape jobid" && return 0
+       $LCTL set_param jobid_var=TEST205b
+       env -i TEST205b="has sp" touch $DIR/$tfile.2
+       do_facet mds1 $LCTL get_param $job_stats | grep "has.*x20sp" ||
+               { do_facet mds1 $LCTL get_param $job_stats;
+                 error "jobid not escaped"; }
 }
 run_test 205b "Verify job stats jobid and output format"