Re: [musl] getdents64 lost direntries with SMB/NFS and buffer size < unknown threshold

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Nov 20, 2019 at 08:57:32PM +0100, Florian Weimer wrote:
> * Rich Felker:
> 
> > An issue was reported today on the Alpine Linux tracker at
> > https://gitlab.alpinelinux.org/alpine/aports/issues/10960 regarding
> > readdir results from SMB/NFS shares with musl libc.
> >
> > After a good deal of analysis, we determined the root cause to be that
> > the second and subsequent calls to getdents64 are dropping/skipping
> > direntries (that have not yet been deleted) when some entries were
> > deleted following the previous call. The issue appears to happen only
> > when the buffer size passed to getdents64 is below some threshold
> > greater than 2k (the size musl uses) but less than 32k (the size glibc
> > uses, with which we were unable to reproduce the issue).
> 
> >From the Gitlab issue:
> 
>   while ((dp = readdir(dir)) != NULL) {
>       unlink(dp->d_name);
>       ++file_cnt;
>   }
> 
> I'm not sure that this is valid code to delete the contents of a
> directory.  It's true that POSIX says this:

I think it is.

> | If a file is removed from or added to the directory after the most
> | recent call to opendir() or rewinddir(), whether a subsequent call
> | to readdir() returns an entry for that file is unspecified.
                                  ^^^^^^^^^^^^^

POSIX only allows both behaviors (showing or not showing) the entry
that was deleted. It does not allow deletion of one entry to cause
other entries not to be seen.

> But many file systems simply provide not the necessary on-disk data
> structures which are need to ensure stable iteration in the face of
> modification of the directory.  There are hacks, of course, such as
> compacting the on-disk directory only on file creation, which solves
> the file removal case.
> 
> For deleting an entire directory, that is not really a problem because
> you can stick another loop around this while loop which re-reads the
> directory after rewinddir.  Eventually, it will become empty.

This is still a serious problem and affects usage other than deletion
of an entire directory.

Rich



[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux