https://github.com/karpeleslab/reflink
Reflink file copy in Go
https://github.com/karpeleslab/reflink
Last synced: 12 months ago
JSON representation
Reflink file copy in Go
- Host: GitHub
- URL: https://github.com/karpeleslab/reflink
- Owner: KarpelesLab
- License: mit
- Created: 2020-07-18T10:54:37.000Z (almost 6 years ago)
- Default Branch: master
- Last Pushed: 2025-03-18T01:25:20.000Z (about 1 year ago)
- Last Synced: 2025-07-01T00:08:51.749Z (12 months ago)
- Language: Go
- Size: 31.3 KB
- Stars: 36
- Watchers: 1
- Forks: 5
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[](https://godoc.org/github.com/KarpelesLab/reflink)
# reflink
A Go library to perform efficient file copies using reflink operations on compatible filesystems (btrfs or xfs).
## What is a reflink?
There are several types of links in file systems:
* symlinks (symbolic links) - pointer to another file path
* hardlinks - multiple directory entries pointing to the same inode/data
* reflinks - copy-on-write links where files initially share the same data blocks
Reflinks are a modern file system feature found in btrfs and xfs that act similar to hard links but with a key difference: modifying one file doesn't affect the other. Only the modified portions will consume additional disk space (copy-on-write). This makes reflinks ideal for efficient file copies, snapshots, and deduplication.
## Benefits of reflinks
* **Space efficiency**: Initial reflink copies use virtually no additional disk space
* **Performance**: Creating a reflink is nearly instantaneous, even for very large files
* **Safety**: Changes to one file don't affect the other file's contents
* **Transparency**: Applications don't need to be aware they're using reflinked files
## Compatibility
A system needs a compatible OS and filesystem to perform reflinks. Currently supported:
* btrfs on Linux
* xfs on Linux (with reflink=1 mount option)
Other operating systems have similar features that may be implemented in future versions:
* Windows has `DUPLICATE_EXTENTS_TO_FILE`
* Solaris has `reflink`
* MacOS has `clonefile`
## Usage
### Basic usage
```golang
// Creates a reflink copy or fails if reflink is not supported
err := reflink.Always("original_file.bin", "snapshot-001.bin")
// Creates a reflink copy if supported, falls back to regular copy if not
err := reflink.Auto("source_img.png", "modified_img.png")
```
### Working with file handles
```golang
src, _ := os.Open("source.dat")
defer src.Close()
dst, _ := os.Create("dest.dat")
defer dst.Close()
// Reflink the entire file
err := reflink.Reflink(dst, src, true) // true enables fallback to regular copy
// Reflink just a portion of the file
// Copy 1MB from offset 2MB in source to offset 0 in destination
err := reflink.Partial(dst, src, 0, 2*1024*1024, 1*1024*1024, true)
```
## Error handling
The library defines these specific errors:
* `ErrReflinkUnsupported` - Returned when reflink is not supported on this OS
* `ErrReflinkFailed` - Returned when reflink is not supported on the specific filesystem or files
Use standard Go error handling to check for these:
```golang
err := reflink.Always(src, dst)
if err != nil {
if errors.Is(err, reflink.ErrReflinkUnsupported) {
// OS doesn't support reflinks
} else if errors.Is(err, reflink.ErrReflinkFailed) {
// These specific files or filesystem don't support reflinks
} else {
// Other error (permissions, file not found, etc.)
}
}
```
## Fallback mechanism
When using `Auto()` or setting `fallback=true` in other functions, the library tries these methods in order:
1. FICLONE ioctl (real reflink)
2. copy_file_range syscall (efficient kernel-space copy)
3. io.Copy (regular userspace copy)
## Requirements
* Source and destination files must be on the same filesystem
* The filesystem must support reflinks (btrfs, xfs with reflink=1)
* Appropriate file permissions are needed
## Notes
* The arguments are in the same order as `os.Link` or `os.Rename` (src, dst) rather than `io.Copy` (dst, src) as we are dealing with filenames
* For optimal performance with large files, always try to use reflinks instead of regular copies
* Reflinks are transparent to applications - a reflinked file behaves exactly like a regular file