Auto sync2gitlab import of rt-tests-2.5-1.el8.src.rpm
This commit is contained in:
		
							parent
							
								
									cb97843325
								
							
						
					
					
						commit
						bfd23b10f6
					
				
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,2 +1,3 @@ | ||||
| /rt-tests-2.3.tar.xz | ||||
| /rt-tests-2.4.tar.xz | ||||
| /rt-tests-2.5.tar.xz | ||||
|  | ||||
| @ -1,300 +0,0 @@ | ||||
| From cbec2872f7533a87f0b63a30d70386d203ebd138 Mon Sep 17 00:00:00 2001 | ||||
| From: Crystal Wood <swood@redhat.com> | ||||
| Date: Tue, 13 Dec 2022 16:38:28 -0600 | ||||
| Subject: [PATCH] oslat: Add command line option for bucket width | ||||
| 
 | ||||
| New option -W/--bucket-width allows the user to specify how large of a | ||||
| range of latencies is covered by a single bucket, including allowing the | ||||
| creation of sub-microsecond buckets. | ||||
| 
 | ||||
| When the flag is not used, output should be unchanged.  However, if a | ||||
| bucket width is specified that is not a multiple of one microsecond, | ||||
| latencies will be output as fractional microseconds, at nanosecond | ||||
| precision.  This includes JSON output. | ||||
| 
 | ||||
| When using this option, it is up to the user to determine what level | ||||
| of precision is meaningful relative to measurement error, as is noted | ||||
| in the documentation. | ||||
| 
 | ||||
| Signed-off-by: Crystal Wood <swood@redhat.com> | ||||
| Signed-off-by: John Kacur <jkacur@redhat.com> | ||||
| ---
 | ||||
|  src/oslat/oslat.8 |   9 +++- | ||||
|  src/oslat/oslat.c | 110 ++++++++++++++++++++++++++++++++-------------- | ||||
|  2 files changed, 85 insertions(+), 34 deletions(-) | ||||
| 
 | ||||
| diff --git a/src/oslat/oslat.8 b/src/oslat/oslat.8
 | ||||
| index 39b36df0db3f..eb96448bfff1 100644
 | ||||
| --- a/src/oslat/oslat.8
 | ||||
| +++ b/src/oslat/oslat.8
 | ||||
| @@ -7,7 +7,7 @@ oslat \- OS Latency Detector
 | ||||
|  .RI "[ \-shvz ] [ \-b " bucket-size " ] [ \-B " bias " ] [ \-c " cpu-list " ] \ | ||||
|  [ \-C " cpu-main-thread " ] [ \-f " rt-prio " ] [ \-\-json " filename " ] \ | ||||
|  [ \-m " workload-mem " ] [\-t " runtime " ] [ \-T " trace-threshold " ] \ | ||||
| -[ \-w " workload " ]"
 | ||||
| +[ \-w " workload " ] [ \-W " bucket-width " ]"
 | ||||
|  .SH DESCRIPTION | ||||
|  .B oslat | ||||
|  is an open source userspace polling mode stress program to detect OS level | ||||
| @@ -57,6 +57,13 @@ NOTE: please make sure the CPU frequency on all testing cores
 | ||||
|  are locked before using this parmater.  If you don't know how | ||||
|  to lock the freq then please don't use this parameter. | ||||
|  .TP | ||||
| +.B \-W, \-\-bucket-width
 | ||||
| +Interval between buckets in nanoseconds
 | ||||
| +
 | ||||
| +NOTE: Widths not a multiple of 1000 cause ns-precision output
 | ||||
| +You are responsible for considering the impact of measurement
 | ||||
| +overhead at the nanosecond scale.
 | ||||
| +.TP
 | ||||
|  .B \-h, \-\-help | ||||
|  Show the help message. | ||||
|  .TP | ||||
| diff --git a/src/oslat/oslat.c b/src/oslat/oslat.c
 | ||||
| index 55302f11986b..b680f1ebce96 100644
 | ||||
| --- a/src/oslat/oslat.c
 | ||||
| +++ b/src/oslat/oslat.c
 | ||||
| @@ -192,6 +192,10 @@ struct global {
 | ||||
|  	struct timeval        tv_start; | ||||
|  	int                   rtprio; | ||||
|  	int                   bucket_size; | ||||
| +	bool                  bucket_size_param;
 | ||||
| +	int                   bucket_width;
 | ||||
| +	int                   unit_per_us;
 | ||||
| +	int                   precision;
 | ||||
|  	int                   trace_threshold; | ||||
|  	int                   runtime; | ||||
|  	/* The core that we run the main thread.  Default is cpu0 */ | ||||
| @@ -325,45 +329,46 @@ static float cycles_to_sec(const struct thread *t, uint64_t cycles)
 | ||||
|   | ||||
|  static void insert_bucket(struct thread *t, stamp_t value) | ||||
|  { | ||||
| -	int index, us;
 | ||||
| +	int index;
 | ||||
| +	unsigned int lat;
 | ||||
|  	uint64_t extra; | ||||
| +	double us;
 | ||||
|   | ||||
| -	index = value / t->counter_mhz;
 | ||||
| -	assert(index >= 0);
 | ||||
| -	us = index + 1;
 | ||||
| -	assert(us > 0);
 | ||||
| -
 | ||||
| +	lat = (value * g.unit_per_us + t->counter_mhz - 1) / t->counter_mhz;
 | ||||
| +	us = (double)lat / g.unit_per_us;
 | ||||
|  	if (!g.preheat && g.trace_threshold && us >= g.trace_threshold) { | ||||
| -		char *line = "%s: Trace threshold (%d us) triggered on cpu %d with %u us!\n"
 | ||||
| +		char *line = "%s: Trace threshold (%d us) triggered on cpu %d with %.*f us!\n"
 | ||||
|  		    "Stopping the test.\n"; | ||||
| -		tracemark(line, g.app_name, g.trace_threshold, t->core_i, us);
 | ||||
| -		err_quit(line, g.app_name, g.trace_threshold, t->core_i, us);
 | ||||
| +		tracemark(line, g.app_name, g.trace_threshold, t->core_i,
 | ||||
| +			  g.precision, us);
 | ||||
| +		err_quit(line, g.app_name, g.trace_threshold, t->core_i,
 | ||||
| +			 g.precision, us);
 | ||||
|  	} | ||||
|   | ||||
|  	/* Update max latency */ | ||||
| -	if (us > t->maxlat)
 | ||||
| -		t->maxlat = us;
 | ||||
| +	if (lat > t->maxlat)
 | ||||
| +		t->maxlat = lat;
 | ||||
|   | ||||
| -	if (us < t->minlat)
 | ||||
| -		t->minlat = us;
 | ||||
| +	if (lat < t->minlat)
 | ||||
| +		t->minlat = lat;
 | ||||
|   | ||||
|  	if (g.bias) { | ||||
|  		/* t->bias will be set after pre-heat if user enabled it */ | ||||
| -		us -= g.bias;
 | ||||
| +		lat -= g.bias;
 | ||||
|  		/* | ||||
|  		 * Negative should hardly happen, but if it happens, we assume we're in | ||||
| -		 * the smallest bucket, which is 1us.  Same to index.
 | ||||
| +		 * the smallest bucket.
 | ||||
|  		 */ | ||||
| -		if (us <= 0)
 | ||||
| -			us = 1;
 | ||||
| -		index -= g.bias;
 | ||||
| -		if (index < 0)
 | ||||
| -			index = 0;
 | ||||
| +		if (lat <= 0)
 | ||||
| +			lat = 1;
 | ||||
|  	} | ||||
|   | ||||
| +	index = lat / g.bucket_width;
 | ||||
| +	assert(index >= 0);
 | ||||
| +
 | ||||
|  	/* Too big the jitter; put into the last bucket */ | ||||
|  	if (index >= g.bucket_size) { | ||||
| -		/* Keep the extra bit (in us) */
 | ||||
| +		/* Keep the extra bit (in bucket width multiples) */
 | ||||
|  		extra = index - g.bucket_size; | ||||
|  		if (t->overflow_sum + extra < t->overflow_sum) { | ||||
|  			/* The uint64_t even overflowed itself; bail out */ | ||||
| @@ -455,6 +460,19 @@ static void *thread_main(void *arg)
 | ||||
|  		printf("%s\n", end);                    \ | ||||
|  	} while (0) | ||||
|   | ||||
| +#define putfieldp(label, val, end) do {                        \
 | ||||
| +		printf("%12s:\t", label);                      \
 | ||||
| +		for (i = 0; i < g.n_threads; ++i)              \
 | ||||
| +			printf(" %.*f", g.precision,           \
 | ||||
| +			       (double)(val) / g.unit_per_us); \
 | ||||
| +		printf("%s\n", end);                           \
 | ||||
| +	} while (0)
 | ||||
| +
 | ||||
| +static double bucket_to_lat(int bucket)
 | ||||
| +{
 | ||||
| +	return (g.bias + (bucket + 1) * (double)g.bucket_width) / g.unit_per_us;
 | ||||
| +}
 | ||||
| +
 | ||||
|  void calculate(struct thread *t) | ||||
|  { | ||||
|  	int i, j; | ||||
| @@ -465,11 +483,11 @@ void calculate(struct thread *t)
 | ||||
|  		/* Calculate average */ | ||||
|  		sum = count = 0; | ||||
|  		for (j = 0; j < g.bucket_size; j++) { | ||||
| -			sum += 1.0 * t[i].buckets[j] * (g.bias+j+1);
 | ||||
| +			sum += t[i].buckets[j] * bucket_to_lat(j);
 | ||||
|  			count += t[i].buckets[j]; | ||||
|  		} | ||||
|  		/* Add the extra amount of huge spikes in */ | ||||
| -		sum += t->overflow_sum;
 | ||||
| +		sum += t->overflow_sum * g.bucket_width;
 | ||||
|  		t[i].average = sum / count; | ||||
|  	} | ||||
|  } | ||||
| @@ -501,16 +519,16 @@ static void write_summary(struct thread *t)
 | ||||
|  			print_dotdotdot = 0; | ||||
|  		} | ||||
|   | ||||
| -		snprintf(bucket_name, sizeof(bucket_name), "%03"PRIu64
 | ||||
| -			 " (us)", g.bias+j+1);
 | ||||
| +		snprintf(bucket_name, sizeof(bucket_name), "%03.*f (us)",
 | ||||
| +			 g.precision, bucket_to_lat(j));
 | ||||
|  		putfield(bucket_name, t[i].buckets[j], PRIu64, | ||||
|  			 (j == g.bucket_size - 1) ? " (including overflows)" : ""); | ||||
|  	} | ||||
|   | ||||
| -	putfield("Minimum", t[i].minlat, PRIu64, " (us)");
 | ||||
| +	putfieldp("Minimum", t[i].minlat, " (us)");
 | ||||
|  	putfield("Average", t[i].average, ".3lf", " (us)"); | ||||
| -	putfield("Maximum", t[i].maxlat, PRIu64, " (us)");
 | ||||
| -	putfield("Max-Min", t[i].maxlat - t[i].minlat, PRIu64, " (us)");
 | ||||
| +	putfieldp("Maximum", t[i].maxlat, " (us)");
 | ||||
| +	putfieldp("Max-Min", t[i].maxlat - t[i].minlat, " (us)");
 | ||||
|  	putfield("Duration", cycles_to_sec(&(t[i]), t[i].runtime), | ||||
|  		 ".3f", " (sec)"); | ||||
|  	printf("\n"); | ||||
| @@ -537,8 +555,8 @@ static void write_summary_json(FILE *f, void *data)
 | ||||
|  			if (t[i].buckets[j] == 0) | ||||
|  				continue; | ||||
|  			fprintf(f, "%s", comma ? ",\n" : "\n"); | ||||
| -			fprintf(f, "        \"%" PRIu64 "\": %" PRIu64,
 | ||||
| -				g.bias+j+1, t[i].buckets[j]);
 | ||||
| +			fprintf(f, "        \"%.*f\": %" PRIu64,
 | ||||
| +				g.precision, bucket_to_lat(j), t[i].buckets[j]);
 | ||||
|  			comma = 1; | ||||
|  		} | ||||
|  		if (comma) | ||||
| @@ -610,6 +628,10 @@ static void usage(int error)
 | ||||
|  	       "-v, --version          Display the version of the software.\n" | ||||
|  	       "-w, --workload         Specify a kind of workload, default is no workload\n" | ||||
|  	       "                       (options: no, memmove)\n" | ||||
| +	       "-W, --bucket-width     Interval between buckets in nanoseconds\n"
 | ||||
| +	       "                       NOTE: Widths not a multiple of 1000 cause ns-precision output\n"
 | ||||
| +	       "                       You are responsible for considering the impact of measurement\n"
 | ||||
| +	       "                       overhead at the nanosecond scale.\n"
 | ||||
|  	       "-z, --zero-omit        Don't display buckets in the output histogram if all zeros.\n" | ||||
|  	       ); | ||||
|  	exit(error); | ||||
| @@ -630,7 +652,7 @@ static int workload_select(char *name)
 | ||||
|  } | ||||
|   | ||||
|  enum option_value { | ||||
| -	OPT_BUCKETSIZE=1, OPT_CPU_LIST, OPT_CPU_MAIN_THREAD,
 | ||||
| +	OPT_BUCKETSIZE = 1, OPT_BUCKETWIDTH, OPT_CPU_LIST, OPT_CPU_MAIN_THREAD,
 | ||||
|  	OPT_DURATION, OPT_JSON, OPT_RT_PRIO, OPT_HELP, OPT_TRACE_TH, | ||||
|  	OPT_WORKLOAD, OPT_WORKLOAD_MEM, OPT_BIAS, | ||||
|  	OPT_QUIET, OPT_SINGLE_PREHEAT, OPT_ZERO_OMIT, | ||||
| @@ -644,6 +666,7 @@ static void parse_options(int argc, char *argv[])
 | ||||
|  		int option_index = 0; | ||||
|  		static struct option options[] = { | ||||
|  			{ "bucket-size", required_argument,	NULL, OPT_BUCKETSIZE }, | ||||
| +			{ "bucket-width", required_argument,	NULL, OPT_BUCKETWIDTH },
 | ||||
|  			{ "cpu-list",	required_argument,	NULL, OPT_CPU_LIST }, | ||||
|  			{ "cpu-main-thread", required_argument, NULL, OPT_CPU_MAIN_THREAD}, | ||||
|  			{ "duration",	required_argument,	NULL, OPT_DURATION }, | ||||
| @@ -660,7 +683,7 @@ static void parse_options(int argc, char *argv[])
 | ||||
|  			{ "version",	no_argument,		NULL, OPT_VERSION }, | ||||
|  			{ NULL, 0, NULL, 0 }, | ||||
|  		}; | ||||
| -		int i, c = getopt_long(argc, argv, "b:Bc:C:D:f:hm:qsw:T:vz",
 | ||||
| +		int i, c = getopt_long(argc, argv, "b:Bc:C:D:f:hm:qsw:W:T:vz",
 | ||||
|  				       options, &option_index); | ||||
|  		long ncores; | ||||
|   | ||||
| @@ -670,6 +693,7 @@ static void parse_options(int argc, char *argv[])
 | ||||
|  		switch (c) { | ||||
|  		case OPT_BUCKETSIZE: | ||||
|  		case 'b': | ||||
| +			g.bucket_size_param = true;
 | ||||
|  			g.bucket_size = strtol(optarg, NULL, 10); | ||||
|  			if (g.bucket_size > 1024 || g.bucket_size <= 4) { | ||||
|  				printf("Illegal bucket size: %s (should be: 4-1024)\n", | ||||
| @@ -677,6 +701,20 @@ static void parse_options(int argc, char *argv[])
 | ||||
|  				exit(1); | ||||
|  			} | ||||
|  			break; | ||||
| +		case OPT_BUCKETWIDTH:
 | ||||
| +		case 'W':
 | ||||
| +			g.bucket_width = strtol(optarg, NULL, 10);
 | ||||
| +			if (g.bucket_width <= 0) {
 | ||||
| +				printf("Illegal bucket width: %s\n", optarg);
 | ||||
| +				exit(1);
 | ||||
| +			}
 | ||||
| +			if (g.bucket_width % 1000) {
 | ||||
| +				g.unit_per_us = 1000;
 | ||||
| +				g.precision = 3;
 | ||||
| +			} else {
 | ||||
| +				g.bucket_width /= 1000;
 | ||||
| +			}
 | ||||
| +			break;
 | ||||
|  		case OPT_BIAS: | ||||
|  		case 'B': | ||||
|  			g.enable_bias = 1; | ||||
| @@ -776,6 +814,9 @@ static void parse_options(int argc, char *argv[])
 | ||||
|  			break; | ||||
|  		} | ||||
|  	} | ||||
| +
 | ||||
| +	if (!g.bucket_size_param && g.precision == 3 && g.bucket_width < 1000)
 | ||||
| +		g.bucket_size = BUCKET_SIZE * 1000 / g.bucket_width;
 | ||||
|  } | ||||
|   | ||||
|  void dump_globals(void) | ||||
| @@ -811,7 +852,8 @@ static void record_bias(struct thread *t)
 | ||||
|  			bias = t[i].minlat; | ||||
|  	} | ||||
|  	g.bias = bias; | ||||
| -	printf("Global bias set to %" PRId64 " (us)\n", bias);
 | ||||
| +	printf("Global bias set to %.*f (us)\n", g.precision,
 | ||||
| +	       (double)bias / g.unit_per_us);
 | ||||
|  } | ||||
|   | ||||
|  int main(int argc, char *argv[]) | ||||
| @@ -835,6 +877,8 @@ int main(int argc, char *argv[])
 | ||||
|  	g.app_name = argv[0]; | ||||
|  	g.rtprio = 0; | ||||
|  	g.bucket_size = BUCKET_SIZE; | ||||
| +	g.bucket_width = 1;
 | ||||
| +	g.unit_per_us = 1;
 | ||||
|  	g.runtime = 1; | ||||
|  	g.workload = &workload_list[WORKLOAD_DEFAULT]; | ||||
|  	g.workload_mem_size = WORKLOAD_MEM_SIZE; | ||||
| -- 
 | ||||
| 2.38.1 | ||||
| 
 | ||||
| @ -1,71 +0,0 @@ | ||||
| From d356a6ae3cbf3cf4ec7fe130bfa4a8e392b910e6 Mon Sep 17 00:00:00 2001 | ||||
| From: John Kacur <jkacur@redhat.com> | ||||
| Date: Thu, 6 Oct 2022 16:00:44 -0400 | ||||
| Subject: [PATCH] rt-tests: Remove arbitrary num of threads limits | ||||
| 
 | ||||
