mirror of
https://github.com/zrepl/zrepl.git
synced 2024-11-22 16:34:32 +01:00
zfs: use createtxg and guid properties for FilesystemVersion
This commit is contained in:
parent
22454738af
commit
aa696dd0ce
49
zfs/diff.go
49
zfs/diff.go
@ -3,6 +3,8 @@ package zfs
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -15,8 +17,24 @@ const (
|
|||||||
|
|
||||||
type FilesystemVersion struct {
|
type FilesystemVersion struct {
|
||||||
Type VersionType
|
Type VersionType
|
||||||
|
|
||||||
|
// Display name. Should not be used for identification, only for user output
|
||||||
Name string
|
Name string
|
||||||
//ZFS_PROP_CREATETX and ZFS_PROP_GUID would be nice here => ZFS_PROP_CREATETX, libzfs_dataset.c:zfs_prop_get
|
|
||||||
|
// GUID as exported by ZFS. Uniquely identifies a snapshot across pools
|
||||||
|
Guid uint64
|
||||||
|
|
||||||
|
// The TXG in which the snapshot was created. For bookmarks,
|
||||||
|
// this is the GUID of the snapshot it was initially tied to.
|
||||||
|
CreateTXG uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
type fsbyCreateTXG []FilesystemVersion
|
||||||
|
|
||||||
|
func (l fsbyCreateTXG) Len() int { return len(l) }
|
||||||
|
func (l fsbyCreateTXG) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
|
||||||
|
func (l fsbyCreateTXG) Less(i, j int) bool {
|
||||||
|
return l[i].CreateTXG < l[j].CreateTXG
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The sender (left) wants to know if the receiver (right) has more recent versions
|
/* The sender (left) wants to know if the receiver (right) has more recent versions
|
||||||
@ -69,10 +87,10 @@ type FilesystemDiff struct {
|
|||||||
func ZFSListFilesystemVersions(fs DatasetPath) (res []FilesystemVersion, err error) {
|
func ZFSListFilesystemVersions(fs DatasetPath) (res []FilesystemVersion, err error) {
|
||||||
var fieldLines [][]string
|
var fieldLines [][]string
|
||||||
fieldLines, err = ZFSList(
|
fieldLines, err = ZFSList(
|
||||||
[]string{"name"},
|
[]string{"name", "guid", "createtxg"},
|
||||||
"-r", "-d", "1",
|
"-r", "-d", "1",
|
||||||
"-t", "bookmark,snapshot",
|
"-t", "bookmark,snapshot",
|
||||||
"-s", "creation", fs.ToString())
|
"-s", "createtxg", fs.ToString())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -100,6 +118,16 @@ func ZFSListFilesystemVersions(fs DatasetPath) (res []FilesystemVersion, err err
|
|||||||
v.Type = Bookmark
|
v.Type = Bookmark
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if v.Guid, err = strconv.ParseUint(line[1], 10, 64); err != nil {
|
||||||
|
err = errors.New(fmt.Sprintf("cannot parse GUID: %s", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.CreateTXG, err = strconv.ParseUint(line[2], 10, 64); err != nil {
|
||||||
|
err = errors.New(fmt.Sprintf("cannot parse CreateTXG: %s", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
res[i] = v
|
res[i] = v
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -110,15 +138,26 @@ func ZFSListFilesystemVersions(fs DatasetPath) (res []FilesystemVersion, err err
|
|||||||
// names are unique (bas ZFS_PROP_GUID replacement)
|
// names are unique (bas ZFS_PROP_GUID replacement)
|
||||||
func MakeFilesystemDiff(left, right []FilesystemVersion) (diff FilesystemDiff) {
|
func MakeFilesystemDiff(left, right []FilesystemVersion) (diff FilesystemDiff) {
|
||||||
|
|
||||||
|
// Assert both left and right are sorted by createtxg
|
||||||
|
var leftSorted, rightSorted fsbyCreateTXG
|
||||||
|
leftSorted = left
|
||||||
|
rightSorted = right
|
||||||
|
if !sort.IsSorted(leftSorted) {
|
||||||
|
panic("cannot make filesystem diff: unsorted left")
|
||||||
|
}
|
||||||
|
if !sort.IsSorted(rightSorted) {
|
||||||
|
panic("cannot make filesystem diff: unsorted right")
|
||||||
|
}
|
||||||
|
|
||||||
// Find most recent common ancestor by name, preferring snapshots over bookmars
|
// Find most recent common ancestor by name, preferring snapshots over bookmars
|
||||||
mrcaLeft := len(left) - 1
|
mrcaLeft := len(left) - 1
|
||||||
var mrcaRight int
|
var mrcaRight int
|
||||||
outer:
|
outer:
|
||||||
for ; mrcaLeft >= 0; mrcaLeft-- {
|
for ; mrcaLeft >= 0; mrcaLeft-- {
|
||||||
for i := len(right) - 1; i >= 0; i-- {
|
for i := len(right) - 1; i >= 0; i-- {
|
||||||
if left[mrcaLeft].Name == right[i].Name {
|
if left[mrcaLeft].Guid == right[i].Guid {
|
||||||
mrcaRight = i
|
mrcaRight = i
|
||||||
if i-1 >= 0 && right[i-1].Name == right[i].Name && right[i-1].Type == Snapshot {
|
if i-1 >= 0 && right[i-1].Guid == right[i].Guid && right[i-1].Type == Snapshot {
|
||||||
// prefer snapshots over bookmarks
|
// prefer snapshots over bookmarks
|
||||||
mrcaRight = i - 1
|
mrcaRight = i - 1
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ func ZFSList(properties []string, zfsArgs ...string) (res [][]string, err error)
|
|||||||
|
|
||||||
args := make([]string, 0, 4+len(zfsArgs))
|
args := make([]string, 0, 4+len(zfsArgs))
|
||||||
args = append(args,
|
args = append(args,
|
||||||
"list", "-H",
|
"list", "-H", "-p",
|
||||||
"-o", strings.Join(properties, ","))
|
"-o", strings.Join(properties, ","))
|
||||||
args = append(args, zfsArgs...)
|
args = append(args, zfsArgs...)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user