* mount.cc (class fs_info_cache): New class to cache filesystem

information.
	(fs_info::update): Check FileFsVolumeInformation against filesystem
	cache and use it, if filesystem is already available.  Add filesystem
	to cache, if not.  Only request FileFsObjectIdInformation if
	FILE_SUPPORTS_OBJECT_IDS is set in filesystem flags.
	* ntdll.h (struct _FILE_FS_VOLUME_INFORMATION): Add pragma pack so the
	structure size is matching the OS expectations.  Add __dummy member
	used in filesystem cache.
This commit is contained in:
Corinna Vinschen 2010-09-10 10:04:28 +00:00
parent 67a9307898
commit f65c5a0a2b
3 changed files with 92 additions and 5 deletions

View File

@ -1,3 +1,15 @@
2010-09-10 Corinna Vinschen <corinna@vinschen.de>
* mount.cc (class fs_info_cache): New class to cache filesystem
information.
(fs_info::update): Check FileFsVolumeInformation against filesystem
cache and use it, if filesystem is already available. Add filesystem
to cache, if not. Only request FileFsObjectIdInformation if
FILE_SUPPORTS_OBJECT_IDS is set in filesystem flags.
* ntdll.h (struct _FILE_FS_VOLUME_INFORMATION): Add pragma pack so the
structure size is matching the OS expectations. Add __dummy member
used in filesystem cache.
2010-09-10 Corinna Vinschen <corinna@vinschen.de>
* security.cc (get_file_sd): Add bool parameter justcreated. Use

View File

@ -105,6 +105,64 @@ struct smb_extended_info {
};
#pragma pack(pop)
#define MAX_FS_INFO_CNT 32
class fs_info_cache
{
static muto fsi_lock;
uint32_t count;
struct {
fs_info fsi;
uint32_t hash;
} entry[MAX_FS_INFO_CNT];
uint32_t genhash (PFILE_FS_VOLUME_INFORMATION);
public:
fs_info_cache () : count (0) { fsi_lock.init ("fsi_lock"); }
fs_info *search (PFILE_FS_VOLUME_INFORMATION, uint32_t &);
void add (uint32_t, fs_info *);
};
static fs_info_cache fsi_cache;
muto NO_COPY fs_info_cache::fsi_lock;
uint32_t
fs_info_cache::genhash (PFILE_FS_VOLUME_INFORMATION pffvi)
{
uint32_t hash = 0;
const uint16_t *p = (const uint16_t *) pffvi;
const uint16_t *end = (const uint16_t *)
((const uint8_t *) p + sizeof *pffvi
+ pffvi->VolumeLabelLength - sizeof (WCHAR));
pffvi->__dummy = 0; /* This member can have random values! */
while (p < end)
hash = *p++ + (hash << 6) + (hash << 16) - hash;
return hash;
}
fs_info *
fs_info_cache::search (PFILE_FS_VOLUME_INFORMATION pffvi, uint32_t &hash)
{
hash = genhash (pffvi);
for (uint32_t i = 0; i < count; ++i)
if (entry[i].hash == hash)
return &entry[i].fsi;
return NULL;
}
void
fs_info_cache::add (uint32_t hashval, fs_info *new_fsi)
{
fsi_lock.acquire ();
if (count < MAX_FS_INFO_CNT)
{
entry[count].fsi = *new_fsi;
entry[count].hash = hashval;
++count;
}
fsi_lock.release ();
}
bool
fs_info::update (PUNICODE_STRING upath, HANDLE in_vol)
{
@ -172,11 +230,23 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol)
return false;
}
}
sernum = 0;
status = NtQueryVolumeInformationFile (vol, &io, &ffvi_buf.ffvi,
sizeof ffvi_buf,
FileFsVolumeInformation);
sernum = NT_SUCCESS (status) ? ffvi_buf.ffvi.VolumeSerialNumber : 0;
uint32_t hash = 0;
if (NT_SUCCESS (status))
{
fs_info *fsi = fsi_cache.search (&ffvi_buf.ffvi, hash);
if (fsi)
{
*this = *fsi;
if (!in_vol)
NtClose (vol);
return true;
}
sernum = ffvi_buf.ffvi.VolumeSerialNumber;
}
status = NtQueryVolumeInformationFile (vol, &io, &ffdi, sizeof ffdi,
FileFsDeviceInformation);
if (!NT_SUCCESS (status))
@ -253,9 +323,10 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol)
#define FS_IS_WINDOWS_FAT TEST_GVI(flags (), WIN_FAT_FLAGS)
/* This always fails on NT4. */
status = NtQueryVolumeInformationFile (vol, &io, &ffoi, sizeof ffoi,
FileFsObjectIdInformation);
if (NT_SUCCESS (status))
if ((flags () & FILE_SUPPORTS_OBJECT_IDS)
&& NT_SUCCESS (NtQueryVolumeInformationFile (vol, &io, &ffoi,
sizeof ffoi,
FileFsObjectIdInformation)))
{
smb_extended_info *extended_info = (smb_extended_info *)
&ffoi.ExtendedInfo;
@ -355,6 +426,7 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol)
if (!in_vol)
NtClose (vol);
fsi_cache.add (hash, this);
return true;
}

View File

@ -751,14 +751,17 @@ typedef struct _FILE_FS_ATTRIBUTE_INFORMATION
WCHAR FileSystemName[1];
} FILE_FS_ATTRIBUTE_INFORMATION, *PFILE_FS_ATTRIBUTE_INFORMATION;
#pragma pack(push,4)
typedef struct _FILE_FS_VOLUME_INFORMATION
{
LARGE_INTEGER VolumeCreationTime;
ULONG VolumeSerialNumber;
ULONG VolumeLabelLength;
BOOLEAN SupportsObjects;
BOOLEAN __dummy;
WCHAR VolumeLabel[1];
} FILE_FS_VOLUME_INFORMATION, *PFILE_FS_VOLUME_INFORMATION;
#pragma pack(pop)
typedef struct _FILE_FS_SIZE_INFORMATION
{