Cygwin Filesystem Performance degradation 1.7.5 vs 1.7.7, and methods for improving performance

Yoni Londner yonihola2@gmail.com
Wed Oct 13 14:30:00 GMT 2010


Hi,

I have prepared a patch with the following changes (I know you guys 
prefer separate patch for each change - I will send multiple patches 
later today):

- caching symlink content (symlink_info::check). If we know that a file 
is a symlink, as long as all it attributes did not change (CreationTime, 
LastWriteTime ChangeTime, AllocationSize and FileAttributes) - then we 
can be sure it is still pointing to the same file. this way we dont need 
to open the file for reading (and read the content)

- caching exec_state (fhandler_base::fstat_helper). as above, there is 
no need to open the file and check the prefix, if we already did that 
earlier.

- reuse QueryInformationFile (fhandler_base::fstat_by_handle). as the 
comment there explain: "If the file has been opened for other purposes 
than stat, we can't rely on the information stored in pc.fnoi". but if 
it is open for stat, we can use the information!

- caching fs_info (fs_info::update): I know there is already caching 
mechanism here, but my solution does not call 
NtQueryVolumeInformationFile even once. (this option is not used by default)

- not using ACL. this option is not used by default. it allows the user 
to decide whether he wants to use ACL or not in runtime.

Yoni.

Index: environ.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/environ.cc,v
retrieving revision 1.183
diff -u -p -r1.183 environ.cc
--- environ.cc	18 May 2010 14:30:50 -0000	1.183
+++ environ.cc	13 Oct 2010 14:05:40 -0000
@@ -34,6 +34,9 @@ details. */
  extern bool dos_file_warning;
  extern bool ignore_case_with_glob;
  extern bool allow_winsymlinks;
+extern bool use_acl;
+extern bool use_file_cache;
+extern bool use_fs_info_cache;
  bool reset_com = false;
  static bool envcache = true;
  static bool create_upcaseenv = false;
@@ -605,6 +608,9 @@ static struct parse_thing
    {"tty", {NULL}, set_process_state, NULL, {{0}, {PID_USETTY}}},
    {"upcaseenv", {&create_upcaseenv}, justset, NULL, {{false}, {true}}},
    {"winsymlinks", {&allow_winsymlinks}, justset, NULL, {{false}, {true}}},
+  {"use_acl", {&use_acl}, justset, NULL, {{false}, {true}}},
+  {"use_file_cache", {&use_file_cache}, justset, NULL, {{false}, {true}}},
+  {"use_fs_info_cache", {&use_fs_info_cache}, justset, NULL, {{false}, 
{true}}},
    {NULL, {0}, justset, 0, {{0}, {0}}}
  };

@@ -616,6 +622,7 @@ parse_options (char *buf)
    int istrue;
    char *p, *lasts;
    parse_thing *k;
+  TCHAR exe_name[MAX_PATH];

    if (buf == NULL)
      {
@@ -694,6 +701,11 @@ parse_options (char *buf)
  	    break;
  	  }
        }
+  if (GetModuleFileName(0, exe_name, MAX_PATH) && (strstr(exe_name, 
"chmod") ||
+      strstr(exe_name, "chown") || strstr(exe_name, "chgrp")))
+    {
+      use_acl = 1;
+    }
    debug_printf ("returning");
  }

Index: fhandler_disk_file.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fhandler_disk_file.cc,v
retrieving revision 1.345
diff -u -p -r1.345 fhandler_disk_file.cc
--- fhandler_disk_file.cc	7 Oct 2010 14:03:26 -0000	1.345
+++ fhandler_disk_file.cc	13 Oct 2010 14:05:41 -0000
@@ -346,9 +346,9 @@ fhandler_base::fstat_by_handle (struct _

    /* If the file has been opened for other purposes than stat, we 
can't rely
       on the information stored in pc.fnoi.  So we overwrite them here. */
-  if (get_io_handle ())
+  if (get_io_handle () && !(pc.opts & PC_STAT))
      {
-      PFILE_NETWORK_OPEN_INFORMATION pfnoi = pc.fnoi ();
+      PFILE_CYGWIN_INFORMATION pfnoi = pc.fnoi ();
        status = NtQueryInformationFile (h, &io, pfnoi, sizeof *pfnoi,
                                        FileNetworkOpenInformation);
        if (!NT_SUCCESS (status))
@@ -485,7 +485,7 @@ fhandler_base::fstat_helper (struct __st
    IO_STATUS_BLOCK st;
    FILE_COMPRESSION_INFORMATION fci;
    HANDLE h = get_stat_handle ();
-  PFILE_NETWORK_OPEN_INFORMATION pfnoi = pc.fnoi ();
+  PFILE_CYGWIN_INFORMATION pfnoi = pc.fnoi ();
    ULONG attributes = pc.file_attributes ();

    to_timestruc_t ((PFILETIME) &pfnoi->LastAccessTime, &buf->st_atim);
@@ -590,8 +590,14 @@ fhandler_base::fstat_helper (struct __st
        else
  	{
  	  buf->st_mode |= S_IFREG;
+	  file_cache_t *s = NULL;
+	  if ((s = file_cache_lookup(pc.get_win32(), pfnoi)) &&
+	      s->exec_state>=0)
+	    {
+	      pc.set_exec(s->exec_state);
+	    }
  	  /* Check suffix for executable file. */
-	  if (pc.exec_state () != is_executable)
+	  else if (pc.exec_state () != is_executable)
  	    {
  	      PUNICODE_STRING path = pc.get_nt_native_path ();

@@ -638,6 +644,11 @@ fhandler_base::fstat_helper (struct __st
  		  NtClose (h);
  		}
  	    }
+	    if (!s)
+	    {
+		file_cache_update(pc.get_win32(), pfnoi, NULL, 0,
+		    pc.exec_state());
+	    }
  	}
        if (pc.exec_state () == is_executable)
  	buf->st_mode |= STD_XBITS;
Index: mount.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/mount.cc,v
retrieving revision 1.72
diff -u -p -r1.72 mount.cc
--- mount.cc	28 Sep 2010 14:49:31 -0000	1.72
+++ mount.cc	13 Oct 2010 14:05:43 -0000
@@ -48,6 +48,8 @@ details. */
  bool NO_COPY mount_info::got_usr_bin;
  bool NO_COPY mount_info::got_usr_lib;
  int NO_COPY mount_info::root_idx = -1;
+bool use_acl = true;
+bool use_fs_info_cache = false;

  /* is_unc_share: Return non-zero if PATH begins with //server/share
  		 or with one of the native prefixes //./ or //?/
@@ -163,6 +165,109 @@ fs_info_cache::add (uint32_t hashval, fs
    fsi_lock.release ();
  }

+typedef struct fs_info_list_t {
+    struct fs_info_list_t *next;
+    fs_info fsi;
+    wchar_t path[MAX_PATH];
+    int path_len;
+} fs_info_list_t;
+
+static fs_info_list_t *fs_info_list;
+static int in_fs_info_update;
+
+int fs_info_lookup(fs_info *fsi, PUNICODE_STRING upath)
+{
+    int shortest = 0;
+    fs_info_list_t *f, *found = NULL;
+    if (in_fs_info_update)
+	return 0;
+    /* find first (longest match) */
+    for (f = fs_info_list; f != NULL; f=f->next)
+    {
+	if (!wcsncmp(f->path, upath->Buffer, f->path_len))
+	{
+	    if (!shortest || shortest > f->path_len)
+	    {
+		shortest = f->path_len;
+		found = f;
+	    }
+	}
+    }
+    if (!found)
+	return 0;
+    memcpy(fsi, &found->fsi, sizeof(fsi));
+    return 1;
+}
+
+static inline int fs_info_eq(fs_info *a, fs_info *b)
+{
+    return a->serial_number()==b->serial_number() &&
+	!memcmp(&a->status, &b->status, sizeof(a->status));
+}
+
+static void fs_info_update(fs_info *fsi, PUNICODE_STRING upath)
+{
+    wchar_t scan_path[MAX_PATH], save, *p;
+    fs_info *_fsi, *scan = NULL;
+    fs_info_list_t *f;
+    UNICODE_STRING  ustr;
+    if (in_fs_info_update)
+	return;
+    in_fs_info_update++;
+    _fsi = new fs_info();
+    _fsi->update(upath, NULL);
+    /* sanity check */
+    if (!fs_info_eq(_fsi, fsi))
+    {
+	debug_printf("fs_info_update: strange: got different volume");
+	delete _fsi;
+	goto Exit;
+    }
+    /* scan up the path to find the base directory of the mount */
+    wcscpy(scan_path, upath->Buffer);
+    while ((p=wcsrchr(scan_path, '\\')))
+    {
+	save = *p;
+	*p = 0;
+	if (p==scan_path)
+	{
+	    *p = save;
+	    break;
+	}
+	if (scan)
+	    delete scan;
+	scan = new fs_info();
+	ustr.Buffer = scan_path;
+	ustr.Length = wcslen(scan_path);
+	ustr.MaximumLength = sizeof(scan_path);
+	if (!scan->update(&ustr, NULL) || !fs_info_eq(scan, fsi))
+	{
+	    *p = save;
+	    break;
+	}
+    }
+    if (scan)
+	delete scan;
+    f = (fs_info_list_t*)calloc(sizeof(*f), 1);
+    memcpy(&f->fsi, _fsi, sizeof(_fsi));
+    f->path_len = wcslen(scan_path);
+    wcscpy(f->path, scan_path);
+    f->next = fs_info_list;
+    fs_info_list = f;
+Exit:
+    in_fs_info_update--;
+}
+
+bool fs_info::has_acls(bool val)
+{
+  return (bool) (status.has_acls = val);
+}
+
+bool fs_info::has_acls() const
+{
+  return use_acl ? status.has_acls : 0;
+}
+
  bool
  fs_info::update (PUNICODE_STRING upath, HANDLE in_vol)
  {
@@ -183,6 +288,8 @@ fs_info::update (PUNICODE_STRING upath,
    } ffvi_buf;
    UNICODE_STRING fsname;

+  if (use_fs_info_cache && fs_info_lookup(this, upath))
+       return true;
    clear ();
    if (in_vol)
      vol = in_vol;
@@ -431,6 +538,8 @@ fs_info::update (PUNICODE_STRING upath,
    if (!in_vol)
      NtClose (vol);
    fsi_cache.add (hash, this);
+  if (use_fs_info_cache && !use_acl)
+       fs_info_update(this, upath);
    return true;
  }

Index: mount.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/mount.h,v
retrieving revision 1.15
diff -u -p -r1.15 mount.h
--- mount.h	21 Sep 2010 16:32:22 -0000	1.15
+++ mount.h	13 Oct 2010 14:05:43 -0000
@@ -43,6 +43,11 @@ extern struct fs_names_t {

  class fs_info
  {
+  ULONG sernum;			/* Volume Serial Number */
+  char fsn[80];			/* Windows filesystem name */
+  unsigned long got_fs () const { return status.fs_type != none; }
+
+ public:
    struct status_flags
    {
      ULONG flags;		/* Volume flags */
@@ -59,11 +64,7 @@ class fs_info
      unsigned has_buggy_basic_info	: 1;
      unsigned has_dos_filenames_only	: 1;
    } status;
-  ULONG sernum;			/* Volume Serial Number */
-  char fsn[80];			/* Windows filesystem name */
-  unsigned long got_fs () const { return status.fs_type != none; }

- public:
    void clear ()
    {
      memset (&status, 0 , sizeof status);
@@ -76,7 +77,8 @@ class fs_info
    IMPLEMENT_STATUS_FLAG (ULONG, samba_version)
    IMPLEMENT_STATUS_FLAG (ULONG, name_len)
    IMPLEMENT_STATUS_FLAG (bool, is_remote_drive)
-  IMPLEMENT_STATUS_FLAG (bool, has_acls)
+  bool has_acls(bool val);
+  bool has_acls() const;
    IMPLEMENT_STATUS_FLAG (bool, hasgood_inode)
    IMPLEMENT_STATUS_FLAG (bool, caseinsensitive)
    IMPLEMENT_STATUS_FLAG (bool, has_buggy_open)
Index: path.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/path.cc,v
retrieving revision 1.617
diff -u -p -r1.617 path.cc
--- path.cc	9 Oct 2010 10:54:13 -0000	1.617
+++ path.cc	13 Oct 2010 14:05:47 -0000
@@ -73,6 +73,7 @@
  #include <wctype.h>

  bool dos_file_warning = true;
+bool use_file_cache = true;

  suffix_info stat_suffixes[] =
  {
@@ -604,6 +605,7 @@ path_conv::check (const char *src, unsig
    bool is_relpath;
    char *tail, *path_end;

+  opts = opt;
  #if 0
    static path_conv last_path_conv;
    static char last_src[CYG_MAX_PATH];
@@ -1876,6 +1878,7 @@ symlink_info::check_sysfile (HANDLE h)
        else
  	res = posixify (srcbuf);
      }
+  debug_printf ("res %d", res);
    return res;
  }

@@ -2213,6 +2216,95 @@ symlink_info::parse_device (const char *
     Return -1 on error, 0 if PATH is not a symlink, or the length
     stored into BUF if PATH is a symlink.  */

+static inline unsigned int hash_from_int(unsigned int val)
+{
+    return val * 1103515245 + 12345; /* from rand() implementaion */
+}
+
+static inline unsigned int hash_from_mem(const char *buf, int len)
+{
+    unsigned int val = 0;
+    int i = 0, len4 = len & ~3;
+    for (; i<len4; i+=4)
+        val = hash_from_int(val ^ *(int *)(buf+i));
+    for (; i<len; i++)
+        val = hash_from_int(val ^ buf[i]);
+    return val;
+}
+
+static inline unsigned int hash_from_str(const char *str)
+{
+    return hash_from_mem(str, strlen(str));
+}
+
+#define FILE_CACHE_SIZE 1000
+#define FILE_CACHE_BUCKET 10
+typedef struct {
+    file_cache_t *f[FILE_CACHE_BUCKET];
+    int i;
+} file_cache_hash_t;
+static file_cache_hash_t file_cache[FILE_CACHE_SIZE];
+
+void file_cache_update(const char *path,
+    FILE_CYGWIN_INFORMATION *fnoi, char *contents, int symlink_len,
+    int exec_state)
+{
+    if (!use_file_cache)
+	return;
+    unsigned int hash = hash_from_str(path), bucket = hash%FILE_CACHE_SIZE;
+    int i;
+    file_cache_hash_t *c = &file_cache[bucket];
+    file_cache_t *s = (file_cache_t*)calloc(sizeof(file_cache_t), 1), *_s;
+    s->path = strdup(path);
+    s->hash = hash;
+    if (exec_state>=0)
+	s->exec_state = exec_state;
+    if (contents)
+	s->contents = strdup(contents);
+    if (symlink_len)
+	s->symlink_len = symlink_len;
+    memcpy(&s->fnoi, fnoi, sizeof(FILE_CYGWIN_INFORMATION));
+    /* if the same file is already in the cache - replace it */
+    for (i=0; i<FILE_CACHE_BUCKET && c->f[i] && c->f[i]->hash!=hash; i++);
+    if (i==FILE_CACHE_BUCKET)
+    {
+	/* file not yet in cache - do round robin */
+	i = c->i;
+	c->i = (c->i+1) % FILE_CACHE_BUCKET;
+    }
+    if ((_s = c->f[i]))
+    {
+	free(_s->path);
+	free(_s);
+    }
+    c->f[i] = s;
+}
+
+file_cache_t *file_cache_lookup(const char *path,
+    FILE_CYGWIN_INFORMATION *fnoi)
+{
+    if (!use_file_cache)
+	return NULL;
+    unsigned int hash = hash_from_str(path), bucket = hash%FILE_CACHE_SIZE;
+    file_cache_hash_t *c = &file_cache[bucket];
+    file_cache_t *s = NULL;
+    for (int i=0; i<FILE_CACHE_BUCKET; i++)
+    {
+	s = c->f[i];
+	if (!s)
+	    return NULL;
+	if (s->hash != hash || strcmp(path, s->path))
+	    continue;
+	/* its the same file */
+	return fnoi->CreationTime.QuadPart==s->fnoi.CreationTime.QuadPart &&
+	    fnoi->LastWriteTime.QuadPart==s->fnoi.LastWriteTime.QuadPart &&
+	    fnoi->ChangeTime.QuadPart==s->fnoi.ChangeTime.QuadPart &&
+	    fnoi->AllocationSize.QuadPart==s->fnoi.AllocationSize.QuadPart &&
+	    fnoi->FileAttributes==s->fnoi.FileAttributes ? s : NULL;
+    }
+    return NULL;
+}
+
  int
  symlink_info::check (char *path, const suffix_info *suffixes, fs_info &fs,
  		     path_conv_handle &conv_hdl)
@@ -2386,7 +2478,7 @@ restart:
  	    }
  	  else
  	    {
-	      PFILE_NETWORK_OPEN_INFORMATION pfnoi = conv_hdl.fnoi ();
+	      PFILE_CYGWIN_INFORMATION pfnoi = conv_hdl.fnoi ();

  	      status = NtQueryInformationFile (h, &io, pfnoi, sizeof *pfnoi,
  					       FileNetworkOpenInformation);
@@ -2500,7 +2592,7 @@ restart:
  		    }
  		  else
  		    {
-		      PFILE_NETWORK_OPEN_INFORMATION pfnoi = conv_hdl.fnoi ();
+		      PFILE_CYGWIN_INFORMATION pfnoi = conv_hdl.fnoi ();

  		      fileattr = fdi_buf.fdi.FileAttributes;
  		      memcpy (pfnoi, &fdi_buf.fdi.CreationTime, sizeof *pfnoi);
@@ -2622,18 +2714,28 @@ restart:
  	       == FILE_ATTRIBUTE_SYSTEM)
  	{
  	  HANDLE sym_h;
-
-	  status = NtOpenFile (&sym_h, SYNCHRONIZE | GENERIC_READ, &attr, &io,
-			       FILE_SHARE_VALID_FLAGS,
-			       FILE_OPEN_FOR_BACKUP_INTENT
-			       | FILE_SYNCHRONOUS_IO_NONALERT);
-
-	  if (!NT_SUCCESS (status))
-	    res = 0;
+	  file_cache_t *s = NULL;
+	  if ((s = file_cache_lookup(path, conv_hdl.fnoi ())) &&
+	      (res = s->symlink_len)>0)
+	    {
+	      strcpy(contents, s->contents);
+	      pflags |= PATH_SYMLINK;
+	    }
  	  else
  	    {
-	      res = check_sysfile (sym_h);
-	      NtClose (sym_h);
+	      status = NtOpenFile (&sym_h, SYNCHRONIZE | GENERIC_READ, &attr,
+		                   &io, FILE_SHARE_VALID_FLAGS,
+			           FILE_OPEN_FOR_BACKUP_INTENT
+			           | FILE_SYNCHRONOUS_IO_NONALERT);
+
+	      if (!NT_SUCCESS (status))
+	        res = 0;
+	      else
+	        {
+	          res = check_sysfile (sym_h);
+		  file_cache_update(path, conv_hdl.fnoi (), contents, res, -1);
+	          NtClose (sym_h);
+	        }
  	    }
  	  if (res)
  	    break;
Index: path.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/path.h,v
retrieving revision 1.152
diff -u -p -r1.152 path.h
--- path.h	7 Oct 2010 14:03:26 -0000	1.152
+++ path.h	13 Oct 2010 14:05:48 -0000
@@ -60,7 +60,8 @@ enum pathconv_arg
    PC_POSIX		= 0x0080,
    PC_NOWARN		= 0x0100,
    PC_KEEP_HANDLE	= 0x00400000,
-  PC_NO_ACCESS_CHECK	= 0x00800000
+  PC_NO_ACCESS_CHECK	= 0x00800000,
+  PC_STAT       	= 0x01000000,
  };

  #define PC_NONULLEMPTY -1
@@ -90,23 +91,26 @@ enum path_types
  };

  class symlink_info;
-struct _FILE_NETWORK_OPEN_INFORMATION;
+/* Identical to FILE_NETWORK_OPEN_INFORMATION.  We don't want to pull in
+   ntdll.h here, though. */
+typedef struct _FILE_CYGWIN_INFORMATION
+{
+  LARGE_INTEGER CreationTime;
+  LARGE_INTEGER LastAccessTime;
+  LARGE_INTEGER LastWriteTime;
+  LARGE_INTEGER ChangeTime;
+  LARGE_INTEGER AllocationSize;
+  LARGE_INTEGER EndOfFile;
+  ULONG FileAttributes;
+  ULONG ReparseTag;
+  LARGE_INTEGER FileId;
+} FILE_CYGWIN_INFORMATION, *PFILE_CYGWIN_INFORMATION;

  class path_conv_handle
  {
    HANDLE      hdl;
    union {
-    /* Identical to FILE_NETWORK_OPEN_INFORMATION.  We don't want to 
pull in
-       ntdll.h here, though. */
-    struct {
-      LARGE_INTEGER CreationTime;
-      LARGE_INTEGER LastAccessTime;
-      LARGE_INTEGER LastWriteTime;
-      LARGE_INTEGER ChangeTime;
-      LARGE_INTEGER AllocationSize;
-      LARGE_INTEGER EndOfFile;
-      ULONG FileAttributes;
-    } _fnoi;
+    FILE_CYGWIN_INFORMATION _fnoi;
      /* For NFS. */
      fattr3 _fattr3;
    } attribs;
@@ -127,12 +131,26 @@ public:
        hdl = NULL;
    }
    inline HANDLE handle () const { return hdl; }
-  inline struct _FILE_NETWORK_OPEN_INFORMATION *fnoi ()
-  { return (struct _FILE_NETWORK_OPEN_INFORMATION *) &attribs._fnoi; }
+  inline FILE_CYGWIN_INFORMATION *fnoi ()
+  { return (FILE_CYGWIN_INFORMATION *) &attribs._fnoi; }
    inline struct fattr3 *nfsattr ()
    { return (struct fattr3 *) &attribs._fattr3; }
  };

+typedef struct {
+    FILE_CYGWIN_INFORMATION fnoi;
+    char *path;
+    char *contents;
+    int symlink_len;
+    int exec_state;
+    unsigned int hash;
+} file_cache_t;
+
+void file_cache_update(const char *path,
+    FILE_CYGWIN_INFORMATION *fnoi, char *contents, int symlink_len,
+    int exec_state);
+file_cache_t *file_cache_lookup(const char *path, 
FILE_CYGWIN_INFORMATION *fnoi);
+
  class path_conv
  {
    DWORD fileattr;
@@ -145,6 +163,7 @@ class path_conv
    const char *path;
    path_conv_handle conv_handle;
   public:
+  unsigned opts;
    unsigned path_flags;
    const char *known_suffix;
    const char *normalized_path;
@@ -320,7 +339,7 @@ class path_conv
    bool is_binary ();

    HANDLE handle () const { return conv_handle.handle (); }
-  struct _FILE_NETWORK_OPEN_INFORMATION *fnoi () { return 
conv_handle.fnoi (); }
+  FILE_CYGWIN_INFORMATION *fnoi () { return conv_handle.fnoi (); }
    struct fattr3 *nfsattr () { return conv_handle.nfsattr (); }
    void reset_conv_handle () { conv_handle.set (NULL); }
    void close_conv_handle () { conv_handle.close (); }
Index: spawn.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/spawn.cc,v
retrieving revision 1.295
diff -u -p -r1.295 spawn.cc
--- spawn.cc	20 Sep 2010 22:28:57 -0000	1.295
+++ spawn.cc	13 Oct 2010 14:05:49 -0000
@@ -788,7 +788,7 @@ loop:
  	      myself->wr_proc_pipe_owner = GetCurrentProcessId ();
  	      myself->wr_proc_pipe = orig_wr_proc_pipe;
  	    }
-	  if (!ch.proc_retry (pi.hProcess))
+	  if (0 && !ch.proc_retry (pi.hProcess))
  	    {
  	      looped++;
  	      goto loop;
Index: syscalls.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/syscalls.cc,v
retrieving revision 1.570
diff -u -p -r1.570 syscalls.cc
--- syscalls.cc	28 Sep 2010 07:54:52 -0000	1.570
+++ syscalls.cc	13 Oct 2010 14:05:54 -0000
@@ -1619,7 +1619,8 @@ extern "C" int
  stat64 (const char *name, struct __stat64 *buf)
  {
    syscall_printf ("entering");
-  path_conv pc (name, PC_SYM_FOLLOW | PC_POSIX | PC_KEEP_HANDLE, 
stat_suffixes);
+  path_conv pc (name, PC_SYM_FOLLOW | PC_POSIX | PC_KEEP_HANDLE | PC_STAT,
+      stat_suffixes);
    return stat_worker (pc, buf);
  }

@@ -1658,7 +1659,7 @@ extern "C" int
  lstat64 (const char *name, struct __stat64 *buf)
  {
    syscall_printf ("entering");
-  path_conv pc (name, PC_SYM_NOFOLLOW | PC_POSIX | PC_KEEP_HANDLE,
+  path_conv pc (name, PC_SYM_NOFOLLOW | PC_POSIX | PC_KEEP_HANDLE | 
PC_STAT,
  		stat_suffixes);
    return stat_worker (pc, buf);
  }




More information about the Cygwin-developers mailing list