/* * chcpumf - Change CPU Measurement Facility Characteristics * * Copyright IBM Corp. 2020, 2022 * * 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 #include #include #include #include #include #include #include #include "lib/libcpumf.h" #include "lib/util_opt.h" #include "lib/util_path.h" #include "lib/util_prg.h" #include "chcpumf_cli.h" static unsigned int verbose; static unsigned long min_sdb, max_sdb; 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 } }; 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 write_sfb(unsigned int min, unsigned int max) { int rc = EXIT_SUCCESS; char text[64], *path; size_t len; FILE *fp; path = util_path_sysfs(S390_CPUMSF_BUFFERSZ); fp = fopen(path, "w"); if (!fp) err(EXIT_FAILURE, "%s", path); snprintf(text, sizeof(text), "%u,%u", min, max); len = strlen(text) + 1; if (fwrite(text, 1, len, fp) != len) { warn("%s", path); rc = EXIT_FAILURE; } if (fclose(fp)) { warn("%s", path); rc = EXIT_FAILURE; } if (verbose && rc != EXIT_FAILURE) warnx("Sampling buffer sizes:\n" " Minimum:%7d sample-data-blocks\n" " Maximum:%7d sample-data-blocks\n", min, max); free(path); 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) errx(EXIT_FAILURE, "The specified number(s) are not valid"); max_sdb = new; action = 1; break; case 'm': new = parse_buffersize(optarg); if (new < 1) errx(EXIT_FAILURE, "The specified number(s) are not valid"); min_sdb = new; action = 1; break; case 'V': verbose = 1; break; default: util_opt_print_parse_error(opt, argv); exit(EXIT_FAILURE); } } if (!action) errx(EXIT_FAILURE, "You must specify a valid option"); return action; } int main(int argc, char **argv) { unsigned long my_min, my_max; util_prg_init(&prg); util_opt_init(chcpumf_opt_vec, NULL); parse_args(argc, argv); if (geteuid()) errx(EXIT_FAILURE, "Must run as root"); if (!libcpumf_have_sfb()) errx(EXIT_FAILURE, "No CPU-measurement sampling facility detected"); libcpumf_sfb_info(&my_min, &my_max); if (!min_sdb) min_sdb = my_min; if (!max_sdb) max_sdb = my_max; return write_sfb(min_sdb, max_sdb); }