|FSCTL_DUPLICATE_EXTENTS_TO_FILE| is likely to fail for 32bit processes on 64bit kernels
[The issue was originally reported for the Windows NFSv4.2 driver, see https://github.com/kofemann/ms-nfs41-client ]
|FSCTL_DUPLICATE_EXTENTS_TO_FILE| is likely to fail for 32bit processes on 64bit kernels, because the layout of DUPLICATE_EXTENTS_DATA| differs between 32bit and 64bit, so a 64bit kernel must test for 32bit processes and use |DUPLICATE_EXTENTS_DATA32| instead to use the correct struct layout.
I assume Windows btrfs has the same issue, because it neither contains |IoIs32bitProcess()| nor |DUPLICATE_EXTENTS_DATA32| in the codepath for |FSCTL_DUPLICATE_EXTENTS_TO_FILE|
Prototype patch for ms-nfs41-client is https://nrubsig.kpaste.net/7b2b16b Standalone (dumb) test program: https://github.com/kofemann/ms-nfs41-client/tree/master/tests/winclonefile/
Thanks for letting me know about this, I'll have a look. The VFS doesn't do the translation for us? That's surprising.
I'll have to double-check, but it's possible that this isn't an issue. The 64-bit version has a 64-bit HANDLE, the 32-bit version a 32-bit HANDLE followed by a 32-bit padding gap:
#include <windows.h>
typedef struct _DUPLICATE_EXTENTS_DATA {
HANDLE FileHandle;
LARGE_INTEGER SourceFileOffset;
LARGE_INTEGER TargetFileOffset;
LARGE_INTEGER ByteCount;
} DUPLICATE_EXTENTS_DATA, *PDUPLICATE_EXTENTS_DATA;
typedef struct _DUPLICATE_EXTENTS_DATA32 {
UINT32 FileHandle;
LARGE_INTEGER SourceFileOffset;
LARGE_INTEGER TargetFileOffset;
LARGE_INTEGER ByteCount;
} DUPLICATE_EXTENTS_DATA32, *PDUPLICATE_EXTENTS_DATA32;
static_assert(sizeof(DUPLICATE_EXTENTS_DATA32) == 32);
static_assert(sizeof(DUPLICATE_EXTENTS_DATA) == 32);
static_assert(offsetof(DUPLICATE_EXTENTS_DATA32, SourceFileOffset) == 8);
static_assert(offsetof(DUPLICATE_EXTENTS_DATA, SourceFileOffset) == 8);
Thanks for letting me know about this, I'll have a look. The VFS doesn't do the translation for us? That's surprising.
No, the VFS layer is not going to help. Problem is also that both 32bit and 64bit end-up with the same struct size, so you have to use |IoIs32bitProcess()| like I did in the ms-nfs41-client driver. And "yes", people use 32bit processes for that FSCTL, and that includes CERN+institute Pasteur... ;/