[PATCH v3 1/2] ntdll/directory: Add support for EXT4 case folding per directory
Huw Davies
huw at codeweavers.com
Fri Jun 7 04:47:18 CDT 2019
On Fri, May 24, 2019 at 03:09:34PM +0300, Gabriel Ivăncescu wrote:
> This adds support for checking the case-insensitive attribute on ext4 with
> newer kernels so that Wine can rely on it for performance.
>
> It has some conditional processing for perf reasons. Checking for the
> EXT4_CASEFOLD_FL attribute involves an ioctl, which operates on file
> descriptors, while all the former checks operated directly on the dir pathname
> (e.g. statfs).
>
> Obviously, it's best to avoid looking up the directory multiple times (also
> for correctness, so it refers to the same dir). So in the case that we *do*
> have a file descriptor, then use it everywhere, with e.g. fstatfs.
>
> However, to avoid a perf regression or downgrade on systems that don't
> support the EXT2_IOC_GETFLAGS ioctl (e.g. MacOS, FreeBSD), we continue
> using statfs and the like directly, this shaves off two syscalls (open/close).
>
> But in the case the EXT4_CASEFOLD_FL is not supported on Linux (i.e. on
> current kernels) or the directory doesn't have it, this will unfortunately
> involve a bit more syscalls now, because it has to open() and close() the fd,
> but it shouldn't be too much of a problem. (the fstatfs and fstatat make it
> less impactful somewhat, so they won't have to lookup the directory again,
> hopefully mitigating some of it)
>
> Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47099
> Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
> ---
>
> v3: Clean up the code and don't have unused parameters in any case.
>
> GET_DIR_CASE_SENSITIVITY_USE_FD is used so it can be as generic as possible
> for fast tweaking and future expansion on other platforms, if they get
> something similar.
>
> As it is now, on Linux, we always set the EXT4_CASEFOLD_FL flag
> ourselves. Thus, I can of course remove the .ciopfs old code and keep just
> the fstatat() call by assuming we always use fd on Linux, if you prefer it
> that way, to keep the code smaller. I didn't remove it because I didn't
> want to "hardcode" this assumption, so please let me know if that should
> be done or not.
>
> dlls/ntdll/directory.c | 73 +++++++++++++++++++++++++++++++++++++-----
> 1 file changed, 65 insertions(+), 8 deletions(-)
>
> diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c
> index bbdbbe9..354c00f 100644
> --- a/dlls/ntdll/directory.c
> +++ b/dlls/ntdll/directory.c
> @@ -115,6 +115,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(file);
>
> /* just in case... */
> #undef VFAT_IOCTL_READDIR_BOTH
> +#undef EXT2_IOC_GETFLAGS
> +#undef EXT4_CASEFOLD_FL
>
> #ifdef linux
>
> @@ -130,12 +132,25 @@ typedef struct
> /* Define the VFAT ioctl to get both short and long file names */
> #define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, KERNEL_DIRENT [2] )
>
> +/* Define the ext2 ioctl for handling extra attributes */
> +#define EXT2_IOC_GETFLAGS _IOR('f', 1, long)
> +
> +/* Case-insensitivity attribute */
> +#define EXT4_CASEFOLD_FL 0x40000000
> +
I'm not sure we need to define these ourselves, we can
just pull them from the headers. I realise that you're
copying what was done with VFAT_IOCTL_READDIR_BOTH and
I don't know why that was done that way, but unless
there's a reason to do this, let's not add more.
> +/* Use a file descriptor for the case-sensitivity check if we have to */
> +#if defined(EXT2_IOC_GETFLAGS) && defined(EXT4_CASEFOLD_FL)
> +#define GET_DIR_CASE_SENSITIVITY_USE_FD 1
> +#else
> +#define GET_DIR_CASE_SENSITIVITY_USE_FD 0
> +#endif
This is now just used in one place, so get rid of it use the
preprocessor condition at the relevant place below.
> static BOOLEAN get_dir_case_sensitivity( const char *dir )
> {
> + int case_sensitive, fd = -1;
> +
> #if defined(HAVE_GETATTRLIST) && defined(ATTR_VOL_CAPABILITIES) && \
> defined(VOL_CAPABILITIES_FORMAT) && defined(VOL_CAP_FMT_CASE_SENSITIVE)
> - int case_sensitive = get_dir_case_sensitivity_attr( dir );
> + case_sensitive = get_dir_case_sensitivity_attr( dir );
> if (case_sensitive != -1) return case_sensitive;
> #endif
> - return get_dir_case_sensitivity_stat( dir );
> +
> + if (GET_DIR_CASE_SENSITIVITY_USE_FD)
#if defined(EXT2_IOC_GETFLAGS) && defined(EXT4_CASEFOLD_FL)
No need for the if block.
> + {
> + if ((fd = open(dir, O_RDONLY | O_NONBLOCK | O_LARGEFILE)) == -1)
> + return TRUE;
> + if ((case_sensitive = get_dir_case_sensitivity_ioctl(fd)) != -1)
> + goto end;
> + }
> + case_sensitive = get_dir_case_sensitivity_stat(dir, fd);
> +
> +end:
> + if (fd != -1) close(fd);
> + return case_sensitive;
> }
FWIW I'm not too convinced about the name/fd thing, but it now doesn't
look too ugly, so I guess it's ok.
Huw.
More information about the wine-devel
mailing list