|
Packit |
7e09eb |
/*
|
|
Packit |
7e09eb |
* Intel(R) Enclosure LED Utilities
|
|
Packit |
7e09eb |
* Copyright (C) 2009-2019 Intel Corporation.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* This program is free software; you can redistribute it and/or modify it
|
|
Packit |
7e09eb |
* under the terms and conditions of the GNU General Public License,
|
|
Packit |
7e09eb |
* version 2, as published by the Free Software Foundation.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
Packit |
7e09eb |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
Packit |
7e09eb |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
Packit |
7e09eb |
* more details.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* You should have received a copy of the GNU General Public License along with
|
|
Packit |
7e09eb |
* this program; if not, write to the Free Software Foundation, Inc.,
|
|
Packit |
7e09eb |
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
#include <limits.h>
|
|
Packit |
7e09eb |
#include <stdint.h>
|
|
Packit |
7e09eb |
#include <stdlib.h>
|
|
Packit |
7e09eb |
#include <string.h>
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
#if _HAVE_DMALLOC_H
|
|
Packit |
7e09eb |
#include <dmalloc.h>
|
|
Packit |
7e09eb |
#endif
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
#include "block.h"
|
|
Packit |
7e09eb |
#include "config.h"
|
|
Packit |
7e09eb |
#include "ibpi.h"
|
|
Packit |
7e09eb |
#include "list.h"
|
|
Packit |
7e09eb |
#include "raid.h"
|
|
Packit |
7e09eb |
#include "slave.h"
|
|
Packit |
7e09eb |
#include "status.h"
|
|
Packit |
7e09eb |
#include "sysfs.h"
|
|
Packit |
7e09eb |
#include "utils.h"
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/**
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
static enum raid_state _get_array_state(const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
enum raid_state state = RAID_STATE_UNKNOWN;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
char *p = get_text(path, "md/array_state");
|
|
Packit |
7e09eb |
if (p) {
|
|
Packit |
7e09eb |
if (strcmp(p, "clear") == 0)
|
|
Packit |
7e09eb |
state = RAID_STATE_CLEAR;
|
|
Packit |
7e09eb |
else if (strcmp(p, "inactive") == 0)
|
|
Packit |
7e09eb |
state = RAID_STATE_INACTIVE;
|
|
Packit |
7e09eb |
else if (strcmp(p, "suspended") == 0)
|
|
Packit |
7e09eb |
state = RAID_STATE_SUSPENDED;
|
|
Packit |
7e09eb |
else if (strcmp(p, "readonly") == 0)
|
|
Packit |
7e09eb |
state = RAID_STATE_READONLY;
|
|
Packit |
7e09eb |
else if (strcmp(p, "read-auto") == 0)
|
|
Packit |
7e09eb |
state = RAID_STATE_READ_AUTO;
|
|
Packit |
7e09eb |
else if (strcmp(p, "clean") == 0)
|
|
Packit |
7e09eb |
state = RAID_STATE_CLEAN;
|
|
Packit |
7e09eb |
else if (strcmp(p, "active") == 0)
|
|
Packit |
7e09eb |
state = RAID_STATE_ACTIVE;
|
|
Packit |
7e09eb |
else if (strcmp(p, "write-pending") == 0)
|
|
Packit |
7e09eb |
state = RAID_STATE_WRITE_PENDING;
|
|
Packit |
7e09eb |
else if (strcmp(p, "active-idle") == 0)
|
|
Packit |
7e09eb |
state = RAID_STATE_ACTIVE_IDLE;
|
|
Packit |
7e09eb |
free(p);
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
return state;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/**
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
static enum raid_action _get_sync_action(const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
enum raid_action action = RAID_ACTION_UNKNOWN;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
char *p = get_text(path, "md/sync_action");
|
|
Packit |
7e09eb |
if (p) {
|
|
Packit |
7e09eb |
if (strcmp(p, "idle") == 0)
|
|
Packit |
7e09eb |
action = RAID_ACTION_IDLE;
|
|
Packit |
7e09eb |
else if (strcmp(p, "reshape") == 0)
|
|
Packit |
7e09eb |
action = RAID_ACTION_RESHAPE;
|
|
Packit |
7e09eb |
else if (strcmp(p, "frozen") == 0)
|
|
Packit |
7e09eb |
action = RAID_ACTION_FROZEN;
|
|
Packit |
7e09eb |
else if (strcmp(p, "resync") == 0)
|
|
Packit |
7e09eb |
action = RAID_ACTION_RESYNC;
|
|
Packit |
7e09eb |
else if (strcmp(p, "check") == 0)
|
|
Packit |
7e09eb |
action = RAID_ACTION_CHECK;
|
|
Packit |
7e09eb |
else if (strcmp(p, "recover") == 0)
|
|
Packit |
7e09eb |
action = RAID_ACTION_RECOVER;
|
|
Packit |
7e09eb |
else if (strcmp(p, "repair") == 0)
|
|
Packit |
7e09eb |
action = RAID_ACTION_REPAIR;
|
|
Packit |
7e09eb |
free(p);
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
return action;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/**
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
static enum raid_level _get_level(const char *path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
enum raid_level result = RAID_LEVEL_UNKNOWN;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
char *p = get_text(path, "md/level");
|
|
Packit |
7e09eb |
if (p) {
|
|
Packit |
7e09eb |
if (strcmp(p, "raid0") == 0)
|
|
Packit |
7e09eb |
result = RAID_LEVEL_0;
|
|
Packit |
7e09eb |
else if (strcmp(p, "raid1") == 0)
|
|
Packit |
7e09eb |
result = RAID_LEVEL_1;
|
|
Packit |
7e09eb |
else if (strcmp(p, "raid10") == 0)
|
|
Packit |
7e09eb |
result = RAID_LEVEL_10;
|
|
Packit |
7e09eb |
else if (strcmp(p, "raid4") == 0)
|
|
Packit |
7e09eb |
result = RAID_LEVEL_4;
|
|
Packit |
7e09eb |
else if (strcmp(p, "raid5") == 0)
|
|
Packit |
7e09eb |
result = RAID_LEVEL_5;
|
|
Packit |
7e09eb |
else if (strcmp(p, "raid6") == 0)
|
|
Packit |
7e09eb |
result = RAID_LEVEL_6;
|
|
Packit |
7e09eb |
else if (strcmp(p, "linear") == 0)
|
|
Packit |
7e09eb |
result = RAID_LEVEL_LINEAR;
|
|
Packit |
7e09eb |
else if (strcmp(p, "faulty") == 0)
|
|
Packit |
7e09eb |
result = RAID_LEVEL_FAULTY;
|
|
Packit |
7e09eb |
free(p);
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
return result;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/**
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
struct raid_device *raid_device_init(const char *path, unsigned int device_num,
|
|
Packit |
7e09eb |
enum device_type type)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
struct raid_device *device = NULL;
|
|
Packit |
7e09eb |
enum raid_state state;
|
|
Packit |
7e09eb |
const char *debug_dev;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
state = _get_array_state(path);
|
|
Packit |
7e09eb |
if (state > RAID_STATE_INACTIVE ||
|
|
Packit |
7e09eb |
(type == DEVICE_TYPE_CONTAINER && state > RAID_STATE_CLEAR)) {
|
|
Packit |
7e09eb |
device = malloc(sizeof(struct raid_device));
|
|
Packit |
7e09eb |
if (device) {
|
|
Packit |
7e09eb |
device->sysfs_path = str_dup(path);
|
|
Packit |
7e09eb |
device->device_num = device_num;
|
|
Packit |
7e09eb |
device->sync_action = _get_sync_action(path);
|
|
Packit |
7e09eb |
device->array_state = state;
|
|
Packit |
7e09eb |
device->level = _get_level(path);
|
|
Packit |
7e09eb |
device->degraded = get_int(path, -1, "md/degraded");
|
|
Packit |
7e09eb |
device->raid_disks = get_int(path, 0, "md/raid_disks");
|
|
Packit |
7e09eb |
device->type = type;
|
|
Packit |
7e09eb |
debug_dev = strrchr(path, '/');
|
|
Packit |
7e09eb |
debug_dev = debug_dev ? debug_dev + 1 : path;
|
|
Packit |
7e09eb |
log_debug("(%s) path: %s, level=%d, state=%d, " \
|
|
Packit |
7e09eb |
"degraded=%d, disks=%d, type=%d",
|
|
Packit |
7e09eb |
__func__, debug_dev, device->level,
|
|
Packit |
7e09eb |
state, device->degraded,
|
|
Packit |
7e09eb |
device->raid_disks, type);
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
return device;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/**
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
void raid_device_fini(struct raid_device *device)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
if (device) {
|
|
Packit |
7e09eb |
if (device->sysfs_path)
|
|
Packit |
7e09eb |
free(device->sysfs_path);
|
|
Packit |
7e09eb |
free(device);
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/**
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
struct raid_device *raid_device_duplicate(struct raid_device *device)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
struct raid_device *new_device = NULL;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
if (device) {
|
|
Packit |
7e09eb |
new_device = malloc(sizeof(struct raid_device));
|
|
Packit |
7e09eb |
if (new_device) {
|
|
Packit |
7e09eb |
*new_device = *device;
|
|
Packit |
7e09eb |
new_device->sysfs_path = str_dup(device->sysfs_path);
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
return new_device;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/**
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
struct raid_device *find_raid_device(const struct list *raid_list,
|
|
Packit |
7e09eb |
char *raid_sysfs_path)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
struct raid_device *raid = NULL;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
list_for_each(raid_list, raid) {
|
|
Packit |
7e09eb |
if (strcmp(raid->sysfs_path, raid_sysfs_path) == 0)
|
|
Packit |
7e09eb |
return raid;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
return NULL;
|
|
Packit |
7e09eb |
}
|