mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
dev-cache: fix mem corruption on refresh context
When lvm2 command works with clvmd and uses locking in wrong way, it may 'leak' certain file descriptors in opened (incorrect) state. dev_cache_exit then destroys memory pool of cached devices, while _open_devices list in dev-io.c was still referencing them if they were still opened. Patch properly calls _close() function to 'self-heal' from this invalid state, but it will report internal error (so execution with abort_on_internal_error causes immediate death). On the normal 'execution', error is only reported, but memory state is corrected, and linked list is not referencing devices from released mempool. For crash see: https://bugzilla.redhat.com/show_bug.cgi?id=1073886
This commit is contained in:
parent
d29fe919e6
commit
68d13b2517
@ -1,5 +1,6 @@
|
|||||||
Version 2.02.106 -
|
Version 2.02.106 -
|
||||||
====================================
|
====================================
|
||||||
|
Fix memory corruption in cmd context refresh if clvmd leaks opened device.
|
||||||
Reinitialise lvmcache properly on fork to fix premature polldaemon exit.
|
Reinitialise lvmcache properly on fork to fix premature polldaemon exit.
|
||||||
Add 'lvm dumpconfig --type diff' to show differences from defaults.
|
Add 'lvm dumpconfig --type diff' to show differences from defaults.
|
||||||
Fix swap signature detection for devices smaller then 2MB.
|
Fix swap signature detection for devices smaller then 2MB.
|
||||||
|
@ -1604,7 +1604,8 @@ int refresh_toolcontext(struct cmd_context *cmd)
|
|||||||
cmd->filter->destroy(cmd->filter);
|
cmd->filter->destroy(cmd->filter);
|
||||||
cmd->filter = NULL;
|
cmd->filter = NULL;
|
||||||
}
|
}
|
||||||
dev_cache_exit();
|
if (!dev_cache_exit())
|
||||||
|
stack;
|
||||||
_destroy_dev_types(cmd);
|
_destroy_dev_types(cmd);
|
||||||
_destroy_tags(cmd);
|
_destroy_tags(cmd);
|
||||||
|
|
||||||
|
@ -760,21 +760,38 @@ int dev_cache_init(struct cmd_context *cmd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _check_closed(struct device *dev)
|
static int _check_for_open_devices(int close_immediate)
|
||||||
{
|
{
|
||||||
if (dev->fd >= 0)
|
struct device *dev;
|
||||||
log_error("Device '%s' has been left open.", dev_name(dev));
|
struct dm_hash_node *n;
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
|
dm_hash_iterate(n, _cache.names) {
|
||||||
|
dev = (struct device *) dm_hash_get_data(_cache.names, n);
|
||||||
|
if (dev->fd >= 0) {
|
||||||
|
log_error("Device '%s' has been left open (%d).",
|
||||||
|
dev_name(dev), dev->open_count);
|
||||||
|
r++;
|
||||||
|
if (close_immediate)
|
||||||
|
dev_close_immediate(dev);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _check_for_open_devices(void)
|
return r;
|
||||||
{
|
|
||||||
dm_hash_iter(_cache.names, (dm_hash_iterate_fn) _check_closed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dev_cache_exit(void)
|
int dev_cache_check_for_open_devices(void)
|
||||||
{
|
{
|
||||||
|
return _check_for_open_devices(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_cache_exit(void)
|
||||||
|
{
|
||||||
|
int cnt = 0;
|
||||||
|
|
||||||
if (_cache.names)
|
if (_cache.names)
|
||||||
_check_for_open_devices();
|
if ((cnt = _check_for_open_devices(1)) > 0)
|
||||||
|
log_error(INTERNAL_ERROR "%d device(s) have been closed.", cnt);
|
||||||
|
|
||||||
if (_cache.preferred_names_matcher)
|
if (_cache.preferred_names_matcher)
|
||||||
_cache.preferred_names_matcher = NULL;
|
_cache.preferred_names_matcher = NULL;
|
||||||
@ -793,6 +810,8 @@ void dev_cache_exit(void)
|
|||||||
_cache.has_scanned = 0;
|
_cache.has_scanned = 0;
|
||||||
dm_list_init(&_cache.dirs);
|
dm_list_init(&_cache.dirs);
|
||||||
dm_list_init(&_cache.files);
|
dm_list_init(&_cache.files);
|
||||||
|
|
||||||
|
return (cnt == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int dev_cache_add_dir(const char *path)
|
int dev_cache_add_dir(const char *path)
|
||||||
|
@ -36,7 +36,8 @@ struct dev_filter {
|
|||||||
*/
|
*/
|
||||||
struct cmd_context;
|
struct cmd_context;
|
||||||
int dev_cache_init(struct cmd_context *cmd);
|
int dev_cache_init(struct cmd_context *cmd);
|
||||||
void dev_cache_exit(void);
|
int dev_cache_check_for_open_devices(void);
|
||||||
|
int dev_cache_exit(void);
|
||||||
|
|
||||||
/* Trigger(1) or avoid(0) a scan */
|
/* Trigger(1) or avoid(0) a scan */
|
||||||
void dev_cache_scan(int do_scan);
|
void dev_cache_scan(int do_scan);
|
||||||
|
Loading…
Reference in New Issue
Block a user