Page MenuHomeFreeBSD

D2410.diff
No OneTemporary

D2410.diff

Index: lib/libc/gen/readdir.c
===================================================================
--- lib/libc/gen/readdir.c
+++ lib/libc/gen/readdir.c
@@ -54,19 +54,25 @@
int skip;
{
struct dirent *dp;
+ long initial_seek;
+ long initial_loc = 0;
for (;;) {
if (dirp->dd_loc >= dirp->dd_size) {
if (dirp->dd_flags & __DTF_READALL)
return (NULL);
+ initial_loc = dirp->dd_loc;
+ dirp->dd_flags &= ~__DTF_SKIPREAD;
dirp->dd_loc = 0;
}
if (dirp->dd_loc == 0 &&
!(dirp->dd_flags & (__DTF_READALL | __DTF_SKIPREAD))) {
+ initial_seek = dirp->dd_seek;
dirp->dd_size = _getdirentries(dirp->dd_fd,
dirp->dd_buf, dirp->dd_len, &dirp->dd_seek);
if (dirp->dd_size <= 0)
return (NULL);
+ _fixtelldir(dirp, initial_seek, initial_loc);
}
dirp->dd_flags &= ~__DTF_SKIPREAD;
dp = (struct dirent *)(dirp->dd_buf + dirp->dd_loc);
Index: lib/libc/gen/rewinddir.c
===================================================================
--- lib/libc/gen/rewinddir.c
+++ lib/libc/gen/rewinddir.c
@@ -51,6 +51,7 @@
if (__isthreaded)
_pthread_mutex_lock(&dirp->dd_lock);
+ dirp->dd_flags &= ~__DTF_SKIPREAD; /* current contents are invalid */
if (dirp->dd_flags & __DTF_READALL)
_filldir(dirp, false);
else {
Index: lib/libc/gen/telldir.h
===================================================================
--- lib/libc/gen/telldir.h
+++ lib/libc/gen/telldir.h
@@ -64,5 +64,6 @@
struct dirent *_readdir_unlocked(DIR *, int);
void _reclaim_telldir(DIR *);
void _seekdir(DIR *, long);
+void _fixtelldir(DIR *dirp, long oldseek, long oldloc);
#endif
Index: lib/libc/gen/telldir.c
===================================================================
--- lib/libc/gen/telldir.c
+++ lib/libc/gen/telldir.c
@@ -101,9 +101,21 @@
return;
if (lp->loc_loc == dirp->dd_loc && lp->loc_seek == dirp->dd_seek)
return;
+ /* If it's within the same chunk of data, don't bother reloading */
+ if (lp->loc_seek == dirp->dd_seek) {
+ /*
+ * If we go back to 0 don't make the next readdir
+ * trigger a call to getdirentries()
+ */
+ if (lp->loc_loc == 0)
+ dirp->dd_flags |= __DTF_SKIPREAD;
+ dirp->dd_loc = lp->loc_loc;
+ return;
+ }
(void) lseek(dirp->dd_fd, (off_t)lp->loc_seek, SEEK_SET);
dirp->dd_seek = lp->loc_seek;
dirp->dd_loc = 0;
+ dirp->dd_flags &= ~__DTF_SKIPREAD; /* current contents are invalid */
while (dirp->dd_loc < lp->loc_loc) {
dp = _readdir_unlocked(dirp, 0);
if (dp == NULL)
@@ -112,6 +124,27 @@
}
/*
+ * when we do a read and cross a boundary, any telldir we
+ * just did will have wrong information in it.
+ * We need to move it from "beyond the end of the previous chunk"
+ * to "the beginning of the new chunk"
+ */
+void
+_fixtelldir(DIR *dirp, long oldseek, long oldloc)
+{
+ struct ddloc *lp;
+
+ lp = LIST_FIRST(&dirp->dd_td->td_locq);
+ if (lp != NULL) {
+ if (lp->loc_loc == oldloc &&
+ lp->loc_seek == oldseek) {
+ lp->loc_seek = dirp->dd_seek;
+ lp->loc_loc = dirp->dd_loc;
+ }
+ }
+}
+
+/*
* Reclaim memory for telldir cookies which weren't used.
*/
void

File Metadata

Mime Type
text/plain
Expires
Thu, Feb 27, 6:47 AM (18 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16863915
Default Alt Text
D2410.diff (3 KB)

Event Timeline