Date: Tue, 22 Aug 2017 07:42:36 -0700 From: Conrad Meyer <cem@freebsd.org> To: freebsd-fs@freebsd.org Subject: Re: Can telldir() == 0 value be made special? Message-ID: <CAG6CVpVViqnbGuVn_JETBC5Q0NoYfC4VJK7iWjEfA7tFurQ2ag@mail.gmail.com> In-Reply-To: <87bmn7kf3b.fsf@vostro.rath.org> References: <87bmn7kf3b.fsf@vostro.rath.org>
next in thread | previous in thread | raw e-mail | index | archive | help
Hi Nikolaus, As you have surmised, DIR* seekpoints are created dynamically whenever requested by user's telldir() call: https://github.com/freebsd/freebsd/blob/master/lib/libc/gen/telldir.c#L53 I believe we could special case zero without breaking ABI compatibility of correct programs. Something like this: --- a/lib/libc/gen/telldir.c +++ b/lib/libc/gen/telldir.c @@ -70,6 +70,20 @@ telldir(DIR *dirp) } } if (lp =3D=3D NULL) { + /* Create special zero telldir entry, similar to Linux */ + if (dirp->dd_td->td_loccnt =3D=3D 0 && dirp->dd_loc !=3D 0)= { + lp =3D malloc(sizeof(struct ddloc)); + if (lp =3D=3D NULL) { + if (__isthreaded) + _pthread_mutex_unlock(&dirp->dd_loc= k); + return (-1); + } + lp->loc_index =3D dirp->dd_td->td_loccnt++; + lp->loc_seek =3D 0; + lp->loc_loc =3D 0; + LIST_INSERT_HEAD(&dirp->dd_td->td_locq, lp, loc_lqe= ); + } + lp =3D malloc(sizeof(struct ddloc)); if (lp =3D=3D NULL) { if (__isthreaded) I don't know if there are any downsides to special-casing zero like this, other than additional code complexity. Best, Conrad On Tue, Aug 22, 2017 at 4:38 AM, Nikolaus Rath <Nikolaus@rath.org> wrote: > Hello, > > I am trying to debug a test failure of libfuse under FreeBSD. I believe > I have reduced it to the following root cause: > > Consider the following program: > > #include <stdio.h> > #include <dirent.h> > #include <sys/types.h> > > int main(void) { > struct dirent *e =3D NULL; > DIR *dirp; > > printf("opendir...\n"); > dirp =3D opendir("/"); > if(dirp =3D=3D NULL) { > perror("opendir"); > return 1; > } > printf("telldir: %ld\n", telldir(dirp)); > e =3D readdir(dirp); > printf("readdir: %s\n", e->d_name); > printf("telldir: %ld\n", telldir(dirp)); > e =3D readdir(dirp); > printf("readdir: %s\n", e->d_name); > printf("closedir..\n"); > closedir(dirp); > > printf("opendir...\n"); > dirp =3D opendir("/"); > if(dirp =3D=3D NULL) { > perror("opendir"); > return 1; > } > e =3D readdir(dirp); > printf("readdir: %s\n", e->d_name); > printf("telldir: %ld\n", telldir(dirp)); > e =3D readdir(dirp); > printf("readdir: %s\n", e->d_name); > printf("closedir..\n"); > closedir(dirp); > > return 0; > } > > > Under FreeBSD, running it gives: > > # ./simple > opendir... > telldir: 0 > readdir: . > telldir: 1 > readdir: .. > closedir.. > opendir... > readdir: . > telldir: 0 > readdir: .. > closedir.. > > In other words, if telldir() is called right after opendir(), it gives > an offset of zero. But if telldir() is called only after the first > readdir() call, it also gives an offset of zero. My hypothesis is that > FreeBSD actually just enumerates the different telldir() calls - is that > correct? > > Now, the offsets returned by telldir() are documented to be valid only > within a given *dirp, so FreeBSD isn't doing anything wrong. > > However, having different meanings even for an offset of zero causes > problems for libfuse, because under Linux an offset of zero is > guaranteed to mean "first entry". This is reflected in the definition of > the fuse readdir() function which always receives an *offset* parameter > that needs to have a definite value even when telldir() was never > called. If zero is suddenly also a valid telldir() return value that may > indicate some other position in the stream, things get complicated. > > Now, I think I managed to work around that by shifting all offsets by > one, but that is awkward (and I may have overlooked some problems that > the unit tests don't cover). So I am wondering: > > Is there a reason why the FreeBSD kernel could not start enumerating > telldir() offsets with 1, so that 0 can always have the same meaning? > > > Best, > -Nikolaus > > -- > GPG Fingerprint: ED31 791B 2C5C 1613 AF38 8B8A D113 FCAC 3C4E 599F > > =C2=BBTime flies like an arrow, fruit flies like a Banana.= =C2=AB > _______________________________________________ > freebsd-fs@freebsd.org mailing list > https://lists.freebsd.org/mailman/listinfo/freebsd-fs > To unsubscribe, send any mail to "freebsd-fs-unsubscribe@freebsd.org"
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAG6CVpVViqnbGuVn_JETBC5Q0NoYfC4VJK7iWjEfA7tFurQ2ag>