diff options
author | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2013-11-06 20:35:26 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2013-11-06 20:35:26 +0000 |
commit | b1d8f56c13f4be13930487b55b7a6da3f0dc6ed2 (patch) | |
tree | 975e465f6c824329201b97e380c2eacdbed31003 /lib/libc | |
parent | 11cf532e7208042d2808063a8b65ab64baad29bb (diff) |
Search the userland buffer of dirent structures before falling back to
getdents(2). No functional change, but considerable speedup in many
cases, see http://marc.info/?l=openbsd-tech&m=138369623117934 for some
approximate numbers.
ok guenther@, "good diagnosis" deraadt@
Diffstat (limited to 'lib/libc')
-rw-r--r-- | lib/libc/gen/opendir.c | 3 | ||||
-rw-r--r-- | lib/libc/gen/seekdir.c | 69 |
2 files changed, 46 insertions, 26 deletions
diff --git a/lib/libc/gen/opendir.c b/lib/libc/gen/opendir.c index 86038754999..6b9adad9c79 100644 --- a/lib/libc/gen/opendir.c +++ b/lib/libc/gen/opendir.c @@ -1,4 +1,4 @@ -/* $OpenBSD: opendir.c,v 1.25 2013/10/06 17:57:11 guenther Exp $ */ +/* $OpenBSD: opendir.c,v 1.26 2013/11/06 20:35:25 schwarze Exp $ */ /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -111,6 +111,7 @@ __fdopendir(int fd) return (NULL); } + dirp->dd_size = 0; dirp->dd_loc = 0; dirp->dd_fd = fd; dirp->dd_lock = NULL; diff --git a/lib/libc/gen/seekdir.c b/lib/libc/gen/seekdir.c index 66c9bbca209..f0523af677c 100644 --- a/lib/libc/gen/seekdir.c +++ b/lib/libc/gen/seekdir.c @@ -1,31 +1,18 @@ -/* $OpenBSD: seekdir.c,v 1.10 2013/11/05 20:36:51 schwarze Exp $ */ +/* $OpenBSD: seekdir.c,v 1.11 2013/11/06 20:35:25 schwarze Exp $ */ /* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. + * Copyright (c) 2013 Ingo Schwarze <schwarze@openbsd.org> * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <dirent.h> @@ -41,7 +28,39 @@ void seekdir(DIR *dirp, long loc) { + struct dirent *dp; + + /* + * First check whether the directory entry to seek for + * is still buffered in the directory structure in memory. + */ + _MUTEX_LOCK(&dirp->dd_lock); + for (dirp->dd_loc = 0; + dirp->dd_loc < dirp->dd_size; + dirp->dd_loc += dp->d_reclen) { + dp = (struct dirent *)(dirp->dd_buf + dirp->dd_loc); + if (dp->d_off != loc) + continue; + + /* + * Entry found in the buffer, use it. If readdir(3) + * follows, this will save us a getdents(2) syscall. + * Note that d_off is the offset of the _next_ entry, + * so advance dd_loc. + */ + + dirp->dd_loc += dp->d_reclen; + dirp->dd_curpos = loc; + _MUTEX_UNLOCK(&dirp->dd_lock); + return; + } + + /* + * The entry is not in the buffer, prepare a call to getdents(2). + * In particular, invalidate dd_loc. + */ + dirp->dd_loc = 0; dirp->dd_curpos = lseek(dirp->dd_fd, loc, SEEK_SET); _MUTEX_UNLOCK(&dirp->dd_lock); |