Re: [PATCH 09/11] mount.cc: Implement poor-man's cache

2021-02-04 Thread Corinna Vinschen via Cygwin-patches
On Feb  3 12:38, Ben wrote:
> 
> 
> On 18-01-2021 12:51, Corinna Vinschen via Cygwin-patches wrote:
> > Ok, so hash_prefix reduces the path to a drive letter or the UNC path
> > prefix and hashes it.  However, what about partitions mounted to a
> > subdir of, say, drive C?  In that case the hashing goes awry, because
> > you're comparing with the hash of drive C while the path is actually
> > pointing to another partition.
> > 
> How can I mount a partition as a subdir of drive C?
> For some reason I can't:
> $ mount /cygdrive/e/Temp/dummy /cygdrive/c/Temp/dummy/dummyone
> mount: /cygdrive/c/Temp/dummy/dummyone: Invalid argument

I wasn't talking about Cygwin mount points, but rather about Windows
mount points.  Since Windows 2000 a partition can be mounted into a
directory of another partition.  Only drive C: (ignoring non-harddisks)
has to be mounted with a drive letter, all others can be mounted just as
on Unix.

But, yeah, Cygwin also supports bind mounts.  Here's an example
from my /etc/fstab.d user mount file:

  //remote/cygwin-src /cygwin nfs binary 0 0
  /cygwin/pub /home/pub nfs bind 0 0


Corinna


Re: [PATCH 09/11] mount.cc: Implement poor-man's cache

2021-02-03 Thread Ben



On 18-01-2021 12:51, Corinna Vinschen via Cygwin-patches wrote:
> Ok, so hash_prefix reduces the path to a drive letter or the UNC path
> prefix and hashes it.  However, what about partitions mounted to a
> subdir of, say, drive C?  In that case the hashing goes awry, because
> you're comparing with the hash of drive C while the path is actually
> pointing to another partition.
> 
How can I mount a partition as a subdir of drive C?
For some reason I can't:
$ mount /cygdrive/e/Temp/dummy /cygdrive/c/Temp/dummy/dummyone
mount: /cygdrive/c/Temp/dummy/dummyone: Invalid argument


Re: [PATCH 09/11] mount.cc: Implement poor-man's cache

2021-01-18 Thread Corinna Vinschen via Cygwin-patches
On Jan 15 14:45, Ben Wijen wrote:
> Try to avoid NtQueryVolumeInformationFile.
> ---
>  winsup/cygwin/mount.cc | 78 --
>  winsup/cygwin/mount.h  |  2 +-
>  winsup/cygwin/path.cc  |  2 +-
>  winsup/cygwin/path.h   |  1 +
>  4 files changed, 56 insertions(+), 27 deletions(-)
> 
> diff --git a/winsup/cygwin/mount.cc b/winsup/cygwin/mount.cc
> index e0349815d..1d2b3a61a 100644
> --- a/winsup/cygwin/mount.cc
> +++ b/winsup/cygwin/mount.cc
> @@ -82,6 +82,32 @@ win32_device_name (const char *src_path, char *win32_path, 
> device& dev)
>return true;
>  }
>  
> +static uint32_t
> +hash_prefix (const PUNICODE_STRING upath)
> +{
> +  UNICODE_STRING prefix;
> +  WCHAR *p;
> +
> +  if (upath->Buffer[5] == L':' && upath->Buffer[6] == L'\\')
> +p = upath->Buffer + 6;
> +  else
> +{
> +  /* We're expecting an UNC path.  Move p to the backslash after
> +   "\??\UNC\server\share" or the trailing NUL. */
> +  p = upath->Buffer + 7; /* Skip "\??\UNC" */
> +  int bs_cnt = 0;
> +
> +  while (*++p)
> +if (*p == L'\\')
> +  if (++bs_cnt > 1)
> +break;
> +}
> +  RtlInitCountedUnicodeString (&prefix, upath->Buffer,
> +   (p - upath->Buffer) * sizeof(WCHAR));
> +
> +  return hash_path_name ((ino_t) 0, &prefix);
> +}
> +

