Skip to content

[FR]Block cloning / reflink support #597

@Jip-Hop

Description

@Jip-Hop

I'm interested in enabling STORAGE_USERS_POSIX_ENABLE_FS_REVISIONS in OpenCloud. It seems like a very useful feature to keep track of revisions, even when local storage is modified outside of OpenCloud (e.g. when using Syncthing or Samba with collaborative mode of the PosixFS driver). But the documented tradeoff of doubling storage is rather large.

As far as I can see the assimilation implementation doesn't support block cloning (reflinks).

if !fi.IsDir() && t.options.EnableFSRevisions {
go func() {
// Copy the previous current version to a revision
currentNode := node.NewBaseNode(n.SpaceID, n.ID+node.CurrentIDDelimiter, t.lookup)
currentPath := currentNode.InternalPath()
stat, err := os.Stat(currentPath)
if err == nil {
revisionPath := t.lookup.VersionPath(n.SpaceID, n.ID, stat.ModTime().UTC().Format(time.RFC3339Nano))
err = os.Rename(currentPath, revisionPath)
if err != nil {
t.log.Error().Err(err).Str("path", path).Str("revisionPath", revisionPath).Msg("could not create revision")
return
}
}
// Copy the new version to the current version
if err := os.MkdirAll(filepath.Dir(currentPath), 0700); err != nil {
t.log.Error().Err(err).Str("path", path).Str("currentPath", currentPath).Msg("could not create base path for current file")
return
}
w, err := os.OpenFile(currentPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)
if err != nil {
t.log.Error().Err(err).Str("path", path).Str("currentPath", currentPath).Msg("could not open current path for writing")
return
}
defer func() {
_ = w.Close()
}()
r, err := os.OpenFile(path, os.O_RDONLY, 0600)
if err != nil {
t.log.Error().Err(err).Str("path", path).Msg("could not open file for reading")
return
}
defer func() {
_ = r.Close()
}()
_, err = io.Copy(w, r)
if err != nil {
t.log.Error().Err(err).Str("currentPath", currentPath).Str("path", path).Msg("could not copy new version to current version")
return
}
err = t.lookup.CopyMetadata(context.Background(), n, currentNode, func(attributeName string, value []byte) (newValue []byte, copy bool) {
return value, strings.HasPrefix(attributeName, prefixes.ChecksumPrefix) ||
attributeName == prefixes.TypeAttr ||
attributeName == prefixes.BlobIDAttr ||
attributeName == prefixes.BlobsizeAttr
}, false)
if err != nil {
t.log.Error().Err(err).Str("currentPath", currentPath).Str("path", path).Msg("failed to copy xattrs to 'current' file")
return
}
}()
}

Using block cloning on filesystems which support it (btrfs, XFS, ZFS) would allow enabling revisions in collaborative mode without the tradeoff of doubling the storage.

I've opened a discussion as I'm not sure if this is the right repo to request this feature.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions