Files
s390-tools/cpumf/chcpumf.c
Thomas Richter ce02dd7167 cpumf/chcpumf.c: Print verbose message on success
Print verbose message on success only.

Reviewed-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-05-29 15:18:31 +02:00

215 lines
4.6 KiB
C

/*
* chcpumf - Change CPU Measurement Facility Characteristics
*
* Copyright IBM Corp. 2020
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include "lib/util_opt.h"
#include "lib/util_prg.h"
#include "lib/util_base.h"
#include "defines.h"
static int verbose;
static unsigned long min_sdb, max_sdb;
static struct util_opt opt_vec[] = {
UTIL_OPT_SECTION("OPTIONS"),
{
.option = { "min", required_argument, NULL, 'm' },
.argument = "num_sdb",
.desc = "Specifies the initial size of the sampling buffer.\n"
"A sample-data-block (SDB) consumes about 4 kilobytes.",
},
{
.option = { "max", required_argument, NULL, 'x' },
.argument = "num_sdb",
.desc = "Specifies the maximum size of the sampling buffer.\n"
"A sample-data-block (SDB) consumes about 4 kilobytes.",
},
{
.option = { "verbose", no_argument, NULL, 'V' },
.desc = "Verbose, display new sample-data-block values.",
},
UTIL_OPT_HELP,
UTIL_OPT_VERSION,
UTIL_OPT_END
};
static const struct util_prg prg = {
.desc = "Change CPU Measurement facility charactertics",
.copyright_vec = {
{
.owner = "IBM Corp.",
.pub_first = 2020,
.pub_last = 2020,
},
UTIL_PRG_COPYRIGHT_END
}
};
/* Parse tool parameters. Fill in global variables keep_case, buffersize and
* command according to parameters. Return VMCP_OK on success, VMCP_OPT
* in case of parameter errors. In case of --help or --version, print
* respective text to stdout and exit. */
static long parse_buffersize(char *string)
{
char *suffix;
long bytes;
bytes = strtol(string, &suffix, 10);
if (strlen(suffix) > 1)
return -1;
switch (*suffix) {
case 'k':
case 'K':
bytes *= 1024;
break;
case 'm':
case 'M':
bytes *= 1048576;
break;
case '\0':
break;
default:
return 0;
}
return bytes;
}
static int read_sfb(unsigned long *min, unsigned long *max)
{
int rc = EXIT_SUCCESS;
FILE *fp;
fp = fopen(PERF_SFB_SIZE, "r");
if (fp == NULL) {
linux_error(PERF_SFB_SIZE);
return EXIT_FAILURE;
}
if (fscanf(fp, "%ld,%ld", min, max) != 2) {
fprintf(stderr, "Error: Can not parse file " PERF_SFB_SIZE);
rc = EXIT_FAILURE;
}
fclose(fp);
return rc;
}
static int write_sfb(unsigned long min, unsigned long max)
{
int rc = EXIT_SUCCESS;
char text[64];
size_t len;
FILE *fp;
fp = fopen(PERF_SFB_SIZE, "w");
if (fp == NULL) {
linux_error(PERF_SFB_SIZE);
return EXIT_FAILURE;
}
snprintf(text, sizeof text, "%ld,%ld", min, max);
len = strlen(text) + 1;
if (fwrite(text, 1, len, fp) != len) {
linux_error(PERF_SFB_SIZE);
rc = EXIT_FAILURE;
}
if (fclose(fp)) {
linux_error(PERF_SFB_SIZE);
rc = EXIT_FAILURE;
}
if (verbose && rc != EXIT_FAILURE)
fprintf(stderr, "Sampling buffer sizes:\n"
" Minimum:%7ld sample-data-blocks\n"
" Maximum:%7ld sample-data-blocks\n",
min, max);
return rc;
}
static int parse_args(int argc, char **argv)
{
int opt, action = 0;
long new;
while ((opt = util_opt_getopt_long(argc, argv)) != -1) {
switch (opt) {
case 'h':
util_prg_print_help();
util_opt_print_help();
exit(EXIT_SUCCESS);
case 'v':
util_prg_print_version();
exit(EXIT_SUCCESS);
case 'x':
new = parse_buffersize(optarg);
if (new < 1) {
fprintf(stderr, "The specified number(s)"
" are not valid\n");
exit(EXIT_FAILURE);
}
max_sdb = new;
action = 1;
break;
case 'm':
new = parse_buffersize(optarg);
if (new < 1) {
fprintf(stderr, "The specified number(s)"
" are not valid\n");
exit(EXIT_FAILURE);
}
min_sdb = new;
action = 1;
break;
case 'V':
verbose = 1;
break;
case '?':
fprintf(stderr, "One or more options are not valid\n");
fprintf(stderr, "Try 'chcpumf --help' for more"
" information\n");
exit(EXIT_FAILURE);
}
}
if (!action) {
fprintf(stderr, "You must specify a valid option\n");
exit(EXIT_FAILURE);
}
return action;
}
int main(int argc, char **argv)
{
int ret = EXIT_FAILURE;
struct stat sbuf;
util_prg_init(&prg);
util_opt_init(opt_vec, NULL);
if (stat(PERF_PATH PERF_SF, &sbuf) != 0) {
fprintf(stderr,
"No CPU-measurement sampling facility detected\n");
return ret;
}
if (read_sfb(&min_sdb, &max_sdb))
return ret;
/* Overwrite min_sdb and/or max_sdb */
parse_args(argc, argv);
if (min_sdb >= max_sdb) {
fprintf(stderr, "The specified maximum must be greater "
"than the minimum\n");
return ret;
}
return write_sfb(min_sdb, max_sdb);
}