* fhandler_disk_file.cc (get_ino_by_handle): Rename pfai to fai.

(fhandler_base::fstat_by_handle): Drop fai_size and pfai in favor of
	static struct fai_buf.  Restructure.
	(fhandler_base::fstat_by_name): Drop fvi_size and pfvi.  Drop fdi_size
	and pfdi in favor of static struct fdi_buf.  Drop redundant test for
	existance.  Use FileDirectoryInformation class instead of
	FileBothDirectoryInformation.  Drop call to NtQueryVolumeInformationFile
	in favor of using pc.fs_serial_number ().  Fix FileId information given
	to fstat_helper.
	(fhandler_disk_file::fstatvfs): Drop fvi_size, pfvi, fai_size and pfai.
	Drop getting FileFsVolumeInformation and FileFsAttributeInformation in
	favor of using the related path_conv info.
	(fhandler_disk_file::opendir): Fix comment.
	(fhandler_disk_file::readdir): Ditto.  Use FileDirectoryInformation
	class instead of FileBothDirectoryInformation.
	* path.cc (fs_info::update): Store MaximumComponentNameLength in new
	member name_len.
	* path.h (struct fs_info): Use ULONG rather than DWORD.  Add member
	name_len to store MaximumComponentNameLength.  Add accessor methods.
	(path_conv::fs_name_len): New method.
This commit is contained in:
Corinna Vinschen 2008-05-21 10:23:19 +00:00
parent 0d3f365881
commit 380b8bac12
4 changed files with 102 additions and 116 deletions

View File

@ -1,3 +1,26 @@
2008-05-21 Corinna Vinschen <corinna@vinschen.de>
* fhandler_disk_file.cc (get_ino_by_handle): Rename pfai to fai.
(fhandler_base::fstat_by_handle): Drop fai_size and pfai in favor of
static struct fai_buf. Restructure.
(fhandler_base::fstat_by_name): Drop fvi_size and pfvi. Drop fdi_size
and pfdi in favor of static struct fdi_buf. Drop redundant test for
existance. Use FileDirectoryInformation class instead of
FileBothDirectoryInformation. Drop call to NtQueryVolumeInformationFile
in favor of using pc.fs_serial_number (). Fix FileId information given
to fstat_helper.
(fhandler_disk_file::fstatvfs): Drop fvi_size, pfvi, fai_size and pfai.
Drop getting FileFsVolumeInformation and FileFsAttributeInformation in
favor of using the related path_conv info.
(fhandler_disk_file::opendir): Fix comment.
(fhandler_disk_file::readdir): Ditto. Use FileDirectoryInformation
class instead of FileBothDirectoryInformation.
* path.cc (fs_info::update): Store MaximumComponentNameLength in new
member name_len.
* path.h (struct fs_info): Use ULONG rather than DWORD. Add member
name_len to store MaximumComponentNameLength. Add accessor methods.
(path_conv::fs_name_len): New method.
2008-05-21 Corinna Vinschen <corinna@vinschen.de>
* fhandler.h (dirent_states): Add dirent_nfs_d_ino state and add it to

View File

