This is the mail archive of the cygwin-developers 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]

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


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);
}




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