2018-08-30 11:51:47 +02:00
|
|
|
package zfs
|
|
|
|
|
2018-09-06 03:24:15 +02:00
|
|
|
import (
|
|
|
|
"fmt"
|
2019-03-22 19:41:12 +01:00
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
2018-09-06 03:24:15 +02:00
|
|
|
)
|
2018-08-30 11:51:47 +02:00
|
|
|
|
2018-09-06 03:24:15 +02:00
|
|
|
const ReplicationCursorBookmarkName = "zrepl_replication_cursor"
|
|
|
|
|
|
|
|
// may return nil for both values, indicating there is no cursor
|
|
|
|
func ZFSGetReplicationCursor(fs *DatasetPath) (*FilesystemVersion, error) {
|
|
|
|
versions, err := ZFSListFilesystemVersions(fs, nil)
|
2018-08-30 11:51:47 +02:00
|
|
|
if err != nil {
|
2018-09-06 03:24:15 +02:00
|
|
|
return nil, err
|
2018-08-30 11:51:47 +02:00
|
|
|
}
|
2018-09-06 03:24:15 +02:00
|
|
|
for _, v := range versions {
|
|
|
|
if v.Type == Bookmark && v.Name == ReplicationCursorBookmarkName {
|
|
|
|
return &v, nil
|
|
|
|
}
|
2018-08-30 11:51:47 +02:00
|
|
|
}
|
2018-09-06 03:24:15 +02:00
|
|
|
return nil, nil
|
2018-08-30 11:51:47 +02:00
|
|
|
}
|
|
|
|
|
2018-09-06 03:24:15 +02:00
|
|
|
func ZFSSetReplicationCursor(fs *DatasetPath, snapname string) (guid uint64, err error) {
|
|
|
|
snapPath := fmt.Sprintf("%s@%s", fs.ToString(), snapname)
|
2019-03-21 16:59:08 +01:00
|
|
|
debug("replication cursor: snap path %q", snapPath)
|
2019-10-14 17:48:47 +02:00
|
|
|
snapProps, err := ZFSGetCreateTXGAndGuid(snapPath)
|
2018-09-06 03:24:15 +02:00
|
|
|
if err != nil {
|
2019-10-14 17:48:47 +02:00
|
|
|
return 0, errors.Wrapf(err, "get properties of %q", snapPath)
|
2019-03-22 20:45:27 +01:00
|
|
|
}
|
2018-09-06 03:24:15 +02:00
|
|
|
bookmarkPath := fmt.Sprintf("%s#%s", fs.ToString(), ReplicationCursorBookmarkName)
|
2019-10-14 17:48:47 +02:00
|
|
|
propsBookmark, err := ZFSGetCreateTXGAndGuid(bookmarkPath)
|
2018-09-06 03:24:15 +02:00
|
|
|
_, bookmarkNotExistErr := err.(*DatasetDoesNotExist)
|
|
|
|
if err != nil && !bookmarkNotExistErr {
|
2019-03-21 16:59:08 +01:00
|
|
|
return 0, errors.Wrap(err, "zfs: replication cursor: get bookmark txg")
|
2018-09-06 03:24:15 +02:00
|
|
|
}
|
|
|
|
if err == nil {
|
2019-10-14 17:48:47 +02:00
|
|
|
if snapProps.CreateTXG < propsBookmark.CreateTXG {
|
2019-03-21 16:59:08 +01:00
|
|
|
return 0, errors.New("zfs: replication cursor: can only be advanced, not set back")
|
2018-09-06 03:24:15 +02:00
|
|
|
}
|
|
|
|
if err := ZFSDestroy(bookmarkPath); err != nil { // FIXME make safer by using new temporary bookmark, then rename, possible with channel programs
|
2019-03-21 16:59:08 +01:00
|
|
|
return 0, errors.Wrap(err, "zfs: replication cursor: destroy current cursor")
|
2018-09-06 03:24:15 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if err := ZFSBookmark(fs, snapname, ReplicationCursorBookmarkName); err != nil {
|
2019-03-21 16:59:08 +01:00
|
|
|
return 0, errors.Wrapf(err, "zfs: replication cursor: create bookmark")
|
2018-08-30 11:51:47 +02:00
|
|
|
}
|
2019-10-14 17:48:47 +02:00
|
|
|
return snapProps.Guid, nil
|
2018-08-30 11:51:47 +02:00
|
|
|
}
|