Ok, so hash_prefix reduces the path to a drive letter or the UNC path
prefix and hashes it.  However, what about partitions mounted to a
subdir of, say, drive C?  In that case the hashing goes awry, because
you're comparing with the hash of drive C while the path is actually
pointing to another partition.

> @@ -233,27 +281,7 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol)
>a unique per-drive/share hash. */
>if (ffvi_buf.ffvi.VolumeSerialNumber == 0)
>   {
> -   UNICODE_STRING path_prefix;
> -   WCHAR *p;
> -
> -   if (upath->Buffer[5] == L':' && upath->Buffer[6] == L'\\')
> - p = upath->Buffer + 6;
> -   else
> - {
> -   /* We're expecting an UNC path.  Move p to the backslash after
> -  "\??\UNC\server\share" or the trailing NUL. */
> -   p = upath->Buffer + 7;  /* Skip "\??\UNC" */
> -   int bs_cnt = 0;
> -
> -   while (*++p)
> - if (*p == L'\\')
> - if (++bs_cnt > 1)
> -   break;
> - }
> -   RtlInitCountedUnicodeString (&path_prefix, upath->Buffer,
> -(p - upath->Buffer) * sizeof (WCHAR));
> -   ffvi_buf.ffvi.VolumeSerialNumber = hash_path_name ((ino_t) 0,
> -  &path_prefix);
> +   ffvi_buf.ffvi.VolumeSerialNumber = hash_prefix(upath);

Please note that we did this *only* for border case FSes returning a VSN
of 0.  This was sufficient for these cases, but not in a a general sense.


Corinna


[PATCH 09/11] mount.cc: Implement poor-man's cache

2021-01-15 Thread Ben Wijen
Try to avoid NtQueryVolumeInformationFile.
---
 winsup/cygwin/mount.cc | 78 --
 winsup/cygwin/mount.h  |  2 +-
 winsup/cygwin/path.cc  |  2 +-
 winsup/cygwin/path.h   |  1 +
 4 files changed, 56 insertions(+), 27 deletions(-)

diff --git a/winsup/cygwin/mount.cc b/winsup/cygwin/mount.cc
index e0349815d..1d2b3a61a 100644
--- a/winsup/cygwin/mount.cc
+++ b/winsup/cygwin/mount.cc
@@ -82,6 +82,32 @@ win32_device_name (const char *src_path, char *win32_path, 
device& dev)
   return true;
 }
 
