Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2010-09-10 14:04:28 +0400
committerCorinna Vinschen <corinna@vinschen.de>2010-09-10 14:04:28 +0400
commitf65c5a0a2b1728ce2b317b31b601574f1ef7f5b2 (patch)
treedce4aa1ba39f4f07fc4dd1d601708687e57798e0 /winsup/cygwin/mount.cc
parent67a9307898f94346cbd4c83b6bae4f9611607818 (diff)
* 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.
Diffstat (limited to 'winsup/cygwin/mount.cc')
-rw-r--r--winsup/cygwin/mount.cc82
1 files changed, 77 insertions, 5 deletions
diff --git a/winsup/cygwin/mount.cc b/winsup/cygwin/mount.cc
index 0117b43b1..8ea1b6295 100644
--- a/winsup/cygwin/mount.cc
+++ b/winsup/cygwin/mount.cc
@@ -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;
}