ref: 91a70d3906fd3614cbfd335f1cedcf2d94950c35
parent: c9891b80712725db0bd696dc0bdfcde31286d6ca
author: Natanael Copa <ncopa@alpinelinux.org>
date: Fri Oct 9 09:54:16 CDT 2015
nlplug-findfs: avoid lstat syscall wen scanning /sys if possible There are ~10k entries in /sys so we want be fast. Not all filesystems supports dirent filed d_type, (iso9660 for example) so we need use lstat to find directories. However, we know that sysfs supports it, so we can avoid 10k lstat syscalls. This might be noticiable difference on rpi.
--- a/nlplug-findfs.c
+++ b/nlplug-findfs.c
@@ -265,6 +265,7 @@
const char *searchname;
void (*callback)(const char *, const void *);
void *userdata;
+ int fastdir; /* avoid lstat on sysfs which we know support d_type */
};
/* pathbuf needs hold PATH_MAX chars */
@@ -280,6 +281,7 @@
struct stat st;
size_t pathlen = strlen(pathbuf);
size_t namelen = strlen(entry->d_name);
+ int is_dir;
/* d_type is not supported by all filesystems so we need
lstat */
@@ -291,12 +293,21 @@
pathbuf[pathlen] = '/';
strcpy(&pathbuf[pathlen+1], entry->d_name);
- if (lstat(pathbuf, &st) < 0) {
- dbg("%s: %s", pathbuf, strerror(errno));
- goto next;
+ if (opts->fastdir) {
+ /* avoid the lstat syscall for sysfs which we know
+ support the d_type field. */
+ is_dir = entry->d_type & DT_DIR;
+ } else {
+ /* some filesystems like iso9660 does not support
+ the d_type so we use lstat */
+ if (lstat(pathbuf, &st) < 0) {
+ dbg("%s: %s", pathbuf, strerror(errno));
+ goto next;
+ }
+ is_dir = S_ISDIR(st.st_mode);
}
- if (S_ISDIR(st.st_mode)) {
+ if (is_dir) {
if (entry->d_name[0] == '.')
goto next;
} else if (opts->searchname
@@ -304,7 +315,7 @@
goto next;
}
- if (S_ISDIR(st.st_mode))
+ if (is_dir)
recurse_dir(pathbuf, opts);
else
opts->callback(pathbuf, opts->userdata);
@@ -376,6 +387,7 @@
.searchname = ".boot_repository",
.callback = bootrepo_cb,
.userdata = &repos,
+ .fastdir = 0,
};
@@ -591,6 +603,7 @@
.searchname = "uevent",
.callback = trigger_uevent_cb,
.userdata = NULL,
+ .fastdir = 1,
};
char path[PATH_MAX] = "/sys/bus";