Why does (stat() ?) open files ?

Ben RUBSON ben.rubson@gmail.com
Tue Apr 10 14:29:00 GMT 2018


On 09 Apr 2018 15:07, Corinna Vinschen wrote:

> On Apr  9 14:12, Ben RUBSON wrote:
>> On 09 Apr 2018 12:52, Corinna Vinschen wrote:
>>
>>> On Apr  9 12:28, Ben RUBSON wrote:
>>>> Hi,
>>>>
>>>> This follows the "Why does readdir() open files ?" discussion we had a  
>>>> few
>>>> days ago.
>>>> Thank you Corinna for your answers and suport there !
>>>>
>>>> So, context is Cygwin, especially rsync, working over a Fuse FS.
>>>> This Fuse FS is assumed to be mounted on `/cygdrive/x` below.
>>>>
>>>> I finally found that readdir() does not open every file.
>>>> `ls /cygdrive/x` does not fire any open() call. Perfect.
>>>>
>>>> However, `ls -l /cygdrive/x` does, every file is opened, with read  
>>>> access.
>>>> As `rsync -an /cygdrive/x /tmp/`, which is a dry-run just grabbing  
>>>> files'
>>>> attributes.
>>>>
>>>> I then went through Cygwin code and found that
>>>> NtCreateFile/NtOpenFile calls
>>>> from symlink_info::check() in path.cc may be the culprits.
>>>> To demonstrate this I added write access to these calls, and found that
>>>> every file was then opened with write access.
>>>>
>>>> Later in this function we have a failback to NtQueryDirectoryFile call.
>>>> I assume (assume only, I may be wrong) this one does not open the
>>>> requested
>>>> file.
>>>
>>> It's nice that you're testing all this, but you should ask *why* Cygwin
>>> does it in the first place.  The reason is that the information one can
>>> gather without opening the file on Windows is insufficient to fill in
>>> all of the stat struct.  The directory info returned by
>>> NtQueryDirectoryFile just isn't, thus it's only a fallback.
>>
>> Corinna, thank you very much for your answer.
>> What info would be missing without opening the file ?
>
> uid, gid, number of links.

If we use "noacl" mount option, I think uid and gid do not really make  
sense and could be forced to some default value ?
Number of links should not be critical too.
Thus gathering files' information without opening them could be possible.
However sounds like a more correct way to handle this is in your answer  
below, though I'm not sure it will be possible.

>> Do you know where the open call could come from, when only using
>> NtQueryDirectoryFile in symlink_info::check() ?
>> (certainly related to the previous question)
>
> The answer here is that your FS should handle the open call differently
> depending on the access mask.  The NtCreateFile call in symlink_info::check
> opens the file with READ_CONTROL | FILE_READ_ATTRIBUTES | FILE_READ_EA
> only.  All these access flags only request *meta* info, not actual data
> from the data stream of the file.  In other words, a Windows open call
> without FILE_READ_DATA/FILE_WRITE_DATA and related flags does not
> actually have to open the file at all in the FS driver.   It only has to
> provide metadata subsequently, an operation which you usally can have at
> much lower cost if the remote FS is running on a POSIX OS:
>
> - NtCreateFile called with only metadata access flags does not have to
>   open the file.
>
> - Make sure to ignore the EaBuffer and EaLength parameter, rather than
>   to return a failure (this avoids YA NtOpenFile call).
>
> - Just call stat/statvfs on the remote file as required to fulfill
>   subsequent NtQueryVolumeInformationFile and NtQueryInformationFile
>   calls.
>
> Does that make sense?

Thank you very much for your detailed answer Corinna !

Yes it does make sense, at least I understand how it should work.
The FS is not really running on a POSIX OS, as it stands on the Windows  
machine using WinFsp FUSE API.
I'll see with WinFsp team if something can be done in this way.

Thank you !

Ben



More information about the Cygwin-developers mailing list