* 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:
		| @@ -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 | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
| { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user