1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

mirrors: fix leak in device_is_usable mirror check

Function _ignore_blocked_mirror_devices was not release
allocated strings images_health and log_health.

In error paths it was also not releasing dm_task structure.

Swaped return code of _ignore_blocked_mirror_devices and
use 1 as success.

In _parse_mirror_status use log_error if memory allocation
fails and few more errors so they are no going unnoticed
as debug messages.

On error path always clear return values and free strings.

For dev_create_file  use cache mem pool to avoid memleak.
This commit is contained in:
Zdenek Kabelac 2012-12-06 23:37:21 +01:00
parent f942ae4a7a
commit ec49f07b0d
2 changed files with 42 additions and 19 deletions

View File

@ -1,5 +1,6 @@
Version 2.02.99 -
===================================
Fix memleak in device_is_usable mirror testing function.
Do not ignore -f in lvconvert --repair -y -f for mirror and raid volumes.
Disallow pvmove on RAID LVs until they are addressed properly
Allow empty activation/{auto_activation|read_only|}_volume_list config option.

View File

@ -158,6 +158,10 @@ static int _parse_mirror_status(char *mirror_status_str,
char **args, **log_args;
unsigned num_devs, log_argc;
*images_health = NULL;
*log_health = NULL;
*log_dev = 0;
if (!dm_split_words(mirror_status_str, 1, 0, &p) ||
!(num_devs = (unsigned) atoi(p)))
/* On errors, we must assume the mirror is to be avoided */
@ -176,19 +180,31 @@ static int _parse_mirror_status(char *mirror_status_str,
log_argc, 0, log_args) < log_argc)
return_0;
*log_health = NULL;
*log_dev = 0;
if (!strcmp(log_args[0], "disk")) {
if (!(*log_health = dm_strdup(log_args[2])))
return_0;
if (sscanf(log_args[1], "%d:%d", &major, &minor) != 2)
return_0;
if (!(*log_health = dm_strdup(log_args[2]))) {
log_error("Allocation of log string failed.");
return 0;
}
if (sscanf(log_args[1], "%d:%d", &major, &minor) != 2) {
log_error("Parsing of log's major minor failed.");
goto out;
}
*log_dev = MKDEV((dev_t)major, minor);
}
if (!(*images_health = dm_strdup(args[2 + num_devs])))
return_0;
if (!(*images_health = dm_strdup(args[2 + num_devs]))) {
log_error("Allocation of images string failed.");
goto out;
}
return 1;
out:
dm_free(*log_health);
*log_health = NULL;
*log_dev = 0;
return 0;
}
/*
@ -227,11 +243,12 @@ static int _ignore_blocked_mirror_devices(struct device *dev,
uint64_t s,l;
char *params, *target_type = NULL;
void *next = NULL;
struct dm_task *dmt;
struct dm_task *dmt = NULL;
int r = 0;
if (!_parse_mirror_status(mirror_status_str,
&images_health, &log_dev, &log_health))
goto_out;
return_0;
for (i = 0; images_health[i]; i++)
if (images_health[i] != 'A') {
@ -254,7 +271,7 @@ static int _ignore_blocked_mirror_devices(struct device *dev,
(int)MINOR(log_dev)) < 0)
goto_out;
if (!(tmp_dev = dev_create_file(buf, NULL, NULL, 1)))
if (!(tmp_dev = dev_create_file(buf, NULL, NULL, 0)))
goto_out;
tmp_dev->dev = log_dev;
@ -263,8 +280,10 @@ static int _ignore_blocked_mirror_devices(struct device *dev,
}
}
if (!check_for_blocking)
return 0;
if (!check_for_blocking) {
r = 1;
goto out;
}
/*
* We avoid another system call if we can, but if a device is
@ -293,16 +312,19 @@ static int _ignore_blocked_mirror_devices(struct device *dev,
strstr(params, "handle_errors")) {
log_debug("%s: I/O blocked to mirror device",
dev_name(dev));
return 1;
goto out;
}
}
} while (next);
dm_task_destroy(dmt);
return 0;
r = 1;
out:
return 1;
if (dmt)
dm_task_destroy(dmt);
dm_free(log_health);
dm_free(images_health);
return r;
}
int device_is_usable(struct device *dev)
@ -356,7 +378,7 @@ int device_is_usable(struct device *dev)
&target_type, &params);
if (target_type && !strcmp(target_type, "mirror") &&
_ignore_blocked_mirror_devices(dev, start, length, params)) {
!_ignore_blocked_mirror_devices(dev, start, length, params)) {
log_debug("%s: Mirror device %s not usable.",
dev_name(dev), name);
goto out;