Excerpts from Brendan Shanks's message of August 5, 2021 1:05 am:
On Aug 4, 2021, at 9:40 AM, Alex Xu (Hello71) alex_y_xu@yahoo.ca wrote:
Over the years, Wine prefixes have gotten bigger and bigger, for a number of reasons. Creating a new Wine prefix for each application is still the current recommendation, as despite the best efforts of Wine developers, some applications still require system-wide workarounds. This leads to significant bloat for each application installed. With a MinGW build of Wine without Mono or Gecko, new 32-bit prefixes are over 150 MB, and new 64-bit prefixes are over 300 MB. The vast majority of these files are byte-for-byte identical to Wine's central DLL copies.
This patch set implements reflink support in Wine via the copy_file_range syscall. The reasons for selecting copy_file_range over FICLONE are outlined in patch 2. A previous unpublished version of this patch set used FICLONERANGE, but it was less convenient to use from setupapi and has inferior system support.
Hi Alex,
This is a separate issue from your patch, but it would be nice if we could implement this functionality on macOS as well. Unfortunately macOS doesn’t support copy_file_range(). The lowest-level interface for CoW clones is clonefile(), which can only create new files, not replace parts of existing ones: https://www.unix.com/man-page/mojave/2/fclonefileat/ I’m not sure if there’s any clear way to use that from Wine.
Brendan
It should theoretically be applicable to both the CopyFile and fakedll implementation. However, this API is poorly designed: both the Windows and Linux APIs support passing file handles/descriptors, whereas the macOS API only supports file names. This is a bad design because an API that only supports file handles can easily be wrapped to support file names, but not the other way around. I suspect that the macOS implementation only supports linking whole files, not parts of files, but even that isn't a particularly good explanation, since the API could simply accept two file descriptors with no length or offset. Linux's FICLONE does exactly this, and I believe the only reason for it is that btrfs didn't support partial file clones at the time.
For CopyFile, this can fairly easily be worked around, since we already receive the filenames. For fakedlls, it is a little harder: although we know the destination file is empty (or can be safely emptied), the way I have written it, write_fake_dll only receives file handles, not file names. This is not a huge problem, because we can simply invoke GetFinalPathNameByHandle. It is only supported on Vista and up, but we don't care about that in Wine. There is a bigger problem, noted in the comments: the destination handle is opened without sharing. So, either the share mode needs to be ignored, or the file needs to be closed and re-opened around the clone. There are also concerns in both cases about the semantics of overwriting an existing file vs removing it and creating a new file.
In conclusion, I think it might be better to land this patch without macOS support for now, then potentially add support later. Better than that would be to pressure Apple to support passing both source and destination FDs to clonefile, since that is what many applications are already designed for (based on the Windows and Linux existing APIs). However, since Apple is legendary for ignoring developers, I think the hopes for that are slim.
Regards, Alex.