summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/fhandler_disk_file.cc
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2006-01-28 13:41:22 +0000
committerCorinna Vinschen <corinna@vinschen.de>2006-01-28 13:41:22 +0000
commit7ab59dee9440f8de58e064271908d309daf95d68 (patch)
treee81d071cfb1ea4ea39c27ac95d6fbbc70f7d26a2 /winsup/cygwin/fhandler_disk_file.cc
parentfa3ffdd01ac7a014822ce546fda7d70612440e94 (diff)
downloadcygnal-7ab59dee9440f8de58e064271908d309daf95d68.tar.gz
cygnal-7ab59dee9440f8de58e064271908d309daf95d68.tar.bz2
cygnal-7ab59dee9440f8de58e064271908d309daf95d68.zip
* fhandler_disk_file.cc (DIR_NUM_ENTRIES): New define determining
minimum number of dir entries which fit into the readdir cache. (DIR_BUF_SIZE): Define globally as size of readdir cache. (struct __DIR_cache): New structure used for readdir caching on NT. (d_dirname): Accessor for struct __DIR_cache, use throughout. (d_pos): Ditto. (d_cache): Ditto. (fhandler_disk_file::opendir): Allocate __d_dirname to contain readdir cache on NT. (fhandler_disk_file::readdir): Use buf as pointer into readdir cache. Implement readdir caching.
Diffstat (limited to 'winsup/cygwin/fhandler_disk_file.cc')
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc154
1 files changed, 94 insertions, 60 deletions
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index d6b1cd282..54b2f17f6 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -1341,6 +1341,28 @@ fhandler_disk_file::rmdir ()
return res;
}
+/* This is the minimal number of entries which fit into the readdir cache.
+ The number of bytes allocated by the cache is determined by this number,
+ To tune caching, just tweak this number. To get a feeling for the size,
+ the size of the readdir cache is DIR_NUM_ENTRIES * 632 + 264 bytes. */
+
+#define DIR_NUM_ENTRIES 25 /* Cache size 16064 bytes */
+
+#define DIR_BUF_SIZE (DIR_NUM_ENTRIES \
+ * (sizeof (FILE_ID_BOTH_DIR_INFORMATION) \
+ + 2 * CYG_MAX_PATH))
+
+typedef struct __DIR_cache
+{
+ char __name[CYG_MAX_PATH];
+ ULONG __pos;
+ char __cache[DIR_BUF_SIZE];
+};
+
+#define d_dirname(d) (((struct __DIR_cache *) (d)->__d_dirname)->__name)
+#define d_pos(d) (((struct __DIR_cache *) (d)->__d_dirname)->__pos)
+#define d_cache(d) (((struct __DIR_cache *) (d)->__d_dirname)->__cache)
+
DIR *
fhandler_disk_file::opendir ()
{
@@ -1355,7 +1377,9 @@ fhandler_disk_file::opendir ()
set_errno (ENAMETOOLONG);
else if ((dir = (DIR *) malloc (sizeof (DIR))) == NULL)
set_errno (ENOMEM);
- else if ((dir->__d_dirname = (char *) malloc (len + 3)) == NULL)
+ else if ((dir->__d_dirname = (char *) malloc (wincap.is_winnt ()
+ ? sizeof (struct __DIR_cache)
+ : len + 3)) == NULL)
{
set_errno (ENOMEM);
goto free_dir;
@@ -1370,7 +1394,8 @@ fhandler_disk_file::opendir ()
goto free_dirent;
else
{
- strcpy (dir->__d_dirname, get_win32_name ());
+ strcpy (d_dirname (dir), get_win32_name ());
+ d_pos (dir) = 0;
dir->__d_dirent->__d_version = __DIRENT_VERSION;
cygheap_fdnew fd;
@@ -1387,9 +1412,9 @@ fhandler_disk_file::opendir ()
Appending a "*" is moved right before calling FindFirstFile.
Since FindFirstFile is only called once, this should even be a
teeny little bit faster. */
- len = strlen (dir->__d_dirname);
- if (len && !isdirsep (dir->__d_dirname[len - 1]))
- strcpy (dir->__d_dirname + len, "\\");
+ len = strlen (d_dirname (dir));
+ if (len && !isdirsep (d_dirname (dir)[len - 1]))
+ strcpy (d_dirname (dir) + len, "\\");
dir->__d_cookie = __DIRENT_COOKIE;
dir->__handle = INVALID_HANDLE_VALUE;
dir->__d_position = 0;
@@ -1470,7 +1495,7 @@ fhandler_disk_file::readdir_helper (DIR *dir, dirent *de, DWORD w32_err,
if (strcasematch (c + len - 4, ".lnk"))
{
char fbuf[CYG_MAX_PATH];
- strcpy (fbuf, dir->__d_dirname);
+ strcpy (fbuf, d_dirname (dir));
strcat (fbuf, c);
path_conv fpath (fbuf, PC_SYM_NOFOLLOW);
if (fpath.issymlink () || fpath.is_fs_special ())
@@ -1561,6 +1586,10 @@ fhandler_disk_file::readdir (DIR *dir, dirent *de)
{
int res = 0;
NTSTATUS status = STATUS_SUCCESS;
+ PFILE_ID_BOTH_DIR_INFORMATION buf = NULL;
+ wchar_t *FileName;
+ char fname[CYG_MAX_PATH];
+ IO_STATUS_BLOCK io;
if (!dir->__handle)
{
@@ -1571,74 +1600,79 @@ fhandler_disk_file::readdir (DIR *dir, dirent *de)
if (!wincap.is_winnt ())
return readdir_9x (dir, de);
-#define DIR_BUF_SIZE (sizeof (FILE_ID_BOTH_DIR_INFORMATION) + 2 * CYG_MAX_PATH)
- PFILE_ID_BOTH_DIR_INFORMATION buf = (PFILE_ID_BOTH_DIR_INFORMATION)
- alloca (DIR_BUF_SIZE);
- IO_STATUS_BLOCK io;
- wchar_t *FileName = buf->FileName;
- char fname[CYG_MAX_PATH];
+ /* d_pos always refers to the next cache entry to use. If it's 0, this means
+ we must reload the cache. */
+ if (d_pos (dir) == 0)
+ {
+ if ((dir->__flags & dirent_get_d_ino))
+ {
+ status = NtQueryDirectoryFile (dir->__handle, NULL, NULL, 0, &io,
+ d_cache (dir), DIR_BUF_SIZE,
+ FileIdBothDirectoryInformation,
+ FALSE, NULL, dir->__d_position == 0);
+ /* FileIdBothDirectoryInformation isn't supported for remote drives
+ on NT4 and 2K systems, and it's also not supported on 2K at all,
+ when accessing network drives on any remote OS. We just fall
+ back to using a standard directory query in this case and note
+ this case using the dirent_get_d_ino flag. */
+ if (status == STATUS_INVALID_LEVEL
+ || status == STATUS_INVALID_PARAMETER)
+ dir->__flags &= ~dirent_get_d_ino;
+ }
+ if (!(dir->__flags & dirent_get_d_ino))
+ status = NtQueryDirectoryFile (dir->__handle, NULL, NULL, 0, &io,
+ d_cache (dir), DIR_BUF_SIZE,
+ FileBothDirectoryInformation,
+ FALSE, NULL, dir->__d_position == 0);
+ }
- if ((dir->__flags & dirent_get_d_ino))
- {
- status = NtQueryDirectoryFile (dir->__handle, NULL, NULL, 0, &io,
- buf, DIR_BUF_SIZE,
- FileIdBothDirectoryInformation,
- TRUE, NULL, dir->__d_position == 0);
- /* FileIdBothDirectoryInformation isn't supported for remote drives
- on NT4 and 2K systems, and it's also not supported on 2K at all,
- when accessing network drives on any remote OS. We just fall
- back to using a standard directory query in this case and note
- this case using the dirent_get_d_ino flag. */
- if (!status)
- {
+ if (!status)
+ {
+ buf = (PFILE_ID_BOTH_DIR_INFORMATION) (d_cache (dir) + d_pos (dir));
+ if (buf->NextEntryOffset == 0)
+ d_pos (dir) = 0;
+ else
+ d_pos (dir) += buf->NextEntryOffset;
+ if ((dir->__flags & dirent_get_d_ino))
+ {
+ FileName = buf->FileName;
if ((dir->__flags & dirent_set_d_ino))
de->d_ino = buf->FileId.QuadPart;
}
- else if (status == STATUS_INVALID_LEVEL
- || status == STATUS_INVALID_PARAMETER)
- dir->__flags &= ~dirent_get_d_ino;
- }
- if (!(dir->__flags & dirent_get_d_ino))
- {
- status = NtQueryDirectoryFile (dir->__handle, NULL, NULL, 0, &io, buf,
- DIR_BUF_SIZE, FileBothDirectoryInformation,
- TRUE, NULL, dir->__d_position == 0);
- FileName = ((PFILE_BOTH_DIR_INFORMATION) buf)->FileName;
- }
- if (!status && de->d_ino == 0 && (dir->__flags & dirent_set_d_ino))
- {
- OBJECT_ATTRIBUTES attr;
-
- if (dir->__d_position == 0 && buf->FileNameLength == 2
- && FileName[0] == '.')
- de->d_ino = readdir_get_ino_by_handle (dir->__handle);
- else if (dir->__d_position == 1 && buf->FileNameLength == 4
- && FileName[0] == '.' && FileName[1] == '.')
- de->d_ino = readdir_get_ino (dir, pc.normalized_path, true);
else
+ FileName = ((PFILE_BOTH_DIR_INFORMATION) buf)->FileName;
+
+ if (de->d_ino == 0 && (dir->__flags & dirent_set_d_ino))
{
- HANDLE hdl;
- UNICODE_STRING upath = {buf->FileNameLength, CYG_MAX_PATH * 2,
- FileName};
- InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE,
- dir->__handle , NULL);
- if (!NtOpenFile (&hdl, READ_CONTROL, &attr, &io,
- wincap.shared (), 0))
+ OBJECT_ATTRIBUTES attr;
+
+ if (dir->__d_position == 0 && buf->FileNameLength == 2
+ && FileName[0] == '.')
+ de->d_ino = readdir_get_ino_by_handle (dir->__handle);
+ else if (dir->__d_position == 1 && buf->FileNameLength == 4
+ && FileName[0] == '.' && FileName[1] == '.')
+ de->d_ino = readdir_get_ino (dir, pc.normalized_path, true);
+ else
{
- de->d_ino = readdir_get_ino_by_handle (hdl);
- CloseHandle (hdl);
+ HANDLE hdl;
+ UNICODE_STRING upath = {buf->FileNameLength, CYG_MAX_PATH * 2,
+ FileName};
+ InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE,
+ dir->__handle , NULL);
+ if (!NtOpenFile (&hdl, READ_CONTROL, &attr, &io,
+ wincap.shared (), 0))
+ {
+ de->d_ino = readdir_get_ino_by_handle (hdl);
+ CloseHandle (hdl);
+ }
}
}
- }
-
- if (!status)
- {
wcstombs (fname, FileName, buf->FileNameLength / 2);
fname[buf->FileNameLength / 2] = '\0';
}
if (!(res = readdir_helper (dir, de, RtlNtStatusToDosError (status),
- buf->FileAttributes, fname)))
+ buf ? buf->FileAttributes : 0, fname)))
dir->__d_position++;
else if (!(dir->__flags & dirent_saw_dot))
{