From 8f004bc53b1a488dad5a92a580f5f0c078e33654 Mon Sep 17 00:00:00 2001 From: Lei Feng Date: Wed, 1 Mar 2023 08:16:03 +0800 Subject: [PATCH] LU-16599 obdclass: job_stats can parse escaped jobid string 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 Change-Id: Idbc63dac6c3b35331317927107e634a3d638dd66 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/50160 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Arshad Hussain Reviewed-by: Oleg Drokin --- lustre/obdclass/lprocfs_jobstats.c | 31 +++++++++++++++++++++++++++---- lustre/tests/sanity.sh | 23 +++++++++++++++++++---- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/lustre/obdclass/lprocfs_jobstats.c b/lustre/obdclass/lprocfs_jobstats.c index 2173f27..9c61b95 100644 --- a/lustre/obdclass/lprocfs_jobstats.c +++ b/lustre/obdclass/lprocfs_jobstats.c @@ -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); diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index bd32050..a1fb1d6 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -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" -- 1.8.3.1