[lvm-devel] [PATCH] Fix segfault when destroying in-use filters in pvs -a.

Milan Broz mbroz at redhat.com
Wed Mar 10 21:43:27 UTC 2010


Because pvs -a iterate throught the whole device cache
we should not refresh filters inside iteration.

Fix it by introducing simple reference counter and test
it in refresh_filters() call.

Fixes https://bugzilla.redhat.com/show_bug.cgi?id=571963
---
 lib/commands/toolcontext.c      |    5 +++++
 lib/device/dev-cache.c          |    2 ++
 lib/device/dev-cache.h          |    1 +
 lib/filters/filter-composite.c  |    1 +
 lib/filters/filter-md.c         |    1 +
 lib/filters/filter-persistent.c |    1 +
 lib/filters/filter-regex.c      |    1 +
 lib/filters/filter-sysfs.c      |    1 +
 lib/filters/filter.c            |    1 +
 9 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index 7aac361..a78efe8 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -1240,6 +1240,11 @@ int refresh_filters(struct cmd_context *cmd)
 {
 	int r, saved_ignore_suspended_devices = ignore_suspended_devices();
 
+	if (cmd->filter && cmd->filter->in_use) {
+		log_debug("Skipping filter refresh currently in use.");
+		return 1;
+	}
+
 	if (cmd->filter) {
 		cmd->filter->destroy(cmd->filter);
 		cmd->filter = NULL;
diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c
index 45c0e8f..933d83a 100644
--- a/lib/device/dev-cache.c
+++ b/lib/device/dev-cache.c
@@ -743,12 +743,14 @@ struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan)
 
 	di->current = btree_first(_cache.devices);
 	di->filter = f;
+	di->filter->in_use++;
 
 	return di;
 }
 
 void dev_iter_destroy(struct dev_iter *iter)
 {
+	iter->filter->in_use--;
 	dm_free(iter);
 }
 
diff --git a/lib/device/dev-cache.h b/lib/device/dev-cache.h
index 96bf013..9314a5c 100644
--- a/lib/device/dev-cache.h
+++ b/lib/device/dev-cache.h
@@ -24,6 +24,7 @@
 struct dev_filter {
 	int (*passes_filter) (struct dev_filter * f, struct device * dev);
 	void (*destroy) (struct dev_filter * f);
+	unsigned in_use;
 	void *private;
 };
 
diff --git a/lib/filters/filter-composite.c b/lib/filters/filter-composite.c
index d1606d3..55aedaf 100644
--- a/lib/filters/filter-composite.c
+++ b/lib/filters/filter-composite.c
@@ -70,6 +70,7 @@ struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
 	cft->passes_filter = _and_p;
 	cft->destroy = _composite_destroy;
 	cft->private = filters_copy;
+	cft->in_use = 0;
 
 	return cft;
 }
diff --git a/lib/filters/filter-md.c b/lib/filters/filter-md.c
index c1ecff7..0e9857d 100644
--- a/lib/filters/filter-md.c
+++ b/lib/filters/filter-md.c
@@ -60,6 +60,7 @@ struct dev_filter *md_filter_create(void)
 	f->passes_filter = _ignore_md;
 	f->destroy = _destroy;
 	f->private = NULL;
+	f->in_use = 0;
 
 	return f;
 }
diff --git a/lib/filters/filter-persistent.c b/lib/filters/filter-persistent.c
index 9243a94..3c7639c 100644
--- a/lib/filters/filter-persistent.c
+++ b/lib/filters/filter-persistent.c
@@ -317,6 +317,7 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
 	f->passes_filter = _lookup_p;
 	f->destroy = _persistent_destroy;
 	f->private = pf;
+	f->in_use = 0;
 
 	return f;
 
diff --git a/lib/filters/filter-regex.c b/lib/filters/filter-regex.c
index 1d415a4..7903314 100644
--- a/lib/filters/filter-regex.c
+++ b/lib/filters/filter-regex.c
@@ -207,6 +207,7 @@ struct dev_filter *regex_filter_create(struct config_value *patterns)
 	f->passes_filter = _accept_p;
 	f->destroy = _regex_destroy;
 	f->private = rf;
+	f->in_use = 0;
 	return f;
 
       bad:
diff --git a/lib/filters/filter-sysfs.c b/lib/filters/filter-sysfs.c
index 1220b3a..30e29b3 100644
--- a/lib/filters/filter-sysfs.c
+++ b/lib/filters/filter-sysfs.c
@@ -317,6 +317,7 @@ struct dev_filter *sysfs_filter_create(const char *sysfs_dir)
 	f->passes_filter = _accept_p;
 	f->destroy = _destroy;
 	f->private = ds;
+	f->in_use = 0;
 	return f;
 
  bad:
diff --git a/lib/filters/filter.c b/lib/filters/filter.c
index b33d099..7e3edfe 100644
--- a/lib/filters/filter.c
+++ b/lib/filters/filter.c
@@ -319,6 +319,7 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
 	f->passes_filter = _passes_lvm_type_device_filter;
 	f->destroy = lvm_type_filter_destroy;
 	f->private = NULL;
+	f->in_use = 0;
 
 	if (!_scan_proc_dev(proc, cn)) {
 		dm_free(f);
-- 
1.7.0




More information about the lvm-devel mailing list