+static uint32_t
+hash_prefix (const PUNICODE_STRING upath)
+{
+  UNICODE_STRING prefix;
+  WCHAR *p;
+
+  if (upath->Buffer[5] == L':' && upath->Buffer[6] == L'\\')
+p = upath->Buffer + 6;
+  else
+{
+  /* We're expecting an UNC path.  Move p to the backslash after
+   "\??\UNC\server\share" or the trailing NUL. */
+  p = upath->Buffer + 7; /* Skip "\??\UNC" */
+  int bs_cnt = 0;
+
+  while (*++p)
+if (*p == L'\\')
+  if (++bs_cnt > 1)
+break;
+}
+  RtlInitCountedUnicodeString (&prefix, upath->Buffer,
+   (p - upath->Buffer) * sizeof(WCHAR));
+
+  return hash_path_name ((ino_t) 0, &prefix);
+}
+
 /* Beginning with Samba 3.0.28a, Samba allows to get version information using
the ExtendedInfo member returned by a FileFsObjectIdInformation request.
We just store the samba_version information for now.  Older versions than
@@ -106,14 +132,16 @@ class fs_info_cache
   struct {
 fs_info fsi;
 uint32_t hash;
+uint32_t prefix_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 (uint32_t);
   fs_info *search (PFILE_FS_VOLUME_INFORMATION, uint32_t &);
-  void add (uint32_t, fs_info *);
+  void add (uint32_t, fs_info *, uint32_t);
 };
 
 static fs_info_cache fsi_cache;
@@ -142,22 +170,31 @@ fs_info_cache::search (PFILE_FS_VOLUME_INFORMATION pffvi, 
uint32_t &hash)
   return &entry[i].fsi;
   return NULL;
 }
+fs_info*
+fs_info_cache::search (uint32_t prefix_hash)
+{
+  for (uint32_t i = 0; i < count; ++i)
+if (entry[i].prefix_hash == prefix_hash)
+  return &entry[i].fsi;
+  return NULL;
+}
 
 void
-fs_info_cache::add (uint32_t hashval, fs_info *new_fsi)
+fs_info_cache::add (uint32_t hashval, fs_info *new_fsi, uint32_t prefix_hash)
 {
   fsi_lock.acquire ();
   if (count < MAX_FS_INFO_CNT)
 {
   entry[count].fsi = *new_fsi;
   entry[count].hash = hashval;
+  entry[count].prefix_hash = prefix_hash;
   ++count;
 }
   fsi_lock.release ();
 }
 
 bool
-fs_info::update (PUNICODE_STRING upath, HANDLE in_vol)
+fs_info::update (PUNICODE_STRING upath, HANDLE in_vol, bool use_prefix_hash)
 {
   NTSTATUS status = STATUS_OBJECT_NAME_NOT_FOUND;
   HANDLE vol;
@@ -178,6 +215,17 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol)
   UNICODE_STRING fsname;
 
   clear ();
+
+  if (use_prefix_hash)
+{
+  fs_info *fsi = fsi_cache.search (hash_prefix (upath));
+  if (fsi)
+{
+  *this = *fsi;
+  return true;
+}
+}
+
   /* Always caseinsensitive.  We really just need access to the drive. */
   InitializeObjectAttributes (&attr, upath, OBJ_CASE_INSENSITIVE, NULL, NULL);
   if (in_vol)
@@ -233,27 +281,7 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol)
 a unique per-drive/share hash. */
   if (ffvi_buf.ffvi.VolumeSerialNumber == 0)
{
- UNICODE_STRING path_prefix;
- WCHAR *p;
-
- if (upath->Buffer[5] == L':' && upath->Buffer[6] == L'\\')
-   p = upath->Buffer + 6;
- else
-   {
- /* We're expecting an UNC path.  Move p to the backslash after
-"\??\UNC\server\share" or the trailing NUL. */
- p = upath->Buffer + 7;  /* Skip "\??\UNC" */
- int bs_cnt = 0;
-
- while (*++p)
-   if (*p == L'\\')
-   if (++bs_cnt > 1)
- break;
-   }
- RtlInitCountedUnicodeString (&path_prefix, upath->Buffer,
-  (p - upath->Buffer) * sizeof (WCHAR));
- ffvi_buf.ffvi.VolumeSerialNumber = hash_path_name ((ino_t) 0,
-&path_prefix);
+ ffvi_buf.ffvi.VolumeSerialNumber = hash_prefix(upath);
}
   fs_info *fsi = fsi_cache.search (&ffvi_buf.ffvi, hash);
   if (fsi)
@@ -460,7 +488,7 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol)
 
   if (!in_vol)
 NtClose (vol);
-  fsi_cache.add (hash, this);
+  fsi_cache.add (hash, this, hash_prefix (upath));
   return true;
 }
 
diff --git a/winsup/cygwin/mount.h b/winsup/cygwin/mount.h
index 122a679a8..86b72fb4c 100644
--- a/winsup/cygwin/mount.h
+++ b/winsup/cygwin/mount.h
@@ -124,7 +124,7 @@ class fs_info
 
   const char *fsname () const { return fsn[0] ? f