[PATCH v2 0/5] Implement reflink support

Alex Xu (Hello71) alex_y_xu at yahoo.ca
Thu Aug 5 09:58:11 CDT 2021

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 at 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.


More information about the wine-devel mailing list