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

[PoC] copy on write #161

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft

[PoC] copy on write #161

wants to merge 2 commits into from

Conversation

otiai10
Copy link
Owner

@otiai10 otiai10 commented Aug 20, 2024

Interface design PoC of #160
If any modification is needed, please send pull-request to this branch first.

This pull request will close #160

Huge thanks to @eth-p

Copy link
Contributor

@eth-p eth-p left a comment

Choose a reason for hiding this comment

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

Thanks for creating an alternative implementation! Clever way to approach it, letting the user set the copy function.

I left a couple comments with my thoughts and concerns :)

import "errors"

func CopyOnWrite(src, dst string) error {
return errors.New("copy-on-write is not supported on this platform")
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it would be better to fall back to read and write copy here. Having it fail with an error is going to cause problems if people write code on one platform but never test it on any others.

In this proposal, there also isn't any way to check if the platform does support copy-on-write.

import "golang.org/x/sys/unix"

func CopyOnWrite(src, dst string) error {
return unix.Clonefile(src, dst, 0)
Copy link
Contributor

Choose a reason for hiding this comment

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

This needs to be able to gracefully handle EEXIST in order to be compatible with the read and write copy.

Read and write copy will just overwrite the file, but clonefile will fail if the destination already exists.

// FileCopyFunc is a function to copy an actual file.
// If nil, it uses the default file copying function with `io.Copy`.
// e.g., You can use `CopyOnWrite` to copy files with copy-on-write.
FileCopyFunc func(src, dest string) error
Copy link
Contributor

Choose a reason for hiding this comment

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

Ooh, that's a clever way of handling it.

A few questions, though:

  • How does this work when the source is a fs.FS. If it's not supposed to, how can that be communicated to the user? Documentation? Error?

  • Similarly, what about also using the Sync option or WrapReader option?

Copy link
Contributor

Choose a reason for hiding this comment

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

It might be better not to give the user full control over the function but instead let them pick between pre-made options.

}
}

chmodfunc, err := opt.PermissionControl(info, dest)
Copy link
Contributor

Choose a reason for hiding this comment

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

Just a question for my own reference: the point where the permissions are changed doesn't matter, as long as it happens?

Example: after file creation, or after the file is finished writing

Copy link
Owner Author

Choose a reason for hiding this comment

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

I doesn't matter

import "golang.org/x/sys/unix"

func CopyOnWrite(src, dst string) error {
return unix.Clonefile(src, dst, 0)
Copy link
Contributor

Choose a reason for hiding this comment

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

This will also fail if:

  • The filesystem doesn't support copy-on-write.
  • The source file is on a different filesystem than the destination.

You can check for both of these ahead of time for every file, but it's more platform-specific logic and overhead. It wouldn't be possible to only do a single check on the original source and destination given to Copy either, since a directory can contain mount points for other filesystems.

I think falling back to read and write copy on error is going to be the most compatible approach.

@otiai10 otiai10 marked this pull request as draft September 25, 2024 08:29
@otiai10 otiai10 changed the title Feature/copy on write [PoC] copy on write Sep 25, 2024
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.

2 participants