| Remove the arbitrary limit to the number of threads in pmqtest, | ||||
| ptsematest, sigwaittest and svsematest. | ||||
| 
 | ||||
| Signed-off-by: John Kacur <jkacur@redhat.com> | ||||
| ---
 | ||||
|  src/pmqtest/pmqtest.c         | 2 +- | ||||
|  src/ptsematest/ptsematest.c   | 2 +- | ||||
|  src/sigwaittest/sigwaittest.c | 2 +- | ||||
|  src/svsematest/svsematest.c   | 2 +- | ||||
|  4 files changed, 4 insertions(+), 4 deletions(-) | ||||
| 
 | ||||
| diff --git a/src/pmqtest/pmqtest.c b/src/pmqtest/pmqtest.c
 | ||||
| index 6ad0a92ffb5c..9e142787d8b4 100644
 | ||||
| --- a/src/pmqtest/pmqtest.c
 | ||||
| +++ b/src/pmqtest/pmqtest.c
 | ||||
| @@ -393,7 +393,7 @@ static void process_options(int argc, char *argv[])
 | ||||
|  		} | ||||
|  	} | ||||
|   | ||||
| -	if (num_threads < 0 || num_threads > 255)
 | ||||
| +	if (num_threads < 0)
 | ||||
|  		error = 1; | ||||
|   | ||||
|  	if (priority < 0 || priority > 99) | ||||
| diff --git a/src/ptsematest/ptsematest.c b/src/ptsematest/ptsematest.c
 | ||||
| index e000c3017081..a9d6c69b6449 100644
 | ||||
| --- a/src/ptsematest/ptsematest.c
 | ||||
| +++ b/src/ptsematest/ptsematest.c
 | ||||
| @@ -299,7 +299,7 @@ static void process_options(int argc, char *argv[])
 | ||||
|  		} | ||||
|  	} | ||||
|   | ||||
| -	if (num_threads < 0 || num_threads > 255)
 | ||||
| +	if (num_threads < 0)
 | ||||
|  		error = 1; | ||||
|   | ||||
|  	if (priority < 0 || priority > 99) | ||||
| diff --git a/src/sigwaittest/sigwaittest.c b/src/sigwaittest/sigwaittest.c
 | ||||
| index d0d79df940de..728176a0b385 100644
 | ||||
| --- a/src/sigwaittest/sigwaittest.c
 | ||||
| +++ b/src/sigwaittest/sigwaittest.c
 | ||||
| @@ -369,7 +369,7 @@ static void process_options(int argc, char *argv[])
 | ||||
|  		if (duration < 0) | ||||
|  			error = 1; | ||||
|   | ||||
| -		if (num_threads < 1 || num_threads > 255)
 | ||||
| +		if (num_threads < 1)
 | ||||
|  			error = 1; | ||||
|   | ||||
|  		if (priority < 0 || priority > 99) | ||||
| diff --git a/src/svsematest/svsematest.c b/src/svsematest/svsematest.c
 | ||||
| index 22ea7bcb7374..243b13738b19 100644
 | ||||
| --- a/src/svsematest/svsematest.c
 | ||||
| +++ b/src/svsematest/svsematest.c
 | ||||
| @@ -398,7 +398,7 @@ static void process_options(int argc, char *argv[])
 | ||||
|  		if (duration < 0) | ||||
|  			error = 0; | ||||
|   | ||||
| -		if (num_threads < 1 || num_threads > 255)
 | ||||
| +		if (num_threads < 1)
 | ||||
|  			error = 1; | ||||
|   | ||||
|  		if (priority < 0 || priority > 99) | ||||
| -- 
 | ||||
| 2.37.3 | ||||
| 
 | ||||
| @ -1,39 +0,0 @@ | ||||
| From a3f7cd235a4aaf7771763d3b0b27d96dd4f5f1c1 Mon Sep 17 00:00:00 2001 | ||||
| From: John Kacur <jkacur@redhat.com> | ||||
| Date: Tue, 1 Nov 2022 09:30:40 -0400 | ||||
| Subject: [PATCH 1/4] rt-tests: hackbench: Add error checking to connect and | ||||
|  getsockname | ||||
| 
 | ||||
| Add error checking around the calls connect and getsockname | ||||
| 
 | ||||
| Signed-off-by: John Kacur <jkacur@redhat.com> | ||||
| ---
 | ||||
|  src/hackbench/hackbench.c | 6 ++++-- | ||||
|  1 file changed, 4 insertions(+), 2 deletions(-) | ||||
| 
 | ||||
| diff --git a/src/hackbench/hackbench.c b/src/hackbench/hackbench.c
 | ||||
| index 18c928480103..8c6d83520e57 100644
 | ||||
| --- a/src/hackbench/hackbench.c
 | ||||
| +++ b/src/hackbench/hackbench.c
 | ||||
| @@ -130,14 +130,16 @@ static int inet_socketpair(int fds[2])
 | ||||
|   | ||||
|  	if (bind(s1, &sin, len) < 0) | ||||
|  		barf("bind"); | ||||
| -	getsockname(s1, &sin, &len);
 | ||||
| +	if (getsockname(s1, &sin, &len) < 0)
 | ||||
| +		barf("getsockname");
 | ||||
|  	if (listen(s1, 10) < 0) | ||||
|  		barf("listen"); | ||||
|  	if (ioctl(s2, FIONBIO, &ul) < 0) | ||||
|  		barf("ioctl"); | ||||
|  	if (ioctl(s1, FIONBIO, &ul) < 0) | ||||
|  		barf("ioctl"); | ||||
| -	connect(s2, &sin, len);
 | ||||
| +	if (connect(s2, &sin, len) < 0)
 | ||||
| +		barf("connect");
 | ||||
|  	if ((fds[0] = accept(s1, &sin, &len)) < 0) | ||||
|  		barf("accept"); | ||||
|  	ul = 0; | ||||
| -- 
 | ||||
| 2.38.1 | ||||
| 
 | ||||
| @ -1,59 +0,0 @@ | ||||
| From fb702d9903b7f8b54a7bd51fcbf5f12ce6bc9540 Mon Sep 17 00:00:00 2001 | ||||
| From: John Kacur <jkacur@redhat.com> | ||||
| Date: Tue, 1 Nov 2022 09:46:01 -0400 | ||||
| Subject: [PATCH 2/4] rt-tests: hackbench: Fix compile comparison of different | ||||
|  signed ints | ||||
| 
 | ||||
