This is the mail archive of the
cygwin-developers
mailing list for the Cygwin project.
Re: Cygwin Filesystem Performance degradation 1.7.5 vs 1.7.7, and methods for improving performance
Hi,
Patch for caching fs info.
Yoni.
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 15:20:42 -0000
@@ -48,6 +48,7 @@ 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_fs_info_cache = true;
/* is_unc_share: Return non-zero if PATH begins with //server/share
or with one of the native prefixes //./ or //?/
@@ -163,6 +164,99 @@ 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::update (PUNICODE_STRING upath, HANDLE in_vol)
{
@@ -183,6 +277,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 +527,8 @@ fs_info::update (PUNICODE_STRING upath,
if (!in_vol)
NtClose (vol);
fsi_cache.add (hash, this);
+ if (use_fs_info_cache)
+ 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 15:20:42 -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);
- References:
- Re: Cygwin Filesystem Performance degradation 1.7.5 vs 1.7.7, and methods for improving performance
- Re: Cygwin Filesystem Performance degradation 1.7.5 vs 1.7.7, and methods for improving performance
- Re: Cygwin Filesystem Performance degradation 1.7.5 vs 1.7.7, and methods for improving performance
- Re: Cygwin Filesystem Performance degradation 1.7.5 vs 1.7.7, and methods for improving performance
- Re: Cygwin Filesystem Performance degradation 1.7.5 vs 1.7.7, and methods for improving performance
- Re: Cygwin Filesystem Performance degradation 1.7.5 vs 1.7.7, and methods for improving performance
- Re: Cygwin Filesystem Performance degradation 1.7.5 vs 1.7.7, and methods for improving performance
- Re: Cygwin Filesystem Performance degradation 1.7.5 vs 1.7.7, and methods for improving performance
- Re: Cygwin Filesystem Performance degradation 1.7.5 vs 1.7.7, and methods for improving performance
- Re: Cygwin Filesystem Performance degradation 1.7.5 vs 1.7.7, and methods for improving performance
- Re: Cygwin Filesystem Performance degradation 1.7.5 vs 1.7.7, and methods for improving performance