[prev in list] [next in list] [prev in thread] [next in thread]
List: wine-devel
Subject: Re: [PATCH 2/4] ntdll: Fix read_directory_getdirentries().
From: Matteo Bruni <matteo.mystral () gmail ! com>
Date: 2015-08-31 20:29:46
Message-ID: CABvNrtOnJ_6xzq4FmMOBxsjBuhdn6=roBVCK6bjn8OUyhmgmVQ () mail ! gmail ! com
[Download RAW message or body]
2015-08-31 21:09 GMT+02:00 Ken Thomases <ken@codeweavers.com>:
> On Aug 28, 2015, at 2:56 PM, Matteo Bruni <matteo.mystral@gmail.com> wrote:
> >
> > We could swap the "." and ".." entries with the first two entries
> > returned from getdirentries(), in the same vein as
> > read_directory_getdents(). That should work but I'm not sure it's much
> > of an improvement overall.
>
> Yikes! I just had a look at read_directory_getdents(). It uses a static variable \
> to store the information needed to know if it should enumerate ".." or a real \
> entry. That's terrible. It's not thread safe. It's not even safe against \
> enumerating two directories item by item in alternation.
Actually it should be safe for both. About thread safety, check
NtQueryDirectoryFile(), the various read_directory_* helpers are
protected by the "dir_section" critical section. BTW notice that fd is
opened by changing the current directory with fchdir().
As for the enumerating multiple directories by alternation, look at
the last_dir_id checks and related code.
Yes, all this is not nice by any means.
> > I'm attaching a v2 of the patch with your points addressed.
>
> > + /* Store the updated position in the fd. */
> > + if (i == OFF_MAX - 2 || i == OFF_MAX - 1)
> > + {
> > + i = lseek( fd, i, SEEK_SET );
> > + }
> > + else
> > + {
> > + lseek( fd, restart_pos, SEEK_SET );
> > + if (bytes_left != bytes_read)
> > + wine_getdirentries( fd, data, bytes_read - bytes_left, &restart_pos \
> > ); }
>
> Hmm. This raises another problem. I knew about it, but had forgotten. You can't \
> rely on getdirentries() reading a specified number of entries (or bytes) and \
> leaving the file position such that the next read will resume with the next entry.
> On some file systems, getdirentries() reads entries from the directory in whole \
> blocks. It may read fewer entries than the supplied buffer could hold if it \
> couldn't fit all of the next block's worth of entries into the buffer. On the \
> affected file systems, getdirentries() will always leave the file position on a \
> multiple of the block size and there's nothing you can do to change that. (This is \
> CodeWeavers bug 12271, FYI.)
> So, that last call to wine_getdirentries() won't do what you hope. And, in \
> general, there's no good way to make read_directory_getdirentries() leave the file \
> position in a place such that it can resume at the next entry it would have \
> enumerated.
> This is a nasty problem. Sorry to have wasted your time working on this before \
> remembering this fundamental flaw.
Eh, right, that's real nasty. No problem, I should have realized that too.
> It may be that the only reliable fix that can be implemented in ntdll is to use a \
> directory index as the file position, after all. Except that we'd never use that \
> as the place to read from. Instead, we'd always seek to the beginning and read \
> entries, throwing away any that were before the index stored in the file position. \
> Of course, this causes tons of redundant reading of directory entries.
I think I'll try this just in case, as a sort of "experiment", even
though it doesn't seem to be the correct way forward overall.
> Alexandre had a vague suggestion for a different approach in a previous thread \
> <https://www.winehq.org/pipermail/wine-devel/2014-February/102688.html> that I \
> didn't entirely follow. Part of it seems to have been to read the whole directory \
> listing into memory when it is first requested (or a restart is requested) and then \
> return entries from this cache on subsequent calls. His scheme may have required \
> additional support from the server to track metadata for handles. I don't know how \
> reads of the same handle in multiple processes would be coordinated.
> Perhaps he can be persuaded to describe the solution he has in mind more fully. \
> Or, if you can understand what he wrote in that previous thread better than I, you \
> can try your hand at it.
Uh, I didn't recall this wine-devel thread at all but I'm sure I
followed it back then. FWIW my understanding pretty much matches yours
and I see why that would be the "right" fix. I guess I'll just try to
implement Alexandre's suggestion and see what happens. Expect either a
new set of patches or some kind of request for help from me in the
somewhat near future :P
> -Ken
Thanks again for the feedback!
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic