This is the mail archive of the cygwin-cvs@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[newlib-cygwin] cygwin: readdir: don't lookup mount target inodes


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=8eada332236791bb3757091d867d3ef5f93a13d3

commit 8eada332236791bb3757091d867d3ef5f93a13d3
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Wed Jun 14 13:22:56 2017 +0200

    cygwin: readdir: don't lookup mount target inodes
    
    So far Cygwin's readdir returned the inode number of a mount target
    in d_ino, rather than the actual inode number of the mount point in
    the underlying filesystem.  This not only results in a performance
    hit if the mount target is a remote FS, it is also not done on other
    POSIX systems.
    
    Remove the code evaluating the mount target inode number.
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 winsup/cygwin/fhandler_disk_file.cc | 71 ++++++++++++++++---------------------
 1 file changed, 30 insertions(+), 41 deletions(-)

diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index f360304..01a9afe 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -28,6 +28,12 @@ details. */
 #define _COMPILING_NEWLIB
 #include <dirent.h>
 
+enum __DIR_mount_type {
+  __DIR_mount_none = 0,
+  __DIR_mount_target,
+  __DIR_mount_virt_target
+};
+
 class __DIR_mounts
 {
   int		 count;
@@ -41,23 +47,6 @@ class __DIR_mounts
 #define __DIR_CYGDRIVE	(MAX_MOUNTS+1)
 #define __DIR_DEV	(MAX_MOUNTS+2)
 
-  ino_t eval_ino (int idx)
-    {
-      ino_t ino = 0;
-      char fname[parent_dir_len + mounts[idx].Length + 2];
-      struct stat st;
-
-      char *c = stpcpy (fname, parent_dir);
-      if (c[- 1] != '/')
-	*c++ = '/';
-      sys_wcstombs (c, mounts[idx].Length + 1,
-		    mounts[idx].Buffer, mounts[idx].Length / sizeof (WCHAR));
-      path_conv pc (fname, PC_SYM_NOFOLLOW | PC_POSIX | PC_KEEP_HANDLE);
-      if (!stat_worker (pc, &st))
-	ino = st.st_ino;
-      return ino;
-    }
-
 public:
   __DIR_mounts (const char *posix_path)
   : parent_dir (posix_path)
@@ -73,48 +62,47 @@ public:
 	RtlFreeUnicodeString (&mounts[i]);
       RtlFreeUnicodeString (&cygdrive);
     }
-  ino_t check_mount (PUNICODE_STRING fname, ino_t ino,
-			 bool eval = true)
+  /* For an entry within this dir, check if a mount point exists. */
+  bool check_mount (PUNICODE_STRING fname)
     {
       if (parent_dir_len == 1)	/* root dir */
 	{
 	  if (RtlEqualUnicodeString (fname, &ro_u_proc, FALSE))
 	    {
 	      found[__DIR_PROC] = true;
-	      return 2;
+	      return true;
 	    }
 	  if (RtlEqualUnicodeString (fname, &ro_u_dev, FALSE))
 	    {
 	      found[__DIR_DEV] = true;
-	      return 2;
+	      return true;
 	    }
 	  if (fname->Length / sizeof (WCHAR) == mount_table->cygdrive_len - 2
 	      && RtlEqualUnicodeString (fname, &cygdrive, FALSE))
 	    {
 	      found[__DIR_CYGDRIVE] = true;
-	      return 2;
+	      return true;
 	    }
 	}
       for (int i = 0; i < count; ++i)
 	if (RtlEqualUnicodeString (fname, &mounts[i], FALSE))
 	  {
 	    found[i] = true;
-	    return eval ? eval_ino (i) : 1;
+	    return true;
 	  }
-      return ino;
+      return false;
     }
-  ino_t check_missing_mount (PUNICODE_STRING retname = NULL)
+  /* On each call, add another mount point within this directory, which is
+     not backed by a real subdir. */
+  __DIR_mount_type check_missing_mount (PUNICODE_STRING retname = NULL)
     {
       for (int i = 0; i < count; ++i)
 	if (!found[i])
 	  {
 	    found[i] = true;
 	    if (retname)
-	      {
-		*retname = mounts[i];
-		return eval_ino (i);
-	      }
-	    return 1;
+	      *retname = mounts[i];
+	    return __DIR_mount_target;
 	  }
       if (parent_dir_len == 1)  /* root dir */
 	{
@@ -123,14 +111,14 @@ public:
 	      found[__DIR_PROC] = true;
 	      if (retname)
 		*retname = ro_u_proc;
-	      return 2;
+	      return __DIR_mount_virt_target;
 	    }
 	  if (!found[__DIR_DEV])
 	    {
 	      found[__DIR_DEV] = true;
 	      if (retname)
 		*retname = ro_u_dev;
-	      return 2;
+	      return __DIR_mount_virt_target;
 	    }
 	  if (!found[__DIR_CYGDRIVE])
 	    {
@@ -139,11 +127,11 @@ public:
 		{
 		  if (retname)
 		    *retname = cygdrive;
-		  return 2;
+		  return __DIR_mount_virt_target;
 		}
 	    }
 	}
-      return 0;
+      return __DIR_mount_none;
     }
     void rewind () { memset (found, 0, sizeof found); }
 };
@@ -1989,16 +1977,17 @@ fhandler_disk_file::readdir_helper (DIR *dir, dirent *de, DWORD w32_err,
 {
   if (w32_err)
     {
-      bool added = false;
-      if ((de->d_ino = d_mounts (dir)->check_missing_mount (fname)))
-	added = true;
-      if (!added)
+      switch (d_mounts (dir)->check_missing_mount (fname))
 	{
+	case __DIR_mount_none:
 	  fname->Length = 0;
 	  return geterrno_from_win_error (w32_err);
+	case __DIR_mount_virt_target:
+	  de->d_type = DT_DIR;
+	  break;
+	default:
+	  break;
 	}
-      if (de->d_ino == 2)	/* Inode number for virtual dirs. */
-	de->d_type = DT_DIR;
       attr = 0;
       dir->__flags &= ~dirent_set_d_ino;
     }
@@ -2216,7 +2205,7 @@ go_ahead:
 		((PFILE_BOTH_DIR_INFORMATION) buf)->FileAttributes;
 	}
       RtlInitCountedUnicodeString (&fname, FileName, FileNameLength);
-      de->d_ino = d_mounts (dir)->check_mount (&fname, de->d_ino);
+      d_mounts (dir)->check_mount (&fname);
       if (de->d_ino == 0 && (dir->__flags & dirent_set_d_ino))
 	{
 	  /* Don't try to optimize relative to dir->__d_position.  On several


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]