@ -168,11 +168,11 @@ static inline __ino64_t
get_ino_by_handle (HANDLE hdl)
{
IO_STATUS_BLOCK io;
FILE_INTERNAL_INFORMATION pfai;
FILE_INTERNAL_INFORMATION fai;
if (NT_SUCCESS (NtQueryInformationFile (hdl, &io, &pfai, sizeof pfai,
if (NT_SUCCESS (NtQueryInformationFile (hdl, &io, &fai, sizeof fai,
FileInternalInformation)))
return pfai.FileId.QuadPart;
return fai.FileId.QuadPart;
return 0;
}
@ -329,38 +329,38 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf)
if (pc.fs_is_nfs ())
return fstat_by_nfs_ea (buf);
/* The entries potentially contain a name of MAX_PATH wide characters. */
const DWORD fai_size = (NAME_MAX + 1) * sizeof (WCHAR)
+ sizeof (FILE_ALL_INFORMATION);
PFILE_ALL_INFORMATION pfai = (PFILE_ALL_INFORMATION) alloca (fai_size);
struct {
FILE_ALL_INFORMATION fai;
WCHAR buf[NAME_MAX + 1];
} fai_buf;
status = NtQueryInformationFile (get_handle (), &io, pfai, fai_size,
FileAllInformation);
if (NT_SUCCESS (status))
status = NtQueryInformationFile (get_handle (), &io, &fai_buf.fai,
sizeof fai_buf, FileAllInformation);
if (!NT_SUCCESS (status))
{
/* If the change time is 0, it's a file system which doesn't
support a change timestamp. In that case use the LastWriteTime
entry, as in other calls to fstat_helper. */
if (pc.is_rep_symlink ())
pfai->BasicInformation.FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
pc.file_attributes (pfai->BasicInformation.FileAttributes);
return fstat_helper (buf,
pfai->BasicInformation.ChangeTime.QuadPart
? *(FILETIME *) &pfai->BasicInformation.ChangeTime
: *(FILETIME *) &pfai->BasicInformation.LastWriteTime,
*(FILETIME *) &pfai->BasicInformation.LastAccessTime,
*(FILETIME *) &pfai->BasicInformation.LastWriteTime,
*(FILETIME *) &pfai->BasicInformation.CreationTime,
get_dev (),
pfai->StandardInformation.EndOfFile.QuadPart,
pfai->StandardInformation.AllocationSize.QuadPart,
pfai->InternalInformation.FileId.QuadPart,
pfai->StandardInformation.NumberOfLinks,
pfai->BasicInformation.FileAttributes);
debug_printf ("%p = NtQueryInformationFile(%S)",
status, pc.get_nt_native_path ());
return -1;
}
debug_printf ("%p = NtQueryInformationFile(%S)",
status, pc.get_nt_native_path ());
return -1;
/* If the change time is 0, it's a file system which doesn't
support a change timestamp. In that case use the LastWriteTime
entry, as in other calls to fstat_helper. */
if (pc.is_rep_symlink ())
fai_buf.fai.BasicInformation.FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
pc.file_attributes (fai_buf.fai.BasicInformation.FileAttributes);
return fstat_helper (buf,
fai_buf.fai.BasicInformation.ChangeTime.QuadPart
? *(FILETIME *) &fai_buf.fai.BasicInformation.ChangeTime
: *(FILETIME *) &fai_buf.fai.BasicInformation.LastWriteTime,
*(FILETIME *) &fai_buf.fai.BasicInformation.LastAccessTime,
*(FILETIME *) &fai_buf.fai.BasicInformation.LastWriteTime,
*(FILETIME *) &fai_buf.fai.BasicInformation.CreationTime,
get_dev (),
fai_buf.fai.StandardInformation.EndOfFile.QuadPart,
fai_buf.fai.StandardInformation.AllocationSize.QuadPart,
fai_buf.fai.InternalInformation.FileId.QuadPart,
fai_buf.fai.StandardInformation.NumberOfLinks,
fai_buf.fai.BasicInformation.FileAttributes);
}
int __stdcall
@ -372,22 +372,12 @@ fhandler_base::fstat_by_name (struct __stat64 *buf)
UNICODE_STRING dirname;
UNICODE_STRING basename;
HANDLE dir;
const DWORD fdi_size = (NAME_MAX + 1) * sizeof (WCHAR)
+ sizeof (FILE_ID_BOTH_DIR_INFORMATION);
const DWORD fvi_size = (NAME_MAX + 1) * sizeof (WCHAR)
+ sizeof (FILE_FS_VOLUME_INFORMATION);
PFILE_ID_BOTH_DIR_INFORMATION pfdi = (PFILE_ID_BOTH_DIR_INFORMATION)
alloca (fdi_size);
PFILE_FS_VOLUME_INFORMATION pfvi = (PFILE_FS_VOLUME_INFORMATION)
alloca (fvi_size);
struct {
FILE_ID_BOTH_DIR_INFORMATION fdi;
WCHAR buf[NAME_MAX + 1];
} fdi_buf;
LARGE_INTEGER FileId;
if (!pc.exists ())
{
debug_printf ("already determined that pc does not exist");
set_errno (ENOENT);
return -1;
}
RtlSplitUnicodePath (pc.get_nt_native_path (), &dirname, &basename);
InitializeObjectAttributes (&attr, &dirname, OBJ_CASE_INSENSITIVE,
NULL, NULL);
@ -402,13 +392,13 @@ fhandler_base::fstat_by_name (struct __stat64 *buf)
}
if (wincap.has_fileid_dirinfo ()
&& NT_SUCCESS (status = NtQueryDirectoryFile (dir, NULL, NULL, 0, &io,
pfdi, fdi_size,
&fdi_buf.fdi, sizeof fdi_buf,
FileIdBothDirectoryInformation,
TRUE, &basename, TRUE)))
FileId = pfdi->FileId;
FileId = fdi_buf.fdi.FileId;
else if (NT_SUCCESS (status = NtQueryDirectoryFile (dir, NULL, NULL, 0, &io,
pfdi, fdi_size,
FileBothDirectoryInformation,
&fdi_buf.fdi, sizeof fdi_buf,
FileDirectoryInformation,
TRUE, &basename, TRUE)))
FileId.QuadPart = 0; /* get_ino is called in fstat_helper. */
if (!NT_SUCCESS (status))
@ -418,34 +408,26 @@ fhandler_base::fstat_by_name (struct __stat64 *buf)
NtClose (dir);
goto too_bad;
}
status = NtQueryVolumeInformationFile (dir, &io, pfvi, fvi_size,
FileFsVolumeInformation);
if (!NT_SUCCESS (status))
{
debug_printf ("%p = NtQueryVolumeInformationFile(%S)",
status, pc.get_nt_native_path ());
pfvi->VolumeSerialNumber = 0;
}
NtClose (dir);
/* If the change time is 0, it's a file system which doesn't
support a change timestamp. In that case use the LastWriteTime
entry, as in other calls to fstat_helper. */
if (pc.is_rep_symlink ())
pfdi->FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
pc.file_attributes (pfdi->FileAttributes);
fdi_buf.fdi.FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
pc.file_attributes (fdi_buf.fdi.FileAttributes);
return fstat_helper (buf,
pfdi->ChangeTime.QuadPart ?
*(FILETIME *) &pfdi->ChangeTime :
*(FILETIME *) &pfdi->LastWriteTime,
*(FILETIME *) &pfdi->LastAccessTime,
*(FILETIME *) &pfdi->LastWriteTime,
*(FILETIME *) &pfdi->CreationTime,
pfvi->VolumeSerialNumber,
pfdi->EndOfFile.QuadPart,
pfdi->AllocationSize.QuadPart,
pfdi->FileId.QuadPart,
fdi_buf.fdi.ChangeTime.QuadPart ?
*(FILETIME *) &fdi_buf.fdi.ChangeTime :
*(FILETIME *) &fdi_buf.fdi.LastWriteTime,
*(FILETIME *) &fdi_buf.fdi.LastAccessTime,
*(FILETIME *) &fdi_buf.fdi.LastWriteTime,
*(FILETIME *) &fdi_buf.fdi.CreationTime,
pc.fs_serial_number (),
fdi_buf.fdi.EndOfFile.QuadPart,
fdi_buf.fdi.AllocationSize.QuadPart,
FileId.QuadPart,
1,
pfdi->FileAttributes);
fdi_buf.fdi.FileAttributes);
too_bad:
LARGE_INTEGER ft;
@ -679,14 +661,6 @@ fhandler_disk_file::fstatvfs (struct statvfs *sfs)
int ret = -1, opened = 0;
NTSTATUS status;
IO_STATUS_BLOCK io;
const size_t fvi_size = sizeof (FILE_FS_VOLUME_INFORMATION)
+ (NAME_MAX + 1) * sizeof (WCHAR);
PFILE_FS_VOLUME_INFORMATION pfvi = (PFILE_FS_VOLUME_INFORMATION)
alloca (fvi_size);
const size_t fai_size = sizeof (FILE_FS_ATTRIBUTE_INFORMATION)
+ (NAME_MAX + 1) * sizeof (WCHAR);
PFILE_FS_ATTRIBUTE_INFORMATION pfai = (PFILE_FS_ATTRIBUTE_INFORMATION)
alloca (fai_size);
FILE_FS_FULL_SIZE_INFORMATION full_fsi;
FILE_FS_SIZE_INFORMATION fsi;
HANDLE fh = get_handle ();
@ -712,27 +686,12 @@ fhandler_disk_file::fstatvfs (struct statvfs *sfs)
}
}
/* Get basic volume information. */
status = NtQueryVolumeInformationFile (fh, &io, pfvi, fvi_size,
FileFsVolumeInformation);
if (!NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
goto out;
}
status = NtQueryVolumeInformationFile (fh, &io, pfai, fai_size,
FileFsAttributeInformation);
if (!NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
goto out;
}
sfs->f_files = ULONG_MAX;
sfs->f_ffree = ULONG_MAX;
sfs->f_favail = ULONG_MAX;
sfs->f_fsid = pfvi->VolumeSerialNumber;
sfs->f_flag = pfai->FileSystemAttributes;
sfs->f_namemax = pfai->MaximumComponentNameLength;
sfs->f_fsid = pc.fs_serial_number ();
sfs->f_flag = pc.fs_flags ();
sfs->f_namemax = pc.fs_name_len ();
/* Get allocation related information. Try to get "full" information
first, which is only available since W2K. If that fails, try to
retrieve normal allocation information. */
@ -1608,7 +1567,7 @@ fhandler_disk_file::opendir (int fd)
OS/FS combinations (say, Win2K/CDFS or so). Instead of
testing in readdir for yet another error code, let's use
FileIdBothDirectoryInformation only on filesystems supporting
persistent ACLs, FileBothDirectoryInformation otherwise.
persistent ACLs, FileDirectoryInformation otherwise.
On older NFS clients (up to SFU 3.5), dangling symlinks
are hidden from directory queries, unless you use the
@ -1825,20 +1784,20 @@ fhandler_disk_file::readdir (DIR *dir, dirent *de)
nicely, but only up to the 128th entry in the directory. After
reaching this entry, the next call to NtQueryDirectoryFile
(FileIdBothDirectoryInformation) returns STATUS_INVALID_LEVEL.
Why should we care, we can just switch to
FileBothDirectoryInformation, isn't it? Nope! The next call to
NtQueryDirectoryFile(FileBothDirectoryInformation) actually
returns STATUS_NO_MORE_FILES, regardless how many files are left
unread in the directory. This does not happen when using
FileBothDirectoryInformation right from the start, but since
Why should we care, we can just switch to FileDirectoryInformation,
isn't it? Nope! The next call to
NtQueryDirectoryFile(FileDirectoryInformation)
actually returns STATUS_NO_MORE_FILES, regardless how many files
are left unread in the directory. This does not happen when using
FileDirectoryInformation right from the start, but since
we can't decide whether the server we're talking with has this
bug or not, we end up serving Samba shares always in the slow
mode using FileBothDirectoryInformation. So, what we do here is
mode using FileDirectoryInformation. So, what we do here is
to implement the solution suggested by Andrew Tridgell, we just
reread all entries up to dir->d_position using
FileBothDirectoryInformation.
FileDirectoryInformation.
However, We do *not* mark this server as broken and fall back to
using FileBothDirectoryInformation further on. This would slow
using FileDirectoryInformation further on. This would slow
down every access to such a server, even for directories under
128 entries. Also, bigger dirs only suffer from one additional
call per full directory scan, which shouldn't be too big a hit.
@ -1852,7 +1811,7 @@ fhandler_disk_file::readdir (DIR *dir, dirent *de)
{
status = NtQueryDirectoryFile (get_handle (), NULL, NULL,
0, &io, d_cache (dir), DIR_BUF_SIZE,
FileBothDirectoryInformation,
FileDirectoryInformation,
FALSE, NULL, cnt == 0);
if (!NT_SUCCESS (status))
goto go_ahead;
@ -1872,7 +1831,7 @@ fhandler_disk_file::readdir (DIR *dir, dirent *de)
d_cache (dir), DIR_BUF_SIZE,
(dir->__flags & dirent_nfs_d_ino)
? FileNamesInformation
: FileBothDirectoryInformation,
: FileDirectoryInformation,
FALSE, NULL, dir->__d_position == 0);
}
@ -1904,9 +1863,9 @@ go_ahead:
}
else
{
FileName = ((PFILE_BOTH_DIR_INFORMATION) buf)->FileName;
FileNameLength = ((PFILE_BOTH_DIR_INFORMATION) buf)->FileNameLength;
FileAttributes = ((PFILE_BOTH_DIR_INFORMATION) buf)->FileAttributes;
FileName = ((PFILE_DIRECTORY_INFORMATION) buf)->FileName;
FileNameLength = ((PFILE_DIRECTORY_INFORMATION) buf)->FileNameLength;
FileAttributes = ((PFILE_DIRECTORY_INFORMATION) buf)->FileAttributes;
}
RtlInitCountedUnicodeString (&fname, FileName, FileNameLength);
de->d_ino = d_mounts (dir)->check_mount (&fname, de->d_ino);

