aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2015-10-09 14:54:16 +0000
committerNatanael Copa <ncopa@alpinelinux.org>2015-10-09 15:04:32 +0000
commit91a70d3906fd3614cbfd335f1cedcf2d94950c35 (patch)
tree3242f9022833071181f48721d4bf987b624e4552
parentc9891b80712725db0bd696dc0bdfcde31286d6ca (diff)
downloadmkinitfs-91a70d3906fd3614cbfd335f1cedcf2d94950c35.tar.bz2
mkinitfs-91a70d3906fd3614cbfd335f1cedcf2d94950c35.tar.xz
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.
-rw-r--r--nlplug-findfs.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/nlplug-findfs.c b/nlplug-findfs.c
index be112d9..6b2c356 100644
--- a/nlplug-findfs.c
+++ b/nlplug-findfs.c
@@ -265,6 +265,7 @@ struct recurse_opts {
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 @@ void recurse_dir(char *pathbuf, struct recurse_opts *opts)
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 @@ void recurse_dir(char *pathbuf, struct recurse_opts *opts)
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 @@ void recurse_dir(char *pathbuf, struct recurse_opts *opts)
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 @@ static int find_bootrepos(const char *devnode, const char *type,
.searchname = ".boot_repository",
.callback = bootrepo_cb,
.userdata = &repos,
+ .fastdir = 0,
};
@@ -591,6 +603,7 @@ void *trigger_thread(void *data)
.searchname = "uevent",
.callback = trigger_uevent_cb,
.userdata = NULL,
+ .fastdir = 1,
};
char path[PATH_MAX] = "/sys/bus";