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