View File

@ -457,6 +457,7 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol)
return false;
}
flags (ffai_buf.ffai.FileSystemAttributes);
name_len (ffai_buf.ffai.MaximumComponentNameLength);
/* Should be reevaluated for each new OS. Right now this mask is valid up
to Vista. The important point here is to test only flags indicating
capabilities and to ignore flags indicating a specific state of this

View File

@ -95,8 +95,9 @@ struct fs_info
private:
struct status_flags
{
DWORD flags; /* Volume flags */
DWORD samba_version; /* Samba version if available */
ULONG flags; /* Volume flags */
ULONG samba_version; /* Samba version if available */
ULONG name_len; /* MaximumComponentNameLength */
unsigned is_remote_drive : 1;
unsigned has_buggy_open : 1;
unsigned has_acls : 1;
@ -113,8 +114,9 @@ struct fs_info
void clear () { memset (&status, 0 , sizeof status); sernum = 0UL; }
fs_info () { clear (); }
IMPLEMENT_STATUS_FLAG (DWORD, flags)
IMPLEMENT_STATUS_FLAG (DWORD, samba_version)
IMPLEMENT_STATUS_FLAG (ULONG, flags)
IMPLEMENT_STATUS_FLAG (ULONG, samba_version)
IMPLEMENT_STATUS_FLAG (ULONG, name_len)
IMPLEMENT_STATUS_FLAG (bool, is_remote_drive)
IMPLEMENT_STATUS_FLAG (bool, has_buggy_open)
IMPLEMENT_STATUS_FLAG (bool, has_acls)
@ -269,6 +271,7 @@ class path_conv
DWORD file_attributes () const {return fileattr;}
void file_attributes (DWORD new_attr) {fileattr = new_attr;}
DWORD fs_flags () {return fs.flags ();}
DWORD fs_name_len () {return fs.name_len ();}
bool fs_is_fat () const {return fs.is_fat ();}
bool fs_is_ntfs () const {return fs.is_ntfs ();}
bool fs_is_samba () const {return fs.is_samba ();}