* fhandler_disk_file.cc (fhandler_disk_file::readdir_helper): Remove

ill-advised attempt to optimize "." and ".." handling by checking for
	specific position in directory listing.  Explain why.
	(fhandler_disk_file.cc (fhandler_disk_file::readdir): Ditto.
	Special-case opening file on NFS to fetch inode number and add longish
	comment to explain why.
This commit is contained in:
Corinna Vinschen 2009-08-14 13:39:07 +00:00
parent c1999c4b0c
commit e575678945
2 changed files with 55 additions and 17 deletions

View File

@ -1,3 +1,12 @@
2009-08-14 Corinna Vinschen <corinna@vinschen.de>
* fhandler_disk_file.cc (fhandler_disk_file::readdir_helper): Remove
ill-advised attempt to optimize "." and ".." handling by checking for
specific position in directory listing. Explain why.
(fhandler_disk_file.cc (fhandler_disk_file::readdir): Ditto.
Special-case opening file on NFS to fetch inode number and add longish
comment to explain why.
2009-08-14 Corinna Vinschen <corinna@vinschen.de> 2009-08-14 Corinna Vinschen <corinna@vinschen.de>
* (fhandler_socket::getsockname): Fix length returned for unbound * (fhandler_socket::getsockname): Fix length returned for unbound

View File

@ -1828,10 +1828,16 @@ fhandler_disk_file::readdir_helper (DIR *dir, dirent *de, DWORD w32_err,
sys_wcstombs (de->d_name, NAME_MAX + 1, fname->Buffer, sys_wcstombs (de->d_name, NAME_MAX + 1, fname->Buffer,
fname->Length / sizeof (WCHAR)); fname->Length / sizeof (WCHAR));
if (dir->__d_position == 0 && !strcmp (de->d_name, ".")) /* Don't try to optimize relative to dir->__d_position. On several
dir->__flags |= dirent_saw_dot; filesystems it's no safe bet that "." and ".." entries always
else if (dir->__d_position == 1 && !strcmp (de->d_name, "..")) come first. */
dir->__flags |= dirent_saw_dot_dot; if (de->d_name[0] == '.')
{
if (de->d_name[1] == '\0')
dir->__flags |= dirent_saw_dot;
else if (de->d_name[1] == '.' && de->d_name[2] == '\0')
dir->__flags |= dirent_saw_dot_dot;
}
return 0; return 0;
} }
@ -1960,28 +1966,51 @@ go_ahead:
de->d_ino = d_mounts (dir)->check_mount (&fname, de->d_ino); de->d_ino = d_mounts (dir)->check_mount (&fname, de->d_ino);
if (de->d_ino == 0 && (dir->__flags & dirent_set_d_ino)) if (de->d_ino == 0 && (dir->__flags & dirent_set_d_ino))
{ {
OBJECT_ATTRIBUTES attr; /* Don't try to optimize relative to dir->__d_position. On several
filesystems it's no safe bet that "." and ".." entries always
if (dir->__d_position == 0 && FileNameLength == 2 come first. */
&& FileName[0] == '.') if (FileNameLength == sizeof (WCHAR) && FileName[0] == '.')
de->d_ino = get_ino_by_handle (pc, get_handle ()); de->d_ino = get_ino_by_handle (pc, get_handle ());
else if (dir->__d_position == 1 && FileNameLength == 4 else if (FileNameLength == sizeof (WCHAR)
&& FileName[0] == L'.' && FileName[1] == L'.') && FileName[0] == L'.' && FileName[1] == L'.')
if (!(dir->__flags & dirent_isroot)) {
de->d_ino = readdir_get_ino (get_name (), true); if (!(dir->__flags & dirent_isroot))
else de->d_ino = readdir_get_ino (get_name (), true);
de->d_ino = get_ino_by_handle (pc, get_handle ()); else
de->d_ino = get_ino_by_handle (pc, get_handle ());
}
else else
{ {
OBJECT_ATTRIBUTES attr;
HANDLE hdl; HANDLE hdl;
NTSTATUS f_status;
InitializeObjectAttributes (&attr, &fname, InitializeObjectAttributes (&attr, &fname,
pc.objcaseinsensitive (), pc.objcaseinsensitive (),
get_handle (), NULL); get_handle (), NULL);
if (NT_SUCCESS (NtOpenFile (&hdl, READ_CONTROL, &attr, &io, /* FILE_OPEN_REPARSE_POINT on NFS is a no-op, so the normal
FILE_SHARE_VALID_FLAGS, NtOpenFile here returns the inode number of the symlink target,
FILE_OPEN_FOR_BACKUP_INTENT rather than the inode number of the symlink itself.
| FILE_OPEN_REPARSE_POINT)))
Worse, trying to open a symlink without setting the special
"ActOnSymlink" EA triggers a bug in Windows 7 which results
in a timeout of about 20 seconds, followed by two exceptions
in the NT kernel.
Since both results are far from desirable, we open symlinks
on NFS so that we get the right inode and a happy W7.
And, since some filesystems choke on the EAs, we don't
use them unconditionally. */
f_status = (dir->__flags & dirent_nfs_d_ino)
? NtCreateFile (&hdl, READ_CONTROL, &attr, &io,
NULL, 0, FILE_SHARE_VALID_FLAGS,
FILE_OPEN, FILE_OPEN_FOR_BACKUP_INTENT,
&nfs_aol_ffei, sizeof nfs_aol_ffei)
: NtOpenFile (&hdl, READ_CONTROL, &attr, &io,
FILE_SHARE_VALID_FLAGS,
FILE_OPEN_FOR_BACKUP_INTENT
| FILE_OPEN_REPARSE_POINT);
if (NT_SUCCESS (f_status))
{ {
de->d_ino = get_ino_by_handle (pc, hdl); de->d_ino = get_ino_by_handle (pc, hdl);
NtClose (hdl); NtClose (hdl);