Skip to contentSkip to conversation

Query udev database to obtain device list for device cache

PATCH New Peter Rajnoha 2 participants 2 messages Mar 21, 2011

lore
Share & tools
lore
#0 lore raw

PATCH 2/3 Query udev database to obtain device list for device cache

Use libudev to obtain the list of all block device nodes and associated symlinks and construct the device cache from this information. This avoids accessing inappropriate devices or subdirectories found in /dev that is managed by udev.

There's a new lvm.conf setting that controls this: obtain_device_list_from_udev to control this feature.

If udev is not running or we're scanning a directory that is not managed by udev, the device scan will fallback to original ("full scan") mode.

LVM2 needs to be compiled with udev support (--enable-udev_sync) for this setting to take effect.

Since we need to access the libudev context quite often, we set it once in init_lvm and finalize it in lvm_fin. The common udev wrappers are in lvm-wrappers.[ch]. This avoids calling udev_new frequently (udev_new reads udev config file etc.).

Peter

---
 doc/example.conf.in             |   10 +++
 lib/commands/toolcontext.c      |    4 +
 lib/config/defaults.h           |    1 +
 lib/device/dev-cache.c          |  130 +++++++++++++++++++++++++++++++++++---
 lib/device/dev-cache.h          |    1 +
 lib/filters/filter-persistent.c |   14 ++++
 lib/misc/lvm-globals.c          |   11 +++
 lib/misc/lvm-globals.h          |    2 +
 lib/misc/lvm-wrappers.c         |   72 +++++++++++++++++++++
 lib/misc/lvm-wrappers.h         |    9 +++
 make.tmpl.in                    |    2 +-
 tools/lvmcmdline.c              |    3 +
 12 files changed, 247 insertions(+), 12 deletions(-)
doc/example.conf.in +10 -0
index 6e9f1b9..2e0d8b6 100644
@@ -19,6 +19,16 @@ devices {
     # to use with LVM2.
     scan = [ "/dev" ]
 
+    # If set, the cache of block device nodes with all associated symlinks
+    # will be constructed out of the existing udev database content.
+    # This avoids using and opening any inapplicable non-block devices or
+    # subdirectories found in the device directory. This setting is applied
+    # to udev-managed device directory only, other directories will be scanned
+    # fully. LVM2 needs to be compiled with udev support for this setting to
+    # take effect. N.B. Any device node or symlink not managed by udev in
+    # udev directory will be ignored with this setting on.
+    # obtain_device_list_from_udev = 1
+
     # If several entries in the scanned directories correspond to the
     # same block device and the tools need to display a name for device,
     # all the pathnames are matched against each item in the following
lib/commands/toolcontext.c +4 -0
index 30c8fc6..4e63075 100644
@@ -592,6 +592,10 @@ static int _init_dev_cache(struct cmd_context *cmd)
 		return 1;
 	}
 