| Fix compile warnings about comparisons of integers of different | ||||
| signedness. | ||||
| 
 | ||||
| Signed-off-by: John Kacur <jkacur@redhat.com> | ||||
| ---
 | ||||
|  src/hackbench/hackbench.c | 10 ++++++---- | ||||
|  1 file changed, 6 insertions(+), 4 deletions(-) | ||||
| 
 | ||||
| diff --git a/src/hackbench/hackbench.c b/src/hackbench/hackbench.c
 | ||||
| index 8c6d83520e57..dda7690b79a0 100644
 | ||||
| --- a/src/hackbench/hackbench.c
 | ||||
| +++ b/src/hackbench/hackbench.c
 | ||||
| @@ -200,7 +200,8 @@ static void *sender(struct sender_context *ctx)
 | ||||
|  	/* Now pump to every receiver. */ | ||||
|  	for (i = 0; i < loops; i++) { | ||||
|  		for (j = 0; j < ctx->num_fds; j++) { | ||||
| -			int ret, done = 0;
 | ||||
| +			int ret;
 | ||||
| +			size_t done = 0;
 | ||||
|   | ||||
|  again: | ||||
|  			ret = write(ctx->out_fds[j], data + done, sizeof(data)-done); | ||||
| @@ -231,7 +232,8 @@ static void *receiver(struct receiver_context* ctx)
 | ||||
|  	/* Receive them all */ | ||||
|  	for (i = 0; i < ctx->num_packets; i++) { | ||||
|  		char data[datasize]; | ||||
| -		int ret, done = 0;
 | ||||
| +		int ret;
 | ||||
| +		size_t done = 0;
 | ||||
|   | ||||
|  again: | ||||
|  		ret = read(ctx->in_fds[0], data + done, datasize - done); | ||||
| @@ -289,7 +291,7 @@ static int create_worker(childinfo_t *child, void *ctx, void *(*func)(void *))
 | ||||
|   | ||||
|  void signal_workers(childinfo_t *children, unsigned int num_children) | ||||
|  { | ||||
| -	int i;
 | ||||
| +	unsigned int i;
 | ||||
|  	printf("signaling %d worker threads to terminate\n", num_children); | ||||
|  	for (i=0; i < num_children; i++) { | ||||
|  		kill(children[i].pid, SIGTERM); | ||||
| @@ -517,7 +519,7 @@ int main(int argc, char *argv[])
 | ||||
|  	if (setjmp(jmpbuf) == 0) { | ||||
|  		total_children = 0; | ||||
|  		for (i = 0; i < num_groups; i++) { | ||||
| -			int c = group(child_tab, total_children, num_fds, readyfds[1], wakefds[0]);
 | ||||
| +			unsigned int c = group(child_tab, total_children, num_fds, readyfds[1], wakefds[0]);
 | ||||
|  			if( c != (num_fds*2) ) { | ||||
|  				fprintf(stderr, "%i children started.  Expected %i\n", c, num_fds*2); | ||||
|  				reap_workers(child_tab, total_children + c, 1); | ||||
| -- 
 | ||||
| 2.38.1 | ||||
| 
 | ||||
| @ -1,30 +0,0 @@ | ||||
| From 4164006a834b93995fb3535508fdf18bff92df7d Mon Sep 17 00:00:00 2001 | ||||
| From: John Kacur <jkacur@redhat.com> | ||||
| Date: Tue, 1 Nov 2022 09:50:03 -0400 | ||||
| Subject: [PATCH 3/4] rt-tests: hackbench: Fix compile warning about fall | ||||
|  through | ||||
| 
 | ||||
| print_usage_exit(0) never returns, but the compiler doesn't understand | ||||
| this. In any case it is not harmful to add a break after this statement. | ||||
| Do so to keep the unhelpful compiler warning from triggering. | ||||
| 
 | ||||
| Signed-off-by: John Kacur <jkacur@redhat.com> | ||||
| ---
 | ||||
|  src/hackbench/hackbench.c | 1 + | ||||
|  1 file changed, 1 insertion(+) | ||||
| 
 | ||||
| diff --git a/src/hackbench/hackbench.c b/src/hackbench/hackbench.c
 | ||||
| index dda7690b79a0..69dd5f087fb6 100644
 | ||||
| --- a/src/hackbench/hackbench.c
 | ||||
| +++ b/src/hackbench/hackbench.c
 | ||||
| @@ -444,6 +444,7 @@ static void process_options(int argc, char *argv[])
 | ||||
|  			break; | ||||
|  		case 'h': | ||||
|  			print_usage_exit(0); | ||||
| +			break;
 | ||||
|  		case 'l': | ||||
|  			if (!(argv[optind] && (loops = atoi(optarg)) > 0)) { | ||||
|  				fprintf(stderr, "%s: --loops|-l requires an integer > 0\n", argv[0]); | ||||
| -- 
 | ||||
| 2.38.1 | ||||
| 
 | ||||
| @ -1,34 +0,0 @@ | ||||
| From 8c7532b710390882ffd7e96d50e75fce99a8249f Mon Sep 17 00:00:00 2001 | ||||
| From: John Kacur <jkacur@redhat.com> | ||||
| Date: Fri, 11 Nov 2022 14:48:15 -0500 | ||||
| Subject: [PATCH 3/3] rt-tests: hwlatdetect: Fix incorrect comment about | ||||
|  testduration | ||||
| 
 | ||||
| At some point | ||||
| self.testduration = 10 | ||||
| was changed to | ||||
| self.testduration = 30 | ||||
| 
 | ||||
| but retained the comment, "ten seconds" | ||||
| 
 | ||||
| Just change the comment to say, "in seconds" so it's clear what unit | ||||
| we are talking about. | ||||
| 
 | ||||
| Signed-off-by: John Kacur <jkacur@redhat.com> | ||||
| 
 | ||||
| diff --git a/src/hwlatdetect/hwlatdetect.py b/src/hwlatdetect/hwlatdetect.py
 | ||||
| index c5b3a689dcd1..68df58f7e2d0 100755
 | ||||
| --- a/src/hwlatdetect/hwlatdetect.py
 | ||||
| +++ b/src/hwlatdetect/hwlatdetect.py
 | ||||
| @@ -130,7 +130,7 @@ class Detector:
 | ||||
|          if not self.debugfs.mount(): | ||||
|              raise RuntimeError("failed to mount debugfs") | ||||
|          self.samples = [] | ||||
| -        self.testduration = 30  # ten seconds
 | ||||
| +        self.testduration = 30  # in seconds
 | ||||
|          self.have_msr = False | ||||
|          self.initsmi = [] | ||||
|          if os.path.exists('/usr/sbin/rdmsr'): | ||||
| -- 
 | ||||
| 2.31.1 | ||||
| 
 | ||||
| @ -1,34 +0,0 @@ | ||||
| From 1eaa7feae3225ae82d00d2e1f02986e34c31a38d Mon Sep 17 00:00:00 2001 | ||||
| From: Leah Leshchinsky <lleshchi@redhat.com> | ||||
| Date: Thu, 10 Nov 2022 10:35:27 -0500 | ||||
| Subject: [PATCH 2/3] rt-tests: hwlatdetect: Update to integer division | ||||
| 
 | ||||
| In Python 3, "/" is a float division operator, as opposed to Python 2, | ||||
| which defaults to integer division. This results in an error when | ||||
| calculating width, which assumes an integer. | ||||
| 
 | ||||
| Update width division to integer division with the "//" operator. | ||||
| 
 | ||||
| Signed-off-by: Leah Leshchinsky <lleshchi@redhat.com> | ||||
| Signed-off-by: John Kacur <jkacur@redhat.com> | ||||
| 
 | ||||
| diff --git a/src/hwlatdetect/hwlatdetect.py b/src/hwlatdetect/hwlatdetect.py
 | ||||
| index 1efbe7a60059..c5b3a689dcd1 100755
 | ||||
| --- a/src/hwlatdetect/hwlatdetect.py
 | ||||
| +++ b/src/hwlatdetect/hwlatdetect.py
 | ||||
| @@ -454,9 +454,10 @@ if __name__ == '__main__':
 | ||||
|   | ||||
|      if args.window: | ||||
|          w = microseconds(args.window) | ||||
| +        width = w//2
 | ||||
|          if w < int(detect.get("width")): | ||||
| -            debug(f"shrinking width to {w//2} for new window of {w}")
 | ||||
| -            detect.set("width", w/2)
 | ||||
| +            debug(f"shrinking width to {width} for new window of {w}")
 | ||||
| +            detect.set("width", width)
 | ||||
|          debug(f"window parameter = {w}") | ||||
|          detect.set("window", w) | ||||
|          debug(f"window for sampling set to {w}us") | ||||
| -- 
 | ||||
| 2.31.1 | ||||
| 
 | ||||
| @ -1,225 +0,0 @@ | ||||
| From d9acad79fa157f90522b3dc2b745bbb3b72fef1d Mon Sep 17 00:00:00 2001 | ||||
| From: Leah Leshchinsky <lleshchi@redhat.com> | ||||
| Date: Fri, 11 Nov 2022 13:49:33 -0500 | ||||
| Subject: [PATCH 1/3] rt-tests: hwlatdetect.py Covert to f-strings | ||||
| 
 | ||||
| Add f-strings where applicable for readability. | ||||
| 
 | ||||
| Signed-off-by: Leah Leshchinsky <lleshchi@redhat.com> | ||||
| Signed-off-by: John Kacur <jkacur@redhat.com> | ||||
| 
 | ||||
| diff --git a/src/hwlatdetect/hwlatdetect.py b/src/hwlatdetect/hwlatdetect.py
 | ||||
| index 9ef50f862127..1efbe7a60059 100755
 | ||||
| --- a/src/hwlatdetect/hwlatdetect.py
 | ||||
| +++ b/src/hwlatdetect/hwlatdetect.py
 | ||||
| @@ -59,7 +59,7 @@ class DebugFS:
 | ||||
|          if self.premounted or self.mounted: | ||||
|              debug("not mounting debugfs") | ||||
|              return True | ||||
| -        debug("mounting debugfs at %s" % path)
 | ||||
| +        debug(f"mounting debugfs at {path}")
 | ||||
|          self.mountpoint = path | ||||
|          cmd = ['/bin/mount', '-t', 'debugfs', 'none', path] | ||||
|          self.mounted = (subprocess.call(cmd) == 0) | ||||
| @@ -90,7 +90,7 @@ class DebugFS:
 | ||||
|              try: | ||||
|                  val = f.readline() | ||||
|              except OSError as e: | ||||
| -                print("errno: %s" % e)
 | ||||
| +                print(f"errno: {e}")
 | ||||
|                  if e.errno == errno.EAGAIN: | ||||
|                      val = None | ||||
|                  else: | ||||
| @@ -192,18 +192,18 @@ class Detector:
 | ||||
|          count = 0 | ||||
|          threshold = int(self.get("threshold")) | ||||
|          self.c_states_off() | ||||
| -        debug("enabling detector module (threshold: %d)" % threshold)
 | ||||
| +        debug(f"enabling detector module (threshold: {threshold})")
 | ||||
|          self.set("enable", 1) | ||||
|          while self.get("enable") == 0: | ||||
|              debug("still disabled, retrying in a bit") | ||||
|              count += 1 | ||||
|              time.sleep(0.1) | ||||
| -            debug("retrying enable of detector module (%d)" % count)
 | ||||
| +            debug(f"retrying enable of detector module ({count})")
 | ||||
|              self.set("enable", 1) | ||||
|          if self.get("threshold") != threshold: | ||||
|              debug("start: threshold reset by start, fixing") | ||||
|              self.set("threshold", threshold) | ||||
| -        debug("detector module enabled (threshold: %d)" % int(self.get("threshold")))
 | ||||
| +        debug(f"detector module enabled (threshold: {int(self.get('threshold'))})")
 | ||||
|   | ||||
|      def stop(self): | ||||
|          """ disable the detector """ | ||||
| @@ -214,7 +214,7 @@ class Detector:
 | ||||
|              debug("still enabled, retrying in a bit") | ||||
|              count += 1 | ||||
|              time.sleep(0.1) | ||||
| -            debug("retrying disable of detector module(%d)" % count)
 | ||||
| +            debug(f"retrying disable of detector module({count})")
 | ||||
|              self.set("enable", 0) | ||||
|          self.c_states_on() | ||||
|          debug("detector module disabled") | ||||
| @@ -248,7 +248,7 @@ class Tracer(Detector):
 | ||||
|              self.outer = int(o) | ||||
|   | ||||
|          def __str__(self): | ||||
| -            return "ts: %s, inner:%d, outer:%d" % (self.timestamp, self.inner, self.outer)
 | ||||
| +            return f"ts: {self.timestamp}, inner:{self.inner}, outer:{self.outer}"
 | ||||
|   | ||||
|          def display(self): | ||||
|              """ convert object to string and print """ | ||||
| @@ -322,8 +322,8 @@ class Tracer(Detector):
 | ||||
|          if output: | ||||
|              with open(output, "w") as f: | ||||
|                  for s in self.samples: | ||||
| -                    f.write("%s\n" % str(s))
 | ||||
| -                print("report saved to %s (%d samples)" % (output, len(self.samples)))
 | ||||
| +                    f.write(f"{s}\n")
 | ||||
| +                print(f"report saved to {output} ({len(self.samples)} samples)")
 | ||||
|   | ||||
|      def display(self): | ||||
|          for s in self.samples: | ||||
| @@ -341,7 +341,7 @@ def seconds(sval):
 | ||||
|      if sval.isdigit(): | ||||
|          return int(sval) | ||||
|      if sval[-2].isalpha(): | ||||
| -        raise RuntimeError("illegal suffix for seconds: '%s'" % sval[-2:-1])
 | ||||
| +        raise RuntimeError(f"illegal suffix for seconds: '{sval[-2:-1]}'")
 | ||||
|      if sval[-1:] == 's': | ||||
|          return int(sval[0:-1]) | ||||
|      if sval[-1:] == 'm': | ||||
| @@ -352,7 +352,7 @@ def seconds(sval):
 | ||||
|          return int(sval[0:-1]) * 86400 | ||||
|      if sval[-1:] == 'w': | ||||
|          return int(sval[0:-1]) * 86400 * 7 | ||||
| -    raise RuntimeError("invalid input for seconds: '%s'" % sval)
 | ||||
| +    raise RuntimeError(f"invalid input for seconds: '{sval}'")
 | ||||
|   | ||||
|   | ||||
|  def milliseconds(sval): | ||||
| @@ -367,7 +367,7 @@ def milliseconds(sval):
 | ||||
|          return int(sval[0:-1]) * 1000 * 60 | ||||
|      if sval[-1] == 'h': | ||||
|          return int(sval[0:-1]) * 1000 * 60 * 60 | ||||
| -    raise RuntimeError("invalid input for milliseconds: %s" % sval)
 | ||||
| +    raise RuntimeError(f"invalid input for milliseconds: {sval}")
 | ||||
|   | ||||
|   | ||||
|  def microseconds(sval): | ||||
| @@ -380,7 +380,7 @@ def microseconds(sval):
 | ||||
|          return int(sval[0:-2]) | ||||
|      if sval[-1:] == 's': | ||||
|          return int(sval[0:-1]) * 1000 * 1000 | ||||
| -    raise RuntimeError("invalid input for microseconds: '%s'" % sval)
 | ||||
| +    raise RuntimeError(f"invalid input for microseconds: '{sval}'")
 | ||||
|   | ||||
|   | ||||
|  if __name__ == '__main__': | ||||
| @@ -444,37 +444,37 @@ if __name__ == '__main__':
 | ||||
|      if args.threshold: | ||||
|          t = microseconds(args.threshold) | ||||
|          detect.set("threshold", t) | ||||
| -        debug("threshold set to %dus" % t)
 | ||||
| +        debug(f"threshold set to {t}us")
 | ||||
|   | ||||
|      if args.hardlimit: | ||||
|          hardlimit = microseconds(args.hardlimit) | ||||
|      else: | ||||
|          hardlimit = int(detect.get("threshold")) | ||||
| -    debug("hardlimit set to %dus" % hardlimit)
 | ||||
| +    debug(f"hardlimit set to {hardlimit}us")
 | ||||
|   | ||||
|      if args.window: | ||||
|          w = microseconds(args.window) | ||||
|          if w < int(detect.get("width")): | ||||
| -            debug("shrinking width to %d for new window of %d" % (w/2, w))
 | ||||
| +            debug(f"shrinking width to {w//2} for new window of {w}")
 | ||||
|              detect.set("width", w/2) | ||||
| -        debug("window parameter = %d" % w)
 | ||||
| +        debug(f"window parameter = {w}")
 | ||||
|          detect.set("window", w) | ||||
| -        debug("window for sampling set to %dus" % w)
 | ||||
| +        debug(f"window for sampling set to {w}us")
 | ||||
|   | ||||
|      if args.width: | ||||
|          w = microseconds(args.width) | ||||
|          if w > int(detect.get("window")): | ||||
| -            debug("widening window to %d for new width of %d" % (w*2, w))
 | ||||
| +            debug(f"widening window to {w*2} for new width of {w}")
 | ||||
|              detect.set("window", w*2) | ||||
| -        debug("width parameter = %d" % w)
 | ||||
| +        debug(f"width parameter = {w}")
 | ||||
|          detect.set("width", w) | ||||
| -        debug("sample width set to %dus" % w)
 | ||||
| +        debug(f"sample width set to {w}us")
 | ||||
|   | ||||
|      if args.duration: | ||||
|          detect.testduration = seconds(args.duration) | ||||
|      else: | ||||
|          detect.testduration = 120  # 2 minutes | ||||
| -    debug("test duration is %ds" % detect.testduration)
 | ||||
| +    debug(f"test duration is {detect.testduration}s")
 | ||||
|   | ||||
|      if args.watch: | ||||
|          watch = True | ||||
| @@ -491,18 +491,18 @@ if __name__ == '__main__':
 | ||||
|                  l, r = map(int, [c, c]) | ||||
|              for i in range(l, r + 1): | ||||
|                  cpumask |= (1 << i) | ||||
| -        debug("set tracing_cpumask to %x" % cpumask)
 | ||||
| -        detect.set("cpumask", "%x" % cpumask)
 | ||||
| +        debug(f"set tracing_cpumask to {cpumask:x}")
 | ||||
| +        detect.set("cpumask", f"{cpumask:x}")
 | ||||
|   | ||||
| -    info("hwlatdetect:  test duration %d seconds" % detect.testduration)
 | ||||
| -    info("   detector: %s" % detect.type)
 | ||||
| +    info(f"hwlatdetect:  test duration {detect.testduration} seconds")
 | ||||
| +    info(f"   detector: {detect.type}")
 | ||||
|      info("   parameters:") | ||||
| -    info("        CPU list:          %s"   % args.cpulist)
 | ||||
| -    info("        Latency threshold: %dus" % int(detect.get("threshold")))
 | ||||
| -    info("        Sample window:     %dus" % int(detect.get("window")))
 | ||||
| -    info("        Sample width:      %dus" % int(detect.get("width")))
 | ||||
| -    info("     Non-sampling period:  %dus" % (int(detect.get("window")) - int(detect.get("width"))))
 | ||||
| -    info("        Output File:       %s" % reportfile)
 | ||||
| +    info(f"        CPU list:          {args.cpulist}")
 | ||||
| +    info(f"        Latency threshold: {int(detect.get('threshold'))}us")
 | ||||
| +    info(f"        Sample window:      {int(detect.get('window'))}us")
 | ||||
| +    info(f"        Sample width:      {int(detect.get('width'))}us")
 | ||||
| +    info(f"     Non-sampling period:  {(int(detect.get('window')) - int(detect.get('width')))}us")
 | ||||
| +    info(f"        Output File:       {reportfile}")
 | ||||
|      info("\nStarting test") | ||||
|   | ||||
|      detect.detect() | ||||
| @@ -513,12 +513,12 @@ if __name__ == '__main__':
 | ||||
|      if max_latency == 0: | ||||
|          info("Max Latency: Below threshold") | ||||
|      else: | ||||
| -        info("Max Latency: %dus" % max_latency)
 | ||||
| +        info(f"Max Latency: {int(max_latency)}us")
 | ||||
|   | ||||
| -    info("Samples recorded: %d" % len(detect.samples))
 | ||||
| +    info(f"Samples recorded: {len(detect.samples)}")
 | ||||
|   | ||||
|      exceeding = detect.get("count") | ||||
| -    info("Samples exceeding threshold: %d" % exceeding)
 | ||||
| +    info(f"Samples exceeding threshold: {exceeding}")
 | ||||
|   | ||||
|      if detect.have_msr: | ||||
|          finishsmi = detect.getsmicounts() | ||||
| @@ -527,8 +527,8 @@ if __name__ == '__main__':
 | ||||
|              if count > detect.initsmi[i]: | ||||
|                  smis = count - detect.initsmi[i] | ||||
|                  total_smis += smis | ||||
| -                print("%d SMIs occured on cpu %d" % (smis, i))
 | ||||
| -        info("SMIs during run: %d" % total_smis)
 | ||||
| +                print(f"{smis} SMIs occured on cpu {i}")
 | ||||
| +        info(f"SMIs during run: {total_smis}")
 | ||||
|   | ||||
|      maxlatency = int(detect.get("max")) | ||||
|   | ||||
| -- 
 | ||||
| 2.31.1 | ||||
| 
 | ||||
| @ -5,8 +5,8 @@ Name: rt-tests | ||||
| # BuildRequires: numactl-devel | ||||
| # Numa argument to make:  NUMA=1 | ||||
| # | ||||
| Version: 2.4 | ||||
| Release: 5%{?dist} | ||||
| Version: 2.5 | ||||
| Release: 1%{?dist} | ||||
| License: GPLv2 | ||||
| Group: Development/Tools | ||||
| URL: git://git.kernel.org/pub/scm/utils/rt-tests/rt-tests.git | ||||
| @ -21,14 +21,6 @@ BuildRequires: python3-devel | ||||
| Requires: bash bc | ||||
| 
 | ||||
| #Patches | ||||
| Patch1: rt-tests-Remove-arbitrary-num-of-threads-limits.patch | ||||
| Patch2: rt-tests-hackbench-Add-error-checking-to-connect-and.patch | ||||
| Patch3: rt-tests-hackbench-Fix-compile-comparison-of-differe.patch | ||||
| Patch4: rt-tests-hackbench-Fix-compile-warning-about-fall-th.patch | ||||
| Patch5: rt-tests-hwlatdetect.py-Covert-to-f-strings.patch | ||||
| Patch6: rt-tests-hwlatdetect-Update-to-integer-division.patch | ||||
| Patch7: rt-tests-hwlatdetect-Fix-incorrect-comment-about-tes.patch | ||||
| Patch8: oslat-Add-command-line-option-for-bucket-width.patch | ||||
| 
 | ||||
| %description | ||||
| rt-tests is a set of programs that test and measure various components of | ||||
| @ -37,14 +29,6 @@ latency. It also tests the functioning of priority-inheritance mutexes. | ||||
| 
 | ||||
| %prep | ||||
| %setup -q -n %{name}-%{version} | ||||
| %patch1 -p1 | ||||
| %patch2 -p1 | ||||
| %patch3 -p1 | ||||
| %patch4 -p1 | ||||
| %patch5 -p1 | ||||
| %patch6 -p1 | ||||
| %patch7 -p1 | ||||
| %patch8 -p1 | ||||
| 
 | ||||
| %build | ||||
| %set_build_flags | ||||
| @ -99,6 +83,10 @@ rm -rf ${build_root} | ||||
| %{_mandir}/man8/determine_maximum_mpps.8.* | ||||
| 
 | ||||
| %changelog | ||||
| * Tue Jan 24 2023 John Kacur <jkacur@redhat.com> - 2.5-1 | ||||
| - Update to latest upstream rt-tests v2.5 | ||||
| Resolves: rhbz#2162780 | ||||
| 
 | ||||
| * Wed Dec 14 2022 Crystal Wood <swood@redhat.com> - 2.4-5 | ||||
| - oslat: Add command line option for bucket width | ||||
| Resolves: rhbz#2122374 | ||||
|  | ||||
							
								
								
									
										2
									
								
								sources
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								sources
									
									
									
									
									
								
							| @ -1 +1 @@ | ||||
| SHA512 (rt-tests-2.4.tar.xz) = ef72a55ed85c4d6717cef4573d684ea87f6e73f9189b2a2b8e9b69eaf6ea59933522769c9ba9c131ef9d0546645152e65f072427c53fcc0e386bd297fac3a6e1 | ||||
| SHA512 (rt-tests-2.5.tar.xz) = 4341716aa1a307aeb9f11e922da814ff6f1e16f7a4b9ba05bcc8a3972f411f4b4f8212ffe58bdaa025e164d1ddcfcc199fdb2b53bfe051d58cfd898a751dcc25 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user