summaryrefslogtreecommitdiff
path: root/lib/libc
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@cvs.openbsd.org>2013-11-06 20:35:26 +0000
committerIngo Schwarze <schwarze@cvs.openbsd.org>2013-11-06 20:35:26 +0000
commitb1d8f56c13f4be13930487b55b7a6da3f0dc6ed2 (patch)
tree975e465f6c824329201b97e380c2eacdbed31003 /lib/libc
parent11cf532e7208042d2808063a8b65ab64baad29bb (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.c3
-rw-r--r--lib/libc/gen/seekdir.c69
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);