Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add clonefile on Windows over ReFS support. #3790

Merged
merged 1 commit into from
Aug 27, 2019

Conversation

kazuki-ma
Copy link
Contributor

@kazuki-ma kazuki-ma commented Aug 25, 2019

ReFS (wikipedia) is filesystem on Windows OS and it's support copy-on-write / file cloning since v3.2.
ReFS v3.2 is available since Windows Server 2016, Windows Server 2019 and Windows 10 also supports format & read-write.

I think many asset heavy product CI system and developer start using ReFS if git-lfs support dedup on it.

Reference:

This closes #3791

@kazuki-ma kazuki-ma force-pushed the clonefile_windows branch 14 times, most recently from 12cdd49 to 1b00158 Compare August 26, 2019 13:05
@kazuki-ma kazuki-ma changed the title Add clonefile windows (ReFS) support. Add clonefile on Windows over ReFS support. Aug 26, 2019
@kazuki-ma kazuki-ma marked this pull request as ready for review August 26, 2019 13:28
Copy link
Member

@bk2204 bk2204 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, this looks good. There are a few issues I noted which we may want to fix.

// Instructs the file system to copy a range of file bytes on behalf of an application.
//
// https://docs.microsoft.com/windows/win32/api/winioctl/ni-winioctl-fsctl_duplicate_extents_to_file
const _FSCTL_DUPLICATE_EXTENTS_TO_FILE = 623428
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even if Windows names this with a leading underscore, we probably don't want to.

// Contains parameters for the FSCTL_DUPLICATE_EXTENTS control code that performs the Block Cloning operation.
//
// https://docs.microsoft.com/windows/win32/api/winioctl/ns-winioctl-duplicate_extents_data
type _DUPLICATE_EXTENTS_DATA struct {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue about the leading underscore. Since this is not supposed to be accessible outside of this package, we probably want to call it duplicateExtentsData.

Is there a way for us to get the definition of this struct and constant from a library so that we don't have to implement it ourselves?

"unsafe"

"github.com/rubyist/tracerx"
"golang.org/x/sys/windows"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to add this to go.mod, or is it already brought in by the golang.org/x/sys package?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't add entry to go.mod. It's part of golang.org/x/sys.

}
defer os.Remove(src.Name())

_, err = src.WriteString("TESTING") // Non-empty file is required for correct result.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is a non-empty file required just for this case or for the function itself to work correctly? If the latter, we probably want to check for a non-zero size below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling FSCTL_DUPLICATE_EXTENTS_TO_FILE to empty file is always success even filesystem don't support it.
To check filesystem support FSCTL_DUPLICATE_EXTENTS_TO_FILE or not, we have to use non-empty file.

I'll write those as comment.

tools/util_windows.go Outdated Show resolved Hide resolved
&bytesReturned,
&overlapped)

tracerx.Printf("DeviceIoControl:%+v result:%+v\n", request, err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also looks like perhaps it's debugging information.

package tools

import (
"crypto/sha1"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're going to use a hash for comparing two files, let's use SHA-256. SHA-1 is considered weak and we'd like to use less of it in our codebase, and we already use SHA-256 in a lot of places.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. Thank you.

@kazuki-ma
Copy link
Contributor Author

Updated. Please review again.

Copy link
Member

@bk2204 bk2204 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good. Thanks for the patch!

@bk2204 bk2204 merged commit a5ecadd into git-lfs:master Aug 27, 2019
@kazuki-ma kazuki-ma deleted the clonefile_windows branch August 27, 2019 16:08
@kazuki-ma
Copy link
Contributor Author

Thank you very much for reviewing.

Artoria2e5 added a commit to Artoria2e5/libuv that referenced this pull request Dec 16, 2019
Windows Server has a reflink feature built onto the dedup-capable ReFS.
This is completely irrelevant for client users, but it would still be a
good thing to add given how Microsoft loves Nodejs now.

The FICLONE_FORCE mode is likely to fail since you have to pay for the
server thing to get it to work. Remove the check if the CI is capable.
(We still really need someone to test it.)

This PR is based on the git-lfs implementation.

Ref: git-lfs/git-lfs#3790
chrisd8088 added a commit to chrisd8088/git-lfs that referenced this pull request Jan 15, 2024
In commit e861b79 of git-lfs#5595 the
Windows variant of our tools.CheckCloneFileSupported() function was
updated to address the problem that it could fail to remove the
temporary files it creates to test whether the "file clone" operation
(as used by the "git lfs dedup" command) is supported in a given
directory.  This problem could occur on Windows because we did not
close all of the temporary file's open descriptors, and so our
deferred call to os.Remove() might not succeed.

In a similar vein, the Windows variant of our tools.CloneFileByPath()
function opens both the source and destination file paths provided for
a "clone" operation but does not close the resultant file descriptors,
so we now add deferred calls to ensure we always close both files.
(This minor issue dates from the introduction in commit
e55bc4c of the support for the
"file clone" operation on ReFS in PR git-lfs#3790.)
chrisd8088 added a commit to chrisd8088/git-lfs that referenced this pull request Jan 15, 2024
In commit e861b79 of git-lfs#5595 the
Windows variant of our tools.CheckCloneFileSupported() function was
updated to address the problem that it could fail to remove the
temporary files it creates to test whether the "file clone" operation
(as used by the "git lfs dedup" command) is supported in a given
directory.  This problem could occur on Windows because we did not
close all of the temporary file's open descriptors, and so our
deferred call to os.Remove() might not succeed.

In a similar vein, the Windows variant of our tools.CloneFileByPath()
function opens both the source and destination file paths provided for
a "clone" operation but does not close the resultant file descriptors,
so we now add deferred calls to ensure we always close both files.
(This minor issue dates from the introduction in commit
e55bc4c of the support for the
"file clone" operation on ReFS in PR git-lfs#3790.)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Clonefile (a.k.a Block cloning) support on Windows.
2 participants