Date: Tue, 5 May 2015 11:43:56 -0400 From: Benjamin Kaduk <bjkfbsd@gmail.com> To: Julian Elischer <julian@freebsd.org> Cc: "src-committers@freebsd.org" <src-committers@freebsd.org>, "svn-src-all@freebsd.org" <svn-src-all@freebsd.org>, "svn-src-head@freebsd.org" <svn-src-head@freebsd.org> Subject: Re: svn commit: r282485 - head/lib/libc/gen Message-ID: <CAJ5_RoBPe0ZnLYbNSyOTpXgChhqU3UuORv9uZj50iUC7nV%2BTZw@mail.gmail.com> In-Reply-To: <201505051452.t45EqXXv027613@svn.freebsd.org> References: <201505051452.t45EqXXv027613@svn.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, May 5, 2015 at 10:52 AM, Julian Elischer <julian@freebsd.org> wrote: > Author: julian > Date: Tue May 5 14:52:33 2015 > New Revision: 282485 > URL: https://svnweb.freebsd.org/changeset/base/282485 > > Log: > Tweak seekdir, telldir and readdir so that when htere are deletes going > on, > as seek to teh last location saved will still work. This is needed for > Samba > to be able to correctly handle delete requests from windows. This does > not > completely fix seekdir when deletes are present but fixes the worst of > the > problems. The real solution must involve some changes to the API for eh > VFS > and getdirentries(2). > > Would it be so hard to run a spell-checker over commit messages? "teh" is not a word, nor is "htere", and "eh" only is if you're in Canada or Minnesota (not that it's the right word there anyway). > Obtained from: Panzura inc > MFC after: 1 week > > Modified: > head/lib/libc/gen/directory.3 > head/lib/libc/gen/readdir.c > head/lib/libc/gen/rewinddir.c > head/lib/libc/gen/telldir.c > head/lib/libc/gen/telldir.h > > Modified: head/lib/libc/gen/directory.3 > > ============================================================================== > --- head/lib/libc/gen/directory.3 Tue May 5 14:19:22 2015 > (r282484) > +++ head/lib/libc/gen/directory.3 Tue May 5 14:52:33 2015 > (r282485) > @@ -267,4 +267,27 @@ The invalidation of > .Fn telldir > tokens when calling > .Fn seekdir > -is non-standard. > +is non-standard. This is a compile time option. > Man page style puts the start of new sentences on a new line. > +.Pp > +The behaviour of > +.Fn telldir > +and > +.Fn seekdir > +is likely to be wrong if there are parallel unlinks happening > +and the directory is larger than one page. > +There is code to ensure that a > +.Fn seekdir > +to the location given by a > +.Fn telldir > +immediately before the last > +.Fn readdir > +will always set the correct location to return the same value as that last > +.Fn readdir > +performed. > +This is enough for some applications which want to "push back the last > entry read" E.g. Samba. > "e.g." should be offset by commas on both sides, and the capital 'E' is only appropriate at the start of a sentence. > +Seeks back to any other location, > +other than the beginning of the directory, > +may result in unexpected behaviour if deletes are present. > "behaviour" is the British English; we use American unless an entire file is already in British. > +It is hoped that this situation will be resolved with changes to > +.Fn getdirentries > +and the VFS. > > This sort of thing is more appropriate for BUGS or CAVEATS, in my opinion. > Modified: head/lib/libc/gen/readdir.c > > ============================================================================== > --- head/lib/libc/gen/readdir.c Tue May 5 14:19:22 2015 (r282484) > +++ head/lib/libc/gen/readdir.c Tue May 5 14:52:33 2015 (r282485) > @@ -54,19 +54,25 @@ _readdir_unlocked(dirp, skip) > 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); > > Modified: head/lib/libc/gen/rewinddir.c > > ============================================================================== > --- head/lib/libc/gen/rewinddir.c Tue May 5 14:19:22 2015 > (r282484) > +++ head/lib/libc/gen/rewinddir.c Tue May 5 14:52:33 2015 > (r282485) > @@ -51,6 +51,7 @@ rewinddir(dirp) > > 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 { > > Modified: head/lib/libc/gen/telldir.c > > ============================================================================== > --- head/lib/libc/gen/telldir.c Tue May 5 14:19:22 2015 (r282484) > +++ head/lib/libc/gen/telldir.c Tue May 5 14:52:33 2015 (r282485) > @@ -101,9 +101,21 @@ _seekdir(dirp, loc) > 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 */ > No stop at the end of the sentence in the comment? > + if (lp->loc_seek == dirp->dd_seek) { > + /* > + * If we go back to 0 don't make the next readdir > + * trigger a call to getdirentries() > nor here > + */ > + 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 @@ _seekdir(dirp, loc) > } > > /* > + * when we do a read and cross a boundary, any telldir we > + * just did will have wrong information in it. > No capital letter at start of sentence. Strange line wrapping (in lieu of proper paragraph break with empty line?). -Ben > + * 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 > > Modified: head/lib/libc/gen/telldir.h > > ============================================================================== > --- head/lib/libc/gen/telldir.h Tue May 5 14:19:22 2015 (r282484) > +++ head/lib/libc/gen/telldir.h Tue May 5 14:52:33 2015 (r282485) > @@ -64,5 +64,6 @@ bool _filldir(DIR *, bool); > struct dirent *_readdir_unlocked(DIR *, int); > void _reclaim_telldir(DIR *); > void _seekdir(DIR *, long); > +void _fixtelldir(DIR *dirp, long oldseek, long oldloc); > > #endif > _______________________________________________ > svn-src-all@freebsd.org mailing list > http://lists.freebsd.org/mailman/listinfo/svn-src-all > To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org" >
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAJ5_RoBPe0ZnLYbNSyOTpXgChhqU3UuORv9uZj50iUC7nV%2BTZw>