From a198224666e4116a0eb60fa48b43551f733417e1 Mon Sep 17 00:00:00 2001 From: Zdenek Kabelac Date: Wed, 22 May 2024 13:29:35 +0200 Subject: [PATCH] dev-cache: skip scanning known blockless dirs Skip scan and stat() for dirs and nodes within known /dev/ paths, where no block devices are located. Also strlen(_cache.dev_dir) just once. TODO: add more dirs to _no_scan (configurable via lvm.conf ?) --- lib/device/dev-cache.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c index 93fe7284c..acc2f13dc 100644 --- a/lib/device/dev-cache.c +++ b/lib/device/dev-cache.c @@ -53,6 +53,7 @@ static struct { struct dm_regex *preferred_names_matcher; const char *dev_dir; + size_t dev_dir_len; int has_scanned; dev_t st_dev; struct dm_list dirs; @@ -205,10 +206,9 @@ static int _builtin_preference(const char *path0, const char *path1, static int _apply_builtin_path_preference_rules(const char *path0, const char *path1) { - size_t devdir_len; + size_t devdir_len = _cache.dev_dir_len; int r; - devdir_len = strlen(_cache.dev_dir); if (!strncmp(path0, _cache.dev_dir, devdir_len) && !strncmp(path1, _cache.dev_dir, devdir_len)) { @@ -878,6 +878,20 @@ static size_t _collapse_slashes(char *str) static int _insert_dir(const char *dir) { + /* alphanetically! sorted list used by bsearch of + * /dev subdirectories that should not contain + * any block device, so no reason to scan them. */ + static const char _no_scan[][12] = { + "bsg/", + "bus/", + "char/", + "cpu/", + "dma_heap/", + "dri/", + "input/", + "snd/", + "usb/", + }; int n, dirent_count, r = 1; struct dirent **dirent = NULL; char path[PATH_MAX]; @@ -892,6 +906,16 @@ static int _insert_dir(const char *dir) if (len && path[len - 1] != '/') path[len++] = '/'; + if ((len < (5 + sizeof(_no_scan[0]))) && (strncmp("/dev/", path, 5) == 0) && (len > 5)) { + path[len] = 0; + if (bsearch(path + 5, _no_scan, DM_ARRAY_SIZE(_no_scan), sizeof(_no_scan[0]), + (int (*)(const void*, const void*))strcmp)) { + /* Skip insertion of directories that can't have block devices */ + log_debug("Skipping \"%s\" (no block devices).", path); + return 1; + } + } + dirent_count = scandir(dir, &dirent, NULL, alphasort); if (dirent_count > 0) { for (n = 0; n < dirent_count; n++) { @@ -1321,6 +1345,7 @@ int dev_cache_init(struct cmd_context *cmd) goto bad; } + _cache.dev_dir_len = strlen(_cache.dev_dir); dm_list_init(&_cache.dirs); if (!_init_preferred_names(cmd))