ntdll: Avoid one of the calls to getattrlist() when read_directory_getattrlist() checks the case sensitivity of the file system.

Extract a new function, get_dir_case_sensitivity_attr_by_id(), from
get_dir_case_sensitivity_attr().  Call that instead of get_dir_case_sensitivity()
from read_directory_getattrlist().  We get the device and file system IDs from
the same getattrlist() call we're already doing, so that avoids an extra call.
This commit is contained in:
Ken Thomases 2015-05-21 11:13:35 -05:00 committed by Alexandre Julliard
parent dec7b246f8
commit 5514df9d4e
1 changed files with 40 additions and 22 deletions

View File

@ -983,43 +983,35 @@ static void add_fs_cache( dev_t dev, fsid_t fsid, BOOLEAN case_sensitive )
} }
/*********************************************************************** /***********************************************************************
* get_dir_case_sensitivity_attr * get_dir_case_sensitivity_attr_by_id
* *
* Checks if the volume containing the specified directory is case * Checks if the volume with the specified device and file system IDs
* sensitive or not. Uses getattrlist(2). * is case sensitive or not. Uses getattrlist(2).
*/ */
static int get_dir_case_sensitivity_attr( const char *dir ) static int get_dir_case_sensitivity_attr_by_id( dev_t dev, fsid_t fsid )
{ {
char *mntpoint = NULL; char *mntpoint = NULL;
struct attrlist attr; struct attrlist attr;
struct vol_caps caps; struct vol_caps caps;
struct get_fsid get_fsid;
struct fs_cache *entry; struct fs_cache *entry;
/* First get the FS ID of the volume */
attr.bitmapcount = ATTR_BIT_MAP_COUNT;
attr.reserved = 0;
attr.commonattr = ATTR_CMN_DEVID|ATTR_CMN_FSID;
attr.volattr = attr.dirattr = attr.fileattr = attr.forkattr = 0;
get_fsid.size = 0;
if (getattrlist( dir, &attr, &get_fsid, sizeof(get_fsid), 0 ) != 0 ||
get_fsid.size != sizeof(get_fsid))
return -1;
/* Try to look it up in the cache */ /* Try to look it up in the cache */
entry = look_up_fs_cache( get_fsid.dev ); entry = look_up_fs_cache( dev );
if (entry && !memcmp( &entry->fsid, &get_fsid.fsid, sizeof(fsid_t) )) if (entry && !memcmp( &entry->fsid, &fsid, sizeof(fsid_t) ))
/* Cache lookup succeeded */ /* Cache lookup succeeded */
return entry->case_sensitive; return entry->case_sensitive;
/* Cache is stale at this point, we have to update it */ /* Cache is stale at this point, we have to update it */
mntpoint = get_device_mount_point( get_fsid.dev ); mntpoint = get_device_mount_point( dev );
/* Now look up the case-sensitivity */ /* Now look up the case-sensitivity */
attr.commonattr = 0; attr.bitmapcount = ATTR_BIT_MAP_COUNT;
attr.reserved = attr.commonattr = 0;
attr.volattr = ATTR_VOL_INFO|ATTR_VOL_CAPABILITIES; attr.volattr = ATTR_VOL_INFO|ATTR_VOL_CAPABILITIES;
attr.dirattr = attr.fileattr = attr.forkattr = 0;
if (getattrlist( mntpoint, &attr, &caps, sizeof(caps), 0 ) < 0) if (getattrlist( mntpoint, &attr, &caps, sizeof(caps), 0 ) < 0)
{ {
RtlFreeHeap( GetProcessHeap(), 0, mntpoint ); RtlFreeHeap( GetProcessHeap(), 0, mntpoint );
add_fs_cache( get_fsid.dev, get_fsid.fsid, TRUE ); add_fs_cache( dev, fsid, TRUE );
return TRUE; return TRUE;
} }
RtlFreeHeap( GetProcessHeap(), 0, mntpoint ); RtlFreeHeap( GetProcessHeap(), 0, mntpoint );
@ -1036,11 +1028,34 @@ static int get_dir_case_sensitivity_attr( const char *dir )
else else
ret = TRUE; ret = TRUE;
/* Update the cache */ /* Update the cache */
add_fs_cache( get_fsid.dev, get_fsid.fsid, ret ); add_fs_cache( dev, fsid, ret );
return ret; return ret;
} }
return FALSE; return FALSE;
} }
/***********************************************************************
* get_dir_case_sensitivity_attr
*
* Checks if the volume containing the specified directory is case
* sensitive or not. Uses getattrlist(2).
*/
static int get_dir_case_sensitivity_attr( const char *dir )
{
struct attrlist attr;
struct get_fsid get_fsid;
/* First get the FS ID of the volume */
attr.bitmapcount = ATTR_BIT_MAP_COUNT;
attr.reserved = 0;
attr.commonattr = ATTR_CMN_DEVID|ATTR_CMN_FSID;
attr.volattr = attr.dirattr = attr.fileattr = attr.forkattr = 0;
get_fsid.size = 0;
if (getattrlist( dir, &attr, &get_fsid, sizeof(get_fsid), 0 ) != 0 ||
get_fsid.size != sizeof(get_fsid))
return -1;
return get_dir_case_sensitivity_attr_by_id( get_fsid.dev, get_fsid.fsid );
}
#endif #endif
/*********************************************************************** /***********************************************************************
@ -2148,6 +2163,8 @@ static int read_directory_getattrlist( int fd, IO_STATUS_BLOCK *io, void *buffer
{ {
u_int32_t length; u_int32_t length;
struct attrreference name_reference; struct attrreference name_reference;
dev_t devid;
fsid_t fsid;
fsobj_type_t type; fsobj_type_t type;
char name[NAME_MAX * 3 + 1]; char name[NAME_MAX * 3 + 1];
} attrlist_buffer; } attrlist_buffer;
@ -2179,7 +2196,7 @@ static int read_directory_getattrlist( int fd, IO_STATUS_BLOCK *io, void *buffer
memset( &attrlist, 0, sizeof(attrlist) ); memset( &attrlist, 0, sizeof(attrlist) );
attrlist.bitmapcount = ATTR_BIT_MAP_COUNT; attrlist.bitmapcount = ATTR_BIT_MAP_COUNT;
attrlist.commonattr = ATTR_CMN_NAME | ATTR_CMN_OBJTYPE; attrlist.commonattr = ATTR_CMN_NAME | ATTR_CMN_DEVID | ATTR_CMN_FSID | ATTR_CMN_OBJTYPE;
ret = getattrlist( unix_name, &attrlist, &attrlist_buffer, sizeof(attrlist_buffer), FSOPT_NOFOLLOW ); ret = getattrlist( unix_name, &attrlist, &attrlist_buffer, sizeof(attrlist_buffer), FSOPT_NOFOLLOW );
/* If unix_name named a symlink, the above may have succeeded even if the symlink is broken. /* If unix_name named a symlink, the above may have succeeded even if the symlink is broken.
Check that with another call without FSOPT_NOFOLLOW. We don't ask for any attributes. */ Check that with another call without FSOPT_NOFOLLOW. We don't ask for any attributes. */
@ -2199,7 +2216,8 @@ static int read_directory_getattrlist( int fd, IO_STATUS_BLOCK *io, void *buffer
} }
else io->u.Status = STATUS_NO_MORE_FILES; else io->u.Status = STATUS_NO_MORE_FILES;
} }
else if ((errno == ENOENT || errno == ENOTDIR) && !get_dir_case_sensitivity(".")) else if ((errno == ENOENT || errno == ENOTDIR) &&
!get_dir_case_sensitivity_attr_by_id( attrlist_buffer.devid, attrlist_buffer.fsid ))
{ {
io->u.Status = STATUS_NO_MORE_FILES; io->u.Status = STATUS_NO_MORE_FILES;
ret = 0; ret = 0;