mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-22 17:35:59 +03:00
1aae627433
For snapshot, prepare whole command in front into private buffer. Add also some missing '\n' for syslog messages. For raid and mirror only convert creation of command line string. This should avoid any unbound growth of mempool for dm_split_names.
173 lines
4.2 KiB
C
173 lines
4.2 KiB
C
/*
|
|
* Copyright (C) 2005-2011 Red Hat, Inc. All rights reserved.
|
|
*
|
|
* This file is part of LVM2.
|
|
*
|
|
* This copyrighted material is made available to anyone wishing to use,
|
|
* modify, copy, or redistribute it subject to the terms and conditions
|
|
* of the GNU Lesser General Public License v.2.1.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#include "lib.h"
|
|
|
|
#include "lvm2cmd.h"
|
|
#include "errors.h"
|
|
#include "libdevmapper-event.h"
|
|
#include "dmeventd_lvm.h"
|
|
|
|
#include <syslog.h> /* FIXME Replace syslog with multilog */
|
|
/* FIXME Missing openlog? */
|
|
/* FIXME Replace most syslogs with log_error() style messages and add complete context. */
|
|
/* FIXME Reformat to 80 char lines. */
|
|
|
|
/*
|
|
* run_repair is a close copy to
|
|
* plugins/mirror/dmeventd_mirror.c:_remove_failed_devices()
|
|
*/
|
|
static int run_repair(const char *device)
|
|
{
|
|
int r;
|
|
#define CMD_SIZE 256 /* FIXME Use system restriction */
|
|
char cmd_str[CMD_SIZE];
|
|
|
|
if (!dmeventd_lvm2_command(dmeventd_lvm2_pool(), cmd_str, sizeof(cmd_str),
|
|
"lvconvert --config devices{ignore_suspended_devices=1} "
|
|
"--repair --use-policies", device))
|
|
return -1;
|
|
|
|
r = dmeventd_lvm2_run(cmd_str);
|
|
|
|
if (r != ECMD_PROCESSED)
|
|
syslog(LOG_INFO, "Repair of RAID device %s failed.", device);
|
|
|
|
return (r == ECMD_PROCESSED) ? 0 : -1;
|
|
}
|
|
|
|
static int _process_raid_event(char *params, const char *device)
|
|
{
|
|
int i, n, failure = 0;
|
|
char *p, *a[4];
|
|
char *raid_type;
|
|
char *num_devices;
|
|
char *health_chars;
|
|
char *resync_ratio;
|
|
|
|
/*
|
|
* RAID parms: <raid_type> <#raid_disks> \
|
|
* <health chars> <resync ratio>
|
|
*/
|
|
if (!dm_split_words(params, 4, 0, a)) {
|
|
syslog(LOG_ERR, "Failed to process status line for %s\n",
|
|
device);
|
|
return -EINVAL;
|
|
}
|
|
raid_type = a[0];
|
|
num_devices = a[1];
|
|
health_chars = a[2];
|
|
resync_ratio = a[3];
|
|
|
|
if (!(n = atoi(num_devices))) {
|
|
syslog(LOG_ERR, "Failed to parse number of devices for %s: %s",
|
|
device, num_devices);
|
|
return -EINVAL;
|
|
}
|
|
|
|
for (i = 0; i < n; i++) {
|
|
switch (health_chars[i]) {
|
|
case 'A':
|
|
/* Device is 'A'live and well */
|
|
case 'a':
|
|
/* Device is 'a'live, but not yet in-sync */
|
|
break;
|
|
case 'D':
|
|
syslog(LOG_ERR,
|
|
"Device #%d of %s array, %s, has failed.",
|
|
i, raid_type, device);
|
|
failure++;
|
|
break;
|
|
default:
|
|
/* Unhandled character returned from kernel */
|
|
break;
|
|
}
|
|
if (failure)
|
|
return run_repair(device);
|
|
}
|
|
|
|
p = strstr(resync_ratio, "/");
|
|
if (!p) {
|
|
syslog(LOG_ERR, "Failed to parse resync_ratio for %s: %s",
|
|
device, resync_ratio);
|
|
return -EINVAL;
|
|
}
|
|
p[0] = '\0';
|
|
syslog(LOG_INFO, "%s array, %s, is %s in-sync.",
|
|
raid_type, device, strcmp(resync_ratio, p+1) ? "not" : "now");
|
|
|
|
return 0;
|
|
}
|
|
|
|
void process_event(struct dm_task *dmt,
|
|
enum dm_event_mask event __attribute__((unused)),
|
|
void **unused __attribute__((unused)))
|
|
{
|
|
void *next = NULL;
|
|
uint64_t start, length;
|
|
char *target_type = NULL;
|
|
char *params;
|
|
const char *device = dm_task_get_name(dmt);
|
|
|
|
dmeventd_lvm2_lock();
|
|
|
|
do {
|
|
next = dm_get_next_target(dmt, next, &start, &length,
|
|
&target_type, ¶ms);
|
|
|
|
if (!target_type) {
|
|
syslog(LOG_INFO, "%s mapping lost.", device);
|
|
continue;
|
|
}
|
|
|
|
if (strcmp(target_type, "raid")) {
|
|
syslog(LOG_INFO, "%s has non-raid portion.", device);
|
|
continue;
|
|
}
|
|
|
|
if (_process_raid_event(params, device))
|
|
syslog(LOG_ERR, "Failed to process event for %s",
|
|
device);
|
|
} while (next);
|
|
|
|
dmeventd_lvm2_unlock();
|
|
}
|
|
|
|
int register_device(const char *device,
|
|
const char *uuid __attribute__((unused)),
|
|
int major __attribute__((unused)),
|
|
int minor __attribute__((unused)),
|
|
void **unused __attribute__((unused)))
|
|
{
|
|
if (!dmeventd_lvm2_init())
|
|
return 0;
|
|
|
|
syslog(LOG_INFO, "Monitoring RAID device %s for events.", device);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int unregister_device(const char *device,
|
|
const char *uuid __attribute__((unused)),
|
|
int major __attribute__((unused)),
|
|
int minor __attribute__((unused)),
|
|
void **unused __attribute__((unused)))
|
|
{
|
|
syslog(LOG_INFO, "No longer monitoring RAID device %s for events.",
|
|
device);
|
|
dmeventd_lvm2_exit();
|
|
|
|
return 1;
|
|
}
|