Merge pull request #535 from Ostrokrzew/by-id
Disallow to use other than by-id path to core or cache device
This commit is contained in:
292
casadm/cas_lib.c
292
casadm/cas_lib.c
@@ -36,6 +36,9 @@
|
||||
#include "safeclib/safe_lib.h"
|
||||
#include <cas_ioctl_codes.h>
|
||||
#include "psort.h"
|
||||
#include <libgen.h>
|
||||
#include <regex.h>
|
||||
|
||||
#define PRINT_STAT(x) header->cmd_input.cache_stats.x
|
||||
|
||||
#define CORE_ADD_MAX_TIMEOUT 30
|
||||
@@ -547,6 +550,42 @@ void print_slow_atomic_cache_start_info(const char *device_path)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save to dest an absolute device file path of src.
|
||||
* Return number of characters copied to dest if succeed, negative value if failed.
|
||||
*/
|
||||
static int get_abs_path(char* dest, size_t dest_len, const char* src, size_t src_len)
|
||||
{
|
||||
int path_len = -FAILURE;
|
||||
char *dir_name, *dev_name;
|
||||
char *dev = strndup(src, src_len); // strdup creates hidden malloc
|
||||
if (!dev) // basename/dirname may modify the source and
|
||||
goto dev_err; // segfault when called with a static string
|
||||
|
||||
char *dir = strndup(src, src_len);
|
||||
if (!dir)
|
||||
goto dir_err;
|
||||
|
||||
dir_name = realpath(dirname(dir), NULL); // realpath creates hidden malloc
|
||||
if (!dir_name)
|
||||
goto dir_name_err;
|
||||
|
||||
dev_name = basename(dev);
|
||||
if (!dev_name)
|
||||
goto dev_name_err;
|
||||
|
||||
path_len = snprintf(dest, dest_len, "%s/%s", dir_name, dev_name);
|
||||
|
||||
dev_name_err:
|
||||
free(dir_name);
|
||||
dir_name_err:
|
||||
free(dir);
|
||||
dir_err:
|
||||
free(dev);
|
||||
dev_err:
|
||||
return path_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get special device file path (/dev/sdX) for disk.
|
||||
*/
|
||||
@@ -565,7 +604,66 @@ int get_dev_path(const char* disk, char* buf, size_t num)
|
||||
return err;
|
||||
}
|
||||
|
||||
int get_core_info(int fd, int cache_id, int core_id, struct kcas_core_info *info)
|
||||
/* Indicate whether given path should be passed without check */
|
||||
static bool is_dev_link_whitelisted(const char* path)
|
||||
{
|
||||
regex_t regex;
|
||||
int result;
|
||||
static const char* const whitelist[] = {"/dev/cas[0-9]\\+-[0-9]\\+$"};
|
||||
static const unsigned count = ARRAY_SIZE(whitelist);
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
result = regcomp(®ex, whitelist[i], REG_NOSUB);
|
||||
if (result)
|
||||
return FAILURE;
|
||||
|
||||
result = regexec(®ex, path, 0, NULL, 0);
|
||||
regfree(®ex);
|
||||
if (!result) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int _is_by_id_path(const char* dev_path)
|
||||
{
|
||||
static const char dev_by_id_dir[] = "/dev/disk/by-id";
|
||||
|
||||
return (!strncmp(dev_path, dev_by_id_dir,
|
||||
strnlen_s(dev_by_id_dir, sizeof(dev_by_id_dir))));
|
||||
}
|
||||
|
||||
int set_device_path(char *dest_path, size_t dest_len, const char *src_path, size_t src_len)
|
||||
{
|
||||
char abs_dev_path[MAX_STR_LEN];
|
||||
int result;
|
||||
|
||||
/* save given path as absolute path in temporary variable */
|
||||
if (get_abs_path(abs_dev_path, sizeof(abs_dev_path), src_path, src_len) < 0)
|
||||
return FAILURE;
|
||||
|
||||
/* check if given dev_path is whitelisted and then pass it as path or not */
|
||||
if (is_dev_link_whitelisted(abs_dev_path)){
|
||||
result = strncpy_s(dest_path, dest_len, abs_dev_path,
|
||||
strnlen_s(abs_dev_path, sizeof(abs_dev_path)));
|
||||
return result ?: SUCCESS;
|
||||
}
|
||||
|
||||
if (_is_by_id_path(abs_dev_path)) {
|
||||
result = strncpy_s(dest_path, dest_len, abs_dev_path,
|
||||
strnlen_s(abs_dev_path, sizeof(abs_dev_path)));
|
||||
if (!result)
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
int get_core_info(int fd, int cache_id, int core_id,
|
||||
struct kcas_core_info *info, bool by_id_path)
|
||||
{
|
||||
memset(info, 0, sizeof(*info));
|
||||
info->cache_id = cache_id;
|
||||
@@ -575,19 +673,20 @@ int get_core_info(int fd, int cache_id, int core_id, struct kcas_core_info *info
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/* internally use device special file path to describe core */
|
||||
if (get_dev_path(info->core_path_name,
|
||||
info->core_path_name,
|
||||
sizeof(info->core_path_name))) {
|
||||
cas_printf(LOG_WARNING, "WARNING: Can not resolve path to core "
|
||||
"%d from cache %d. By-id path will be shown for that core.\n",
|
||||
core_id, cache_id);
|
||||
if (!by_id_path) {
|
||||
if (get_dev_path(info->core_path_name, info->core_path_name,
|
||||
sizeof(info->core_path_name))) {
|
||||
cas_printf(LOG_WARNING, "WARNING: Can not resolve path to core %d "
|
||||
"from cache %d. By-id path will be shown for that core.\n",
|
||||
core_id, cache_id);
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int get_core_device(int cache_id, int core_id, struct core_device *core)
|
||||
static int get_core_device(int cache_id, int core_id,
|
||||
struct core_device *core, bool by_id_path)
|
||||
{
|
||||
int fd;
|
||||
struct kcas_core_info cmd_info;
|
||||
@@ -599,7 +698,7 @@ static int get_core_device(int cache_id, int core_id, struct core_device *core)
|
||||
if (fd == -1)
|
||||
return FAILURE;
|
||||
|
||||
if (get_core_info(fd, cache_id, core_id, &cmd_info)) {
|
||||
if (get_core_info(fd, cache_id, core_id, &cmd_info, by_id_path)) {
|
||||
cas_printf(LOG_ERR, "Error while retrieving stats\n");
|
||||
print_err(cmd_info.ext_err_code);
|
||||
close(fd);
|
||||
@@ -693,7 +792,7 @@ error_out:
|
||||
*
|
||||
* @return valid pointer to a structure or NULL if error happened
|
||||
*/
|
||||
struct cache_device *get_cache_device(const struct kcas_cache_info *info)
|
||||
struct cache_device *get_cache_device(const struct kcas_cache_info *info, bool by_id_path)
|
||||
{
|
||||
int core_id, cache_id, ret;
|
||||
struct cache_device *cache;
|
||||
@@ -713,8 +812,11 @@ struct cache_device *get_cache_device(const struct kcas_cache_info *info)
|
||||
cache->expected_core_count = info->info.core_count;
|
||||
cache->id = cache_id;
|
||||
cache->state = info->info.state;
|
||||
strncpy_s(cache->device, sizeof(cache->device), info->cache_path_name,
|
||||
strnlen_s(info->cache_path_name, sizeof(info->cache_path_name)));
|
||||
if (set_device_path(cache->device, sizeof(cache->device), info->cache_path_name,
|
||||
sizeof(info->cache_path_name)) != SUCCESS) {
|
||||
free(cache);
|
||||
return NULL;
|
||||
}
|
||||
cache->mode = info->info.cache_mode;
|
||||
cache->dirty = info->info.dirty;
|
||||
cache->flushed = info->info.flushed;
|
||||
@@ -730,7 +832,7 @@ struct cache_device *get_cache_device(const struct kcas_cache_info *info)
|
||||
for (cache->core_count = 0; cache->core_count < info->info.core_count; ++cache->core_count) {
|
||||
core_id = info->core_id[cache->core_count];
|
||||
|
||||
ret = get_core_device(cache_id, core_id, &core);
|
||||
ret = get_core_device(cache_id, core_id, &core, by_id_path);
|
||||
if (0 != ret) {
|
||||
break;
|
||||
} else {
|
||||
@@ -752,7 +854,7 @@ struct cache_device *get_cache_device(const struct kcas_cache_info *info)
|
||||
* @param cache_id cache id (1...)
|
||||
* @return valid pointer to a structure or NULL if error happened
|
||||
*/
|
||||
struct cache_device *get_cache_device_by_id_fd(int cache_id, int fd)
|
||||
struct cache_device *get_cache_device_by_id_fd(int cache_id, int fd, bool by_id_path)
|
||||
{
|
||||
struct kcas_cache_info cmd_info;
|
||||
|
||||
@@ -764,7 +866,7 @@ struct cache_device *get_cache_device_by_id_fd(int cache_id, int fd)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return get_cache_device(&cmd_info);
|
||||
return get_cache_device(&cmd_info, by_id_path);
|
||||
}
|
||||
|
||||
void free_cache_devices_list(struct cache_device **caches, int caches_count)
|
||||
@@ -777,7 +879,7 @@ void free_cache_devices_list(struct cache_device **caches, int caches_count)
|
||||
free(caches);
|
||||
}
|
||||
|
||||
struct cache_device **get_cache_devices(int *caches_count)
|
||||
struct cache_device **get_cache_devices(int *caches_count, bool by_id_path)
|
||||
{
|
||||
int i, fd, status, chunk_size, count;
|
||||
struct kcas_cache_list cache_list;
|
||||
@@ -823,7 +925,8 @@ struct cache_device **get_cache_devices(int *caches_count)
|
||||
|
||||
/* iterate through id table and get status */
|
||||
for (i = 0; i < cache_list.in_out_num; i++) {
|
||||
if ((tmp_cache = get_cache_device_by_id_fd(cache_list.cache_id_tab[i], fd)) == NULL) {
|
||||
if ((tmp_cache = get_cache_device_by_id_fd(cache_list.cache_id_tab[i],
|
||||
fd, by_id_path)) == NULL) {
|
||||
cas_printf(LOG_ERR, "Failed to retrieve cache information!\n");
|
||||
continue;
|
||||
}
|
||||
@@ -852,7 +955,7 @@ int check_cache_already_added(const char *cache_device) {
|
||||
struct cache_device **caches, *curr_cache;
|
||||
int caches_count, i;
|
||||
|
||||
caches = get_cache_devices(&caches_count);
|
||||
caches = get_cache_devices(&caches_count, false);
|
||||
|
||||
if (NULL == caches) {
|
||||
return SUCCESS;
|
||||
@@ -911,7 +1014,7 @@ int start_cache(uint16_t cache_id, unsigned int cache_init,
|
||||
|
||||
if (cache_id == 0) {
|
||||
cache_id = 1;
|
||||
caches = get_cache_devices(&caches_count);
|
||||
caches = get_cache_devices(&caches_count, false);
|
||||
if (caches != NULL) {
|
||||
psort(caches, caches_count, sizeof(struct cache_device*), caches_compare);
|
||||
for (i = 0; i < caches_count; ++i) {
|
||||
@@ -928,11 +1031,13 @@ int start_cache(uint16_t cache_id, unsigned int cache_init,
|
||||
|
||||
cmd.cache_id = cache_id;
|
||||
cmd.init_cache = cache_init;
|
||||
strncpy_s(cmd.cache_path_name,
|
||||
sizeof(cmd.cache_path_name),
|
||||
cache_device,
|
||||
strnlen_s(cache_device,
|
||||
sizeof(cmd.cache_path_name)));
|
||||
if (set_device_path(cmd.cache_path_name, sizeof(cmd.cache_path_name),
|
||||
cache_device, MAX_STR_LEN) != SUCCESS) {
|
||||
cas_printf(LOG_ERR, "Please use correct by-id path to the device "
|
||||
"%s.\n", cache_device);
|
||||
close(fd);
|
||||
return FAILURE;
|
||||
}
|
||||
cmd.caching_mode = cache_mode;
|
||||
cmd.eviction_policy = eviction_policy_type;
|
||||
cmd.line_size = line_size;
|
||||
@@ -978,7 +1083,7 @@ int start_cache(uint16_t cache_id, unsigned int cache_init,
|
||||
status = SUCCESS;
|
||||
|
||||
for (i = 0; i < CORE_ADD_MAX_TIMEOUT; ++i) {
|
||||
cache = get_cache_device_by_id_fd(cache_id, fd);
|
||||
cache = get_cache_device_by_id_fd(cache_id, fd, false);
|
||||
status = FAILURE;
|
||||
|
||||
if (cache == NULL) {
|
||||
@@ -1394,7 +1499,7 @@ int check_core_already_cached(const char *core_device) {
|
||||
if (get_dev_path(core_device, core_device_path, sizeof(core_device_path)))
|
||||
return SUCCESS;
|
||||
|
||||
caches = get_cache_devices(&caches_count);
|
||||
caches = get_cache_devices(&caches_count, false);
|
||||
|
||||
if (NULL == caches) {
|
||||
return SUCCESS;
|
||||
@@ -1483,7 +1588,7 @@ int get_inactive_core_count(const struct kcas_cache_info *cache_info)
|
||||
int inactive_cores = 0;
|
||||
int i;
|
||||
|
||||
cache = get_cache_device(cache_info);
|
||||
cache = get_cache_device(cache_info, false);
|
||||
if (!cache)
|
||||
return -1;
|
||||
|
||||
@@ -1586,7 +1691,7 @@ int illegal_recursive_core(unsigned int cache_id, const char *core_device, int c
|
||||
* iteration of this loop*/
|
||||
|
||||
/* get underlying core device of dev_cache_id-dev_core_id */
|
||||
cache = get_cache_device_by_id_fd(dev_cache_id, fd);
|
||||
cache = get_cache_device_by_id_fd(dev_cache_id, fd, false);
|
||||
|
||||
if (!cache) {
|
||||
cas_printf(LOG_ERR, "Failed to extract statistics for "
|
||||
@@ -1619,103 +1724,6 @@ int illegal_recursive_core(unsigned int cache_id, const char *core_device, int c
|
||||
}
|
||||
}
|
||||
|
||||
/* Indicate whether given entry in /dev/disk/by-id should be ignored -
|
||||
we ignore software created links like 'lvm-' since these can point to
|
||||
both CAS exported object and core device depending on initialization order.
|
||||
*/
|
||||
static bool dev_link_blacklisted(const char* entry)
|
||||
{
|
||||
static const char* const prefix_blacklist[] = {"lvm", "md-name"};
|
||||
static const unsigned count = ARRAY_SIZE(prefix_blacklist);
|
||||
const char* curr;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
curr = prefix_blacklist[i];
|
||||
if (!strncmp(entry, curr, strnlen_s(curr, MAX_STR_LEN)))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* get device link starting with /dev/disk/by-id */
|
||||
static int get_dev_link(const char* disk, char* buf, size_t num)
|
||||
{
|
||||
static const char dev_by_id_dir[] = "/dev/disk/by-id";
|
||||
int err;
|
||||
struct dirent *entry;
|
||||
DIR* dir;
|
||||
char disk_dev[MAX_STR_LEN]; /* input disk device file */
|
||||
char dev_by_id[MAX_STR_LEN]; /* current device path by id */
|
||||
char curr_dev[MAX_STR_LEN]; /* current device file - compared against disk_dev[] */
|
||||
int n;
|
||||
|
||||
dir = opendir(dev_by_id_dir);
|
||||
if (!dir) {
|
||||
/* no disk available by id? */
|
||||
cas_printf(LOG_WARNING, "Unable to open disk alias directory.\n");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (get_dev_path(disk, disk_dev, sizeof(disk_dev))) {
|
||||
err = FAILURE;
|
||||
goto close_dir;
|
||||
}
|
||||
|
||||
err = FAILURE;
|
||||
while (err != SUCCESS && (entry = readdir(dir))) {
|
||||
/* check if link is blacklisted */
|
||||
if (dev_link_blacklisted(entry->d_name))
|
||||
continue;
|
||||
|
||||
/* construct device-by-id path for current device */
|
||||
n = snprintf(dev_by_id, sizeof(dev_by_id), "%s/%s",
|
||||
dev_by_id_dir, entry->d_name);
|
||||
if (n < 0 || n >= sizeof(dev_by_id)) {
|
||||
cas_printf(LOG_WARNING,
|
||||
"Error constructing disk device by-link path.\n");
|
||||
continue;
|
||||
}
|
||||
/* get device path for current device */
|
||||
if (get_dev_path(dev_by_id, curr_dev, sizeof(curr_dev))) {
|
||||
/* it's normal to have stale links in /dev/ - no log */
|
||||
continue;
|
||||
}
|
||||
/* compare current device path against disk device path */
|
||||
if (!strncmp(disk_dev, curr_dev, sizeof(curr_dev))) {
|
||||
if (n >= num) {
|
||||
cas_printf(LOG_WARNING, "Buffer to short to store device link.\n");
|
||||
} else {
|
||||
strncpy_s(buf, num, dev_by_id, sizeof(dev_by_id));
|
||||
err = SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close_dir:
|
||||
closedir(dir);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int set_core_path(char *path, const char *core_device, size_t len)
|
||||
{
|
||||
/* attempt to get disk device path by id */
|
||||
if (get_dev_link(core_device, path, len) == SUCCESS)
|
||||
return SUCCESS;
|
||||
|
||||
/* .. if this failed, try to get standard /dev/sd* path */
|
||||
if (get_dev_path(core_device, path, len) == SUCCESS)
|
||||
return SUCCESS;
|
||||
|
||||
/* if everything else failed - fall back to user-provided path */
|
||||
if (!strncpy_s(path, len, core_device, strnlen_s(core_device, MAX_STR_LEN)))
|
||||
return SUCCESS;
|
||||
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
int add_core(unsigned int cache_id, unsigned int core_id, const char *core_device,
|
||||
int try_add, int update_path)
|
||||
{
|
||||
@@ -1745,7 +1753,8 @@ int add_core(unsigned int cache_id, unsigned int core_id, const char *core_devic
|
||||
}
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
if (set_core_path(cmd.core_path_name, core_device, MAX_STR_LEN) != SUCCESS) {
|
||||
if (set_device_path(cmd.core_path_name, sizeof(cmd.core_path_name),
|
||||
core_device, MAX_STR_LEN) != SUCCESS) {
|
||||
cas_printf(LOG_ERR, "Failed to copy core path\n");
|
||||
return FAILURE;
|
||||
}
|
||||
@@ -1758,7 +1767,7 @@ int add_core(unsigned int cache_id, unsigned int core_id, const char *core_devic
|
||||
if (fd == -1)
|
||||
return FAILURE;
|
||||
|
||||
/* check for illegal rec ursive caching config. */
|
||||
/* check for illegal recursive caching config. */
|
||||
if (illegal_recursive_core(cache_id, user_core_path,
|
||||
user_core_path_size, fd)) {
|
||||
close(fd);
|
||||
@@ -1894,7 +1903,8 @@ int core_pool_remove(const char *core_device)
|
||||
if (fd == -1)
|
||||
return FAILURE;
|
||||
|
||||
if (set_core_path(cmd.core_path_name, core_device, MAX_STR_LEN) != SUCCESS) {
|
||||
if (set_device_path(cmd.core_path_name, sizeof(cmd.core_path_name),
|
||||
core_device, MAX_STR_LEN) != SUCCESS) {
|
||||
cas_printf(LOG_ERR, "Failed to copy core path\n");
|
||||
close(fd);
|
||||
return FAILURE;
|
||||
@@ -2638,7 +2648,7 @@ error_out:
|
||||
return result;
|
||||
}
|
||||
|
||||
int list_caches(unsigned int list_format)
|
||||
int list_caches(unsigned int list_format, bool by_id_path)
|
||||
{
|
||||
struct cache_device **caches, *curr_cache;
|
||||
struct kcas_core_pool_path core_pool_path_cmd = {0};
|
||||
@@ -2650,7 +2660,7 @@ int list_caches(unsigned int list_format)
|
||||
pthread_t thread;
|
||||
struct list_printout_ctx printout_ctx;
|
||||
|
||||
caches = get_cache_devices(&caches_count);
|
||||
caches = get_cache_devices(&caches_count, by_id_path);
|
||||
if (caches_count < 0) {
|
||||
cas_printf(LOG_INFO, "Error getting caches list\n");
|
||||
return FAILURE;
|
||||
@@ -2705,9 +2715,12 @@ int list_caches(unsigned int list_format)
|
||||
"-" /* device */);
|
||||
for (i = 0; i < core_pool_path_cmd.core_pool_count; i++) {
|
||||
char *core_path = core_pool_path_cmd.core_path_tab + (MAX_STR_LEN * i);
|
||||
if (get_dev_path(core_path, core_path, MAX_STR_LEN)) {
|
||||
cas_printf(LOG_WARNING, "WARNING: Can not resolve path to core. "
|
||||
"By-id path will be shown for that core.\n");
|
||||
if (!by_id_path) {
|
||||
if (get_dev_path(core_path, core_path, MAX_STR_LEN)) {
|
||||
cas_printf(LOG_WARNING, "WARNING: Can not resolve path "
|
||||
"to core. By-id path will be shown for that "
|
||||
"core.\n");
|
||||
}
|
||||
}
|
||||
fprintf(intermediate_file[1], TAG(TREE_LEAF)
|
||||
"%s,%s,%s,%s,%s,%s\n",
|
||||
@@ -2729,7 +2742,10 @@ int list_caches(unsigned int list_format)
|
||||
float cache_flush_prog;
|
||||
float core_flush_prog;
|
||||
|
||||
get_dev_path(curr_cache->device, curr_cache->device, sizeof(curr_cache->device));
|
||||
if (!by_id_path) {
|
||||
get_dev_path(curr_cache->device, curr_cache->device,
|
||||
sizeof(curr_cache->device));
|
||||
}
|
||||
|
||||
cache_flush_prog = calculate_flush_progress(curr_cache->dirty, curr_cache->flushed);
|
||||
if (cache_flush_prog) {
|
||||
@@ -2805,8 +2821,10 @@ int _check_cache_device(const char *device_path,
|
||||
{
|
||||
int result, fd;
|
||||
|
||||
strncpy_s(cmd_info->path_name, sizeof(cmd_info->path_name), device_path,
|
||||
strnlen_s(device_path, sizeof(cmd_info->path_name)));
|
||||
if (set_device_path(cmd_info->path_name, sizeof(cmd_info->path_name),
|
||||
device_path, MAX_STR_LEN) != SUCCESS) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
fd = open_ctrl_device();
|
||||
if (fd == -1)
|
||||
|
@@ -26,7 +26,7 @@
|
||||
|
||||
#define FAILURE 1 /**< default non-zero exit code. */
|
||||
#define INTERRUPTED 2 /**< if command is interrupted */
|
||||
#define SUCCESS 0 /**< 0 exit code from majority of our functions
|
||||
#define SUCCESS 0 /**< 0 exit code from majority of our functions \
|
||||
stands for success */
|
||||
|
||||
struct core_device {
|
||||
@@ -210,7 +210,7 @@ int set_cache_mode(unsigned int cache_state, unsigned int cache_id, int flush);
|
||||
*/
|
||||
int add_core(unsigned int cache_id, unsigned int core_id, const char *core_device, int try_add, int update_path);
|
||||
|
||||
int get_core_info(int fd, int cache_id, int core_id, struct kcas_core_info *info);
|
||||
int get_core_info(int fd, int cache_id, int core_id, struct kcas_core_info *info, bool by_id_path);
|
||||
|
||||
int remove_core(unsigned int cache_id, unsigned int core_id,
|
||||
bool detach, bool force_no_flush);
|
||||
@@ -234,16 +234,16 @@ int partition_is_name_valid(const char *name);
|
||||
|
||||
int cas_module_version(char *buff, int size);
|
||||
int disk_module_version(char *buff, int size);
|
||||
int list_caches(unsigned int list_format);
|
||||
int list_caches(unsigned int list_format, bool by_id_path);
|
||||
int cache_status(unsigned int cache_id, unsigned int core_id, int io_class_id,
|
||||
unsigned int stats_filters, unsigned int stats_format);
|
||||
unsigned int stats_filters, unsigned int stats_format, bool by_id_path);
|
||||
int get_inactive_core_count(const struct kcas_cache_info *cache_info);
|
||||
|
||||
int open_ctrl_device_quiet();
|
||||
int open_ctrl_device();
|
||||
int *get_cache_ids(int *cache_count);
|
||||
struct cache_device *get_cache_device_by_id_fd(int cache_id, int fd);
|
||||
struct cache_device **get_cache_devices(int *caches_count);
|
||||
struct cache_device *get_cache_device_by_id_fd(int cache_id, int fd, bool by_id_path);
|
||||
struct cache_device **get_cache_devices(int *caches_count, bool by_id_path);
|
||||
void free_cache_devices_list(struct cache_device **caches, int caches_count);
|
||||
|
||||
int validate_dev(const char *dev_path);
|
||||
@@ -298,6 +298,17 @@ void print_err(int error_code);
|
||||
*/
|
||||
int get_dev_path(const char* disk, char* buf, size_t num);
|
||||
|
||||
/**
|
||||
* @brief make sure device link is unique and write sanitized version to \a dest_path
|
||||
*
|
||||
* @param[in] src_path link to device
|
||||
* @param[in] src_len length of \a src_path
|
||||
* @param[in] dest_len max length of \a dest_path
|
||||
* @param[out] dest_path sanitized absolute path
|
||||
* @return 0 on success, nonzero on failure
|
||||
*/
|
||||
int set_device_path(char *dest_path, size_t dest_len, const char *src_path, size_t src_len);
|
||||
|
||||
/**
|
||||
* @brief convert string to int
|
||||
*/
|
||||
|
@@ -60,6 +60,7 @@ struct command_args{
|
||||
uint32_t params_type;
|
||||
uint32_t params_count;
|
||||
bool verbose;
|
||||
bool by_id_path;
|
||||
};
|
||||
|
||||
static struct command_args command_args_values = {
|
||||
@@ -83,6 +84,7 @@ static struct command_args command_args_values = {
|
||||
.no_flush = false,
|
||||
.cache_device = NULL,
|
||||
.core_device = NULL,
|
||||
.by_id_path = false,
|
||||
|
||||
.params_type = 0,
|
||||
.params_count = 0,
|
||||
@@ -153,6 +155,8 @@ int command_handle_option(char *opt, const char **arg)
|
||||
command_args_values.detach = true;
|
||||
} else if (!strcmp(opt, "no-flush")) {
|
||||
command_args_values.no_flush = true;
|
||||
} else if (!strcmp(opt, "by-id-path")) {
|
||||
command_args_values.by_id_path = true;
|
||||
} else {
|
||||
return FAILURE;
|
||||
}
|
||||
@@ -344,12 +348,13 @@ int handle_start()
|
||||
|
||||
static cli_option list_options[] = {
|
||||
{'o', "output-format", "Output format: {table|csv}", 1, "FORMAT", 0},
|
||||
{'b', "by-id-path", "Display by-id path to disks instead of short form /dev/sdx"},
|
||||
{0}
|
||||
};
|
||||
|
||||
int handle_list()
|
||||
{
|
||||
return list_caches(command_args_values.output_format);
|
||||
return list_caches(command_args_values.output_format, command_args_values.by_id_path);
|
||||
}
|
||||
|
||||
static cli_option stats_options[] = {
|
||||
@@ -358,6 +363,7 @@ static cli_option stats_options[] = {
|
||||
{'d', "io-class-id", "Display per IO class statistics", 1, "ID", CLI_OPTION_OPTIONAL_ARG},
|
||||
{'f', "filter", "Apply filters from the following set: {all, conf, usage, req, blk, err}", 1, "FILTER-SPEC"},
|
||||
{'o', "output-format", "Output format: {table|csv}", 1, "FORMAT"},
|
||||
{'b', "by-id-path", "Display by-id path to disks instead of short form /dev/sdx"},
|
||||
{0}
|
||||
};
|
||||
|
||||
@@ -396,6 +402,10 @@ int stats_command_handle_option(char *opt, const char **arg)
|
||||
command_args_values.output_format = validate_str_output_format(arg[0]);
|
||||
if (OUTPUT_FORMAT_INVALID == command_args_values.output_format)
|
||||
return FAILURE;
|
||||
} else if (!strcmp(opt, "by-id-path")) {
|
||||
command_args_values.by_id_path = true;
|
||||
if (command_args_values.by_id_path == false)
|
||||
return FAILURE;
|
||||
} else {
|
||||
return FAILURE;
|
||||
}
|
||||
@@ -409,7 +419,8 @@ int handle_stats()
|
||||
command_args_values.core_id,
|
||||
command_args_values.io_class_id,
|
||||
command_args_values.stats_filters,
|
||||
command_args_values.output_format);
|
||||
command_args_values.output_format,
|
||||
command_args_values.by_id_path);
|
||||
}
|
||||
|
||||
static cli_option stop_options[] = {
|
||||
|
@@ -516,7 +516,7 @@ int cache_stats_ioclasses(int ctrl_fd, const struct kcas_cache_info *cache_info,
|
||||
}
|
||||
|
||||
int cache_stats_conf(int ctrl_fd, const struct kcas_cache_info *cache_info,
|
||||
unsigned int cache_id, FILE *outfile)
|
||||
unsigned int cache_id, FILE *outfile, bool by_id_path)
|
||||
{
|
||||
float flush_progress = 0;
|
||||
float value;
|
||||
@@ -526,10 +526,10 @@ int cache_stats_conf(int ctrl_fd, const struct kcas_cache_info *cache_info,
|
||||
char dev_path[MAX_STR_LEN];
|
||||
int inactive_cores;
|
||||
|
||||
if (get_dev_path(cache_info->cache_path_name, dev_path, sizeof(dev_path)) != SUCCESS)
|
||||
cache_path = cache_info->cache_path_name;
|
||||
else
|
||||
if (!by_id_path && get_dev_path(cache_info->cache_path_name, dev_path, sizeof(dev_path)) == SUCCESS)
|
||||
cache_path = dev_path;
|
||||
else
|
||||
cache_path = cache_info->cache_path_name;
|
||||
|
||||
flush_progress = calculate_flush_progress(cache_info->info.dirty,
|
||||
cache_info->info.flushed);
|
||||
@@ -602,7 +602,8 @@ void cache_stats_counters(struct kcas_get_stats *cache_stats, FILE *outfile,
|
||||
}
|
||||
|
||||
static int cache_stats(int ctrl_fd, const struct kcas_cache_info *cache_info,
|
||||
unsigned int cache_id, FILE *outfile, unsigned int stats_filters)
|
||||
unsigned int cache_id, FILE *outfile, unsigned int stats_filters,
|
||||
bool by_id_path)
|
||||
{
|
||||
struct kcas_get_stats cache_stats = {};
|
||||
cache_stats.cache_id = cache_id;
|
||||
@@ -615,7 +616,7 @@ static int cache_stats(int ctrl_fd, const struct kcas_cache_info *cache_info,
|
||||
begin_record(outfile);
|
||||
|
||||
if (stats_filters & STATS_FILTER_CONF)
|
||||
cache_stats_conf(ctrl_fd, cache_info, cache_id, outfile);
|
||||
cache_stats_conf(ctrl_fd, cache_info, cache_id, outfile, by_id_path);
|
||||
|
||||
if (stats_filters & STATS_FILTER_USAGE)
|
||||
print_usage_stats(&cache_stats.usage, outfile);
|
||||
@@ -633,12 +634,12 @@ static int cache_stats(int ctrl_fd, const struct kcas_cache_info *cache_info,
|
||||
|
||||
int cache_stats_cores(int ctrl_fd, const struct kcas_cache_info *cache_info,
|
||||
unsigned int cache_id, unsigned int core_id, int io_class_id,
|
||||
FILE *outfile, unsigned int stats_filters)
|
||||
FILE *outfile, unsigned int stats_filters, bool by_id_path)
|
||||
{
|
||||
struct kcas_core_info core_info;
|
||||
struct kcas_get_stats stats;
|
||||
|
||||
if (get_core_info(ctrl_fd, cache_id, core_id, &core_info)) {
|
||||
if (get_core_info(ctrl_fd, cache_id, core_id, &core_info, by_id_path)) {
|
||||
cas_printf(LOG_ERR, "Error while retrieving stats for core %d\n", core_id);
|
||||
print_err(core_info.ext_err_code);
|
||||
return FAILURE;
|
||||
@@ -695,7 +696,7 @@ void *stats_printout(void *ctx)
|
||||
* @return SUCCESS upon successful printing of statistic. FAILURE if any error happens
|
||||
*/
|
||||
int cache_status(unsigned int cache_id, unsigned int core_id, int io_class_id,
|
||||
unsigned int stats_filters, unsigned int output_format)
|
||||
unsigned int stats_filters, unsigned int output_format, bool by_id_path)
|
||||
{
|
||||
int ctrl_fd, i;
|
||||
int ret = SUCCESS;
|
||||
@@ -763,13 +764,14 @@ int cache_status(unsigned int cache_id, unsigned int core_id, int io_class_id,
|
||||
}
|
||||
} else if (core_id == OCF_CORE_ID_INVALID) {
|
||||
if (cache_stats(ctrl_fd, &cache_info, cache_id, intermediate_file[1],
|
||||
stats_filters)) {
|
||||
stats_filters, by_id_path)) {
|
||||
ret = FAILURE;
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
if (cache_stats_cores(ctrl_fd, &cache_info, cache_id, core_id,
|
||||
io_class_id, intermediate_file[1], stats_filters)) {
|
||||
io_class_id, intermediate_file[1],
|
||||
stats_filters, by_id_path)) {
|
||||
ret = FAILURE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
Reference in New Issue
Block a user