+	init_obtain_device_list_from_udev(udev_is_running() ?
+		find_config_tree_bool(cmd, "devices/obtain_device_list_from_udev",
+				      DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV) : 0);
+
 	for (cv = cn->v; cv; cv = cv->next) {
 		if (cv->type != CFG_STRING) {
 			log_error("Invalid string in config file: "
lib/config/defaults.h +1 -0
index 2e20f93..c554058 100644
@@ -29,6 +29,7 @@
 
 #define DEFAULT_DEV_DIR "/dev"
 #define DEFAULT_PROC_DIR "/proc"
+#define DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV 1
 #define DEFAULT_SYSFS_SCAN 1
 #define DEFAULT_MD_COMPONENT_DETECTION 1
 #define DEFAULT_MD_CHUNK_ALIGNMENT 1
lib/device/dev-cache.c +119 -11

194 lines not on this page · raw message

lib/device/dev-cache.h +1 -0
index c1c86d6..5db5226 100644
@@ -17,6 +17,7 @@
 #define _LVM_DEV_CACHE_H
 
 #include "device.h"
+#include "lvm-wrappers.h"
 
 /*
  * predicate for devices.
lib/filters/filter-persistent.c +14 -0
index 3025e68..cb0b695 100644
@@ -103,6 +103,17 @@ int persistent_filter_load(struct dev_filter *f, struct config_tree **cft_out)
 	struct stat info;
 	int r = 0;
 
+	if (obtain_device_list_from_udev()) {
+		if (!stat(pf->file, &info)) {
+			log_very_verbose("Obtaining device list from "
+					 "udev. Removing obolete %s.",
+					 pf->file);
+			if (unlink(pf->file) < 0)
+				log_sys_error("unlink", pf->file);
+		}
+		return 1;
+	}
+
 	if (!stat(pf->file, &info))
 		pf->ctime = info.st_ctime;
 	else {
@@ -180,6 +191,9 @@ int persistent_filter_dump(struct dev_filter *f, int merge_existing)
 	int lockfd;
 	int r = 0;
 
+	if (obtain_device_list_from_udev())
+		return 1;
+
 	if (!f)
 		return_0;
 	pf = (struct pfilter *) f->private;
lib/misc/lvm-globals.c +11 -0
index 7adb5e3..f489f1d 100644
@@ -28,6 +28,7 @@ static int _test = 0;
 static int _md_filtering = 0;
 static int _pvmove = 0;
 static int _full_scan_done = 0;	/* Restrict to one full scan during each cmd */
+static int _obtain_device_list_from_udev = DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV;
 static int _trust_cache = 0; /* Don't scan when incomplete VGs encountered */
 static int _debug_level = 0;
 static int _log_cmd_name = 0;
@@ -72,6 +73,11 @@ void init_full_scan_done(int level)
 	_full_scan_done = level;
 }
 
+void init_obtain_device_list_from_udev(int device_list_from_udev)
+{
+	_obtain_device_list_from_udev = device_list_from_udev;
+}
+
 void init_trust_cache(int trustcache)
 {
 	_trust_cache = trustcache;
@@ -185,6 +191,11 @@ int full_scan_done()
 	return _full_scan_done;
 }
 
+int obtain_device_list_from_udev()
+{
+	return _obtain_device_list_from_udev;
+}
+
 int trust_cache()
 {
 	return _trust_cache;
lib/misc/lvm-globals.h +2 -0
index bb383f4..6694da6 100644
@@ -25,6 +25,7 @@ void init_test(int level);
 void init_md_filtering(int level);
 void init_pvmove(int level);
 void init_full_scan_done(int level);
+void init_obtain_device_list_from_udev(int device_list_from_udev);
 void init_trust_cache(int trustcache);
 void init_debug(int level);
 void init_cmd_name(int status);
@@ -48,6 +49,7 @@ int test_mode(void);
 int md_filtering(void);
 int pvmove_mode(void);
 int full_scan_done(void);
+int obtain_device_list_from_udev(void);
 int trust_cache(void);
 int verbose_level(void);
 int debug_level(void);
lib/misc/lvm-wrappers.c +72 -0

78 lines not on this page · raw message

lib/misc/lvm-wrappers.h +9 -0
index 19a7f03..e43f831 100644
@@ -16,6 +16,15 @@
 #ifndef _LVM_WRAPPERS_H
 #define _LVM_WRAPPERS_H
 
+#ifdef UDEV_SYNC_SUPPORT
+#include <libudev.h>
+struct udev *udev_get_library_context(void);
+#endif
+
+int udev_init_library_context(void);
+void udev_fin_library_context(void);
+int udev_is_running(void);
+
 int lvm_getpagesize(void);
 
 /*
make.tmpl.in +1 -1
index 5380b5e..cd8ae35 100644
@@ -38,7 +38,7 @@ CLDFLAGS += @CLDFLAGS@
 LDDEPS += @LDDEPS@
 LDFLAGS += @LDFLAGS@
 LIB_SUFFIX = @LIB_SUFFIX@
-LVMINTERNAL_LIBS = -llvm-internal $(DL_LIBS)
+LVMINTERNAL_LIBS = -llvm-internal $(UDEV_LIBS) $(DL_LIBS)
 DL_LIBS = @DL_LIBS@
 PTHREAD_LIBS = @PTHREAD_LIBS@
 READLINE_LIBS = @READLINE_LIBS@
tools/lvmcmdline.c +3 -0
index 45c3703..efe7f4e 100644
@@ -1282,6 +1282,8 @@ struct cmd_context *init_lvm(void)
 {
 	struct cmd_context *cmd;
 
+	(void) udev_init_library_context();
+
 	if (!(cmd = create_toolcontext(0, NULL)))
 		return_NULL;
 
@@ -1313,6 +1315,7 @@ void lvm_fin(struct cmd_context *cmd)
 {
 	_fin_commands();
 	destroy_toolcontext(cmd);
+	udev_fin_library_context();
 }
 
 static int _run_script(struct cmd_context *cmd, int argc, char **argv)
#1 lore raw

PATCH 2/3 Query udev database to obtain device list for device cache

Quoted 3 lines · Peter Rajnoha

Use libudev to obtain the list of all block device nodes and associated symlinks and construct the device cache from this information. This avoids accessing inappropriate devices or subdirectories found in /dev that is managed by udev.

ack. it need some testing but definitely it should go in.

Milan