Files
s390-tools/zconf/scm/lsscm.c
Michael Holzheu b627b8d8e1 Initial s390-tools-2.0.0 import
This commit is based on the s390-tools-1.39.0 version.

Changes on top of s390-tools-1.39.0:

 - Add MIT license to all source files
 - Add LICENSE file
 - Transform REAMDE to README.md (markdown)
 - Add AUTHORS.md file
 - Add CONTRIBUTING.md file
 - Move changelog from README to CHANGELOG.md file

Reviewed-by: Stefan Haberland <sth@linux.vnet.ibm.com>
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
2017-08-21 10:55:40 +02:00

193 lines
4.6 KiB
C

/*
* lsscm - Show information about Storage Class Memory Increments
*
* Copyright IBM Corp. 2016, 2017
*
* 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 <err.h>
#include "lib/util_base.h"
#include "lib/util_file.h"
#include "lib/util_opt.h"
#include "lib/util_panic.h"
#include "lib/util_path.h"
#include "lib/util_prg.h"
#include "lib/util_rec.h"
#include "lib/util_scandir.h"
#include "lib/zt_common.h"
/*
* Program configuration
*/
const struct util_prg prg = {
.desc = "List information about available Storage Class Memory Increments.",
.copyright_vec = {
{
.owner = "IBM Corp.",
.pub_first = 2016,
.pub_last = 2017,
},
UTIL_PRG_COPYRIGHT_END
}
};
/*
* Configuration of command line options
*/
static struct util_opt opt_vec[] = {
UTIL_OPT_HELP,
UTIL_OPT_VERSION,
UTIL_OPT_END
};
/**
* Print all attributes of one device
*
* @param[in] name Block device name, or NULL if scm_block.ko is not loaed
* @param[in] data Address of scm device
* @param[in] rec Container for tabular output
*/
static void print_scm_attrs(const char *name, const char *addr,
struct util_rec *rec)
{
long value;
char *path;
path = util_path_sysfs("bus/scm/devices/%s", addr);
util_rec_set(rec, "addr", addr);
if (name) {
util_rec_set(rec, "name", name);
if (util_file_read_l(&value, 10, "%s/block/%s/size", path, name))
goto out_free_path;
util_rec_set(rec, "size", "%ldMB", value * 512 / (1024 * 1024));
} else {
util_rec_set(rec, "name", "N/A");
util_rec_set(rec, "size", "%ldMB", 0);
}
if (util_file_read_l(&value, 10, "%s/rank", path))
goto out_free_path;
util_rec_set(rec, "rank", "%ld", value);
if (util_file_read_l(&value, 10, "%s/data_state", path))
goto out_free_path;
util_rec_set(rec, "dstate", "%ld", value);
if (util_file_read_l(&value, 10, "%s/oper_state", path))
goto out_free_path;
util_rec_set(rec, "ostate", "%ld", value);
if (util_file_read_l(&value, 10, "%s/persistence", path))
goto out_free_path;
util_rec_set(rec, "pers", "%ld", value);
if (util_file_read_l(&value, 10, "%s/res_id", path))
goto out_free_path;
util_rec_set(rec, "resid", "%ld", value);
util_rec_print(rec);
out_free_path:
free(path);
}
/**
* Print one scm block device
*
* @param[in] addr Address
* @param[in] rec Container for tabular output
*/
void print_scm(const char *addr, struct util_rec *rec)
{
struct dirent **de_vec;
char *path;
int count;
path = util_path_sysfs("bus/scm/devices/%s/block", addr);
/* Match scma..scmzz */
count = util_scandir(&de_vec, NULL, path, "^scm[[:lower:]]{1,2}$");
if (count < 0) {
/* If scm_block not loaded */
print_scm_attrs(NULL, addr, rec);
} else {
util_assert(count == 1, "We expect only one block device\n");
print_scm_attrs(de_vec[0]->d_name, addr, rec);
util_scandir_free(de_vec, count);
}
free(path);
}
/*
* Look for used scm increments
*/
static void cmd_lsscm(void)
{
struct dirent **de_vec;
struct util_rec *rec;
int i, count;
char *path;
rec = util_rec_new_wide("-");
util_rec_def(rec, "addr", UTIL_REC_ALIGN_LEFT, 16, "SCM Increment");
util_rec_def(rec, "size", UTIL_REC_ALIGN_LEFT, 7, "Size");
util_rec_def(rec, "name", UTIL_REC_ALIGN_LEFT, 5, "Name");
util_rec_def(rec, "rank", UTIL_REC_ALIGN_RIGHT, 4, "Rank");
util_rec_def(rec, "dstate", UTIL_REC_ALIGN_RIGHT, 7, "D_state");
util_rec_def(rec, "ostate", UTIL_REC_ALIGN_RIGHT, 7, "O_state");
util_rec_def(rec, "pers", UTIL_REC_ALIGN_RIGHT, 4, "Pers");
util_rec_def(rec, "resid", UTIL_REC_ALIGN_RIGHT, 5, "ResID");
util_rec_print_hdr(rec);
/* Call print_scm() for each "/sys/bus/scm/devices/[%16x]" softlink */
path = util_path_sysfs("bus/scm/devices");
count = util_scandir(&de_vec, util_scandir_hexsort,
path, "^[[:xdigit:]]{16}$");
if (count < 0)
errx(EXIT_FAILURE, "Could not read directory: %s", path);
for (i = 0; i < count; i++) {
if (de_vec[i]->d_type != DT_LNK)
continue;
print_scm(de_vec[i]->d_name, rec);
}
util_ptr_vec_free((void **) de_vec, count);
util_rec_free(rec);
free(path);
}
/*
* Entry point
*/
int main(int argc, char **argv)
{
int c;
util_prg_init(&prg);
util_opt_init(opt_vec, NULL);
while (1) {
c = util_opt_getopt_long(argc, argv);
if (c == -1)
break;
switch (c) {
case 'h':
util_prg_print_help();
util_opt_print_help();
return EXIT_SUCCESS;
case 'v':
util_prg_print_version();
return EXIT_SUCCESS;
default:
util_opt_print_parse_error(c, argv);
return EXIT_FAILURE;
}
}
if (argc > optind) {
util_prg_print_arg_error(argv[optind]);
return EXIT_FAILURE;
}
cmd_lsscm();
return EXIT_SUCCESS;
}