Whamcloud - gitweb
LU-16599 obdclass: job_stats can parse escaped jobid string 60/50160/7
authorLei Feng <flei@whamcloud.com>
Wed, 1 Mar 2023 00:16:03 +0000 (08:16 +0800)
committerOleg Drokin <green@whamcloud.com>
Tue, 28 Mar 2023 22:16:32 +0000 (22:16 +0000)
Writing a jobid to job_stats proc entry asks lustre to clear
the stats of the specific jobid. Since job_stats outputs
escaped jobid string in some cases, it should be able to parse
an escaped jobid string when the string is written to it.

Test-Parameters: trivial
Signed-off-by: Lei Feng <flei@whamcloud.com>
Change-Id: Idbc63dac6c3b35331317927107e634a3d638dd66
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/50160
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@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 2173f27..9c61b95 100644 (file)
@@ -561,10 +561,12 @@ static ssize_t lprocfs_jobstats_seq_write(struct file *file,
 {
        struct seq_file *seq = file->private_data;
        struct obd_job_stats *stats = seq->private;
-       char jobid[LUSTRE_JOBID_SIZE];
+       char jobid[4 * LUSTRE_JOBID_SIZE]; /* all escaped chars, plus ""\n\0 */
+       char *p1, *p2, *last;
+       unsigned int c;
        struct job_stat *job;
 
-       if (len == 0 || len >= LUSTRE_JOBID_SIZE)
+       if (len == 0 || len >= 4 * LUSTRE_JOBID_SIZE)
                return -EINVAL;
 
        if (stats->ojs_hash == NULL)
@@ -573,10 +575,31 @@ static ssize_t lprocfs_jobstats_seq_write(struct file *file,
        if (copy_from_user(jobid, buf, len))
                return -EFAULT;
        jobid[len] = 0;
+       last = jobid + len - 1;
 
        /* Trim '\n' if any */
-       if (jobid[len - 1] == '\n')
-               jobid[len - 1] = 0;
+       if (*last == '\n')
+               *(last--) = 0;
+
+       /* decode escaped chars if jobid is a quoted string */
+       if (jobid[0] == '"' && *last == '"') {
+               last--;
+
+               for (p1 = jobid, p2 = jobid + 1; p2 <= last; p1++, p2++) {
+                       if (*p2 != '\\') {
+                               *p1 = *p2;
+                       } else if (p2 + 3 <= last && *(p2 + 1) == 'x' &&
+                                sscanf(p2 + 2, "%02X", &c) == 1) {
+                               *p1 = c;
+                               p2 += 3;
+                       } else {
+                               return -EINVAL;
+                       }
+               }
+               *p1 = 0;
+
+       }
+       jobid[LUSTRE_JOBID_SIZE - 1] = 0;
 
        if (strcmp(jobid, "clear") == 0) {
                lprocfs_job_cleanup(stats, true);
index bd32050..a1fb1d6 100755 (executable)
@@ -19468,7 +19468,7 @@ test_205a() { # Job stats
 }
 run_test 205a "Verify job stats"
 
-# LU-13117, LU-13597
+# LU-13117, LU-13597, LU-16599
 test_205b() {
        (( $MDS1_VERSION >= $(version_code 2.13.54.91) )) ||
                skip "Need MDS version at least 2.13.54.91"
@@ -19494,11 +19494,26 @@ test_205b() {
 
        (( $MDS1_VERSION <= $(version_code 2.15.0) )) &&
                echo "MDS does not yet escape jobid" && return 0
+
+       mkdir_on_mdt0 $DIR/$tdir
        $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;
+       env -i TEST205b="has sp" touch $DIR/$tdir/$tfile.2
+       local jobid=$(do_facet mds1 $LCTL get_param $job_stats |
+                     awk '/has\\x20sp/ {print $3}')
+       [[ -n "$jobid" ]] || { do_facet mds1 $LCTL get_param $job_stats;
                  error "jobid not escaped"; }
+
+       if (( $MDS1_VERSION >= $(version_code 2.15.53.139) )); then
+               # need to run such a command on mds1:
+               # lctl set_param mdt.$FSNAME-MDT0000.job_stats='"has\x20sp.touch.0"'
+               #
+               # there might be multiple MDTs on single mds server, so need to
+               # specifiy MDT0000. Or the command will fail due to other MDTs
+               do_facet_vp mds1 $LCTL set_param mdt.$FSNAME-MDT0000.job_stats=$jobid ||
+                       error "cannot clear escaped jobid in job_stats";
+       else
+               echo "MDS does not support clearing escaped jobid"
+       fi
 }
 run_test 205b "Verify job stats jobid and output format"