forked from RepoMirrors/btrfs
refactor send definitions
This commit is contained in:
parent
3db12b2294
commit
cdc1bf5c04
@ -1,6 +1,7 @@
|
|||||||
package btrfs
|
package btrfs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
@ -52,6 +53,54 @@ func asRootRef(p []byte) rootRef {
|
|||||||
return ref
|
return ref
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var treeKeyNames = map[treeKeyType]string{
|
||||||
|
inodeItemKey: "inodeItem",
|
||||||
|
inodeRefKey: "inodeRef",
|
||||||
|
inodeExtrefKey: "inodeExtref",
|
||||||
|
xattrItemKey: "xattrItemKey",
|
||||||
|
orphanItemKey: "orphanItem",
|
||||||
|
dirLogItemKey: "dirLogItem",
|
||||||
|
dirLogIndexKey: "dirLogIndex",
|
||||||
|
dirItemKey: "dirItem",
|
||||||
|
dirIndexKey: "dirIndex",
|
||||||
|
extentDataKey: "extentData",
|
||||||
|
extentCsumKey: "extentCsum",
|
||||||
|
rootItemKey: "rootItem",
|
||||||
|
rootBackrefKey: "rootBackref",
|
||||||
|
rootRefKey: "rootRef",
|
||||||
|
extentItemKey: "extentItem",
|
||||||
|
metadataItemKey: "metadataItem",
|
||||||
|
treeBlockRefKey: "treeBlockRef",
|
||||||
|
extentDataRefKey: "extentDataRef",
|
||||||
|
extentRefV0Key: "extentRefV0",
|
||||||
|
sharedBlockRefKey: "sharedBlockRef",
|
||||||
|
sharedDataRefKey: "sharedDataRef",
|
||||||
|
blockGroupItemKey: "blockGroupItem",
|
||||||
|
freeSpaceInfoKey: "freeSpaceInfo",
|
||||||
|
freeSpaceExtentKey: "freeSpaceExtent",
|
||||||
|
freeSpaceBitmapKey: "freeSpaceBitmap",
|
||||||
|
devExtentKey: "devExtent",
|
||||||
|
devItemKey: "devItem",
|
||||||
|
chunkItemKey: "chunkItem",
|
||||||
|
qgroupStatusKey: "qgroupStatus",
|
||||||
|
qgroupInfoKey: "qgroupInfo",
|
||||||
|
qgroupLimitKey: "qgroupLimit",
|
||||||
|
qgroupRelationKey: "qgroupRelation",
|
||||||
|
temporaryItemKey: "temporaryItem",
|
||||||
|
persistentItemKey: "persistentItem",
|
||||||
|
devReplaceKey: "devReplace",
|
||||||
|
uuidKeySubvol: "uuidKeySubvol",
|
||||||
|
uuidKeyReceivedSubvol: "uuidKeyReceivedSubvol",
|
||||||
|
stringItemKey: "stringItem",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t treeKeyType) String() string {
|
||||||
|
if name, ok := treeKeyNames[t]; ok {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%#x", int(t))
|
||||||
|
}
|
||||||
|
|
||||||
// btrfs_disk_key_raw is a raw bytes for btrfs_disk_key structure
|
// btrfs_disk_key_raw is a raw bytes for btrfs_disk_key structure
|
||||||
type btrfs_disk_key_raw [17]byte
|
type btrfs_disk_key_raw [17]byte
|
||||||
|
|
||||||
|
10
receive.go
10
receive.go
@ -66,7 +66,7 @@ type streamReader struct {
|
|||||||
buf *bytes.Buffer
|
buf *bytes.Buffer
|
||||||
}
|
}
|
||||||
type sendCommandArgs struct {
|
type sendCommandArgs struct {
|
||||||
Type tlvType
|
Type sendCmdAttr
|
||||||
Data []byte
|
Data []byte
|
||||||
}
|
}
|
||||||
type sendCommand struct {
|
type sendCommand struct {
|
||||||
@ -110,12 +110,12 @@ func (sr *streamReader) ReadCommand() (*sendCommand, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
data = data[th.Size():]
|
data = data[th.Size():]
|
||||||
if th.Type > _BTRFS_SEND_A_MAX { // || th.Len > _BTRFS_SEND_BUF_SIZE {
|
if sendCmdAttr(th.Type) > sendAttrMax { // || th.Len > _BTRFS_SEND_BUF_SIZE {
|
||||||
return nil, fmt.Errorf("invalid tlv in cmd: %+v", th)
|
return nil, fmt.Errorf("invalid tlv in cmd: %+v", th)
|
||||||
}
|
}
|
||||||
b := make([]byte, th.Len)
|
b := make([]byte, th.Len)
|
||||||
copy(b, data)
|
copy(b, data)
|
||||||
cmd.Args = append(cmd.Args, sendCommandArgs{Type: th.Type, Data: b})
|
cmd.Args = append(cmd.Args, sendCommandArgs{Type: sendCmdAttr(th.Type), Data: b})
|
||||||
}
|
}
|
||||||
return &cmd, nil
|
return &cmd, nil
|
||||||
}
|
}
|
||||||
@ -125,11 +125,11 @@ func newStreamReader(r io.Reader) (*streamReader, error) {
|
|||||||
_, err := io.ReadFull(r, buf)
|
_, err := io.ReadFull(r, buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if bytes.Compare(buf[:sendStreamMagicSize], []byte(_BTRFS_SEND_STREAM_MAGIC)) != 0 {
|
} else if bytes.Compare(buf[:sendStreamMagicSize], []byte(sendStreamMagic)) != 0 {
|
||||||
return nil, errors.New("unexpected stream header")
|
return nil, errors.New("unexpected stream header")
|
||||||
}
|
}
|
||||||
version := binary.LittleEndian.Uint32(buf[sendStreamMagicSize:])
|
version := binary.LittleEndian.Uint32(buf[sendStreamMagicSize:])
|
||||||
if version > _BTRFS_SEND_STREAM_VERSION {
|
if version > sendStreamVersion {
|
||||||
return nil, fmt.Errorf("stream version %d not supported", version)
|
return nil, fmt.Errorf("stream version %d not supported", version)
|
||||||
}
|
}
|
||||||
return &streamReader{r: r}, nil
|
return &streamReader{r: r}, nil
|
||||||
|
243
send_h.go
243
send_h.go
@ -3,17 +3,20 @@ package btrfs
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"io"
|
"io"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
var sendEndianess = binary.LittleEndian
|
||||||
|
|
||||||
|
const (
|
||||||
|
sendStreamMagic = "btrfs-stream\x00"
|
||||||
|
sendStreamMagicSize = len(sendStreamMagic)
|
||||||
|
sendStreamVersion = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
_BTRFS_SEND_STREAM_MAGIC = "btrfs-stream"
|
sendBufSize = 64 * 1024
|
||||||
sendStreamMagicSize = len(_BTRFS_SEND_STREAM_MAGIC)
|
sendReadSize = 48 * 1024
|
||||||
_BTRFS_SEND_STREAM_VERSION = 1
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
_BTRFS_SEND_BUF_SIZE = 64 * 1024
|
|
||||||
_BTRFS_SEND_READ_SIZE = 48 * 1024
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type tlvType uint16
|
type tlvType uint16
|
||||||
@ -30,115 +33,211 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type streamHeader struct {
|
type streamHeader struct {
|
||||||
Magic [len(_BTRFS_SEND_STREAM_MAGIC)]byte
|
Magic [sendStreamMagicSize]byte
|
||||||
Version uint32
|
Version uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cmdHeaderSize = 10
|
||||||
|
|
||||||
type cmdHeader struct {
|
type cmdHeader struct {
|
||||||
Len uint32 // len excluding the header
|
Len uint32 // len excluding the header
|
||||||
Cmd uint16
|
Cmd sendCmd
|
||||||
Crc uint32 // crc including the header with zero crc field
|
Crc uint32 // crc including the header with zero crc field
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *cmdHeader) Size() int { return 10 }
|
func (h *cmdHeader) Size() int { return cmdHeaderSize }
|
||||||
func (h *cmdHeader) Unmarshal(p []byte) error {
|
func (h *cmdHeader) Unmarshal(p []byte) error {
|
||||||
if len(p) < h.Size() {
|
if len(p) < cmdHeaderSize {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
h.Len = binary.LittleEndian.Uint32(p[0:])
|
h.Len = sendEndianess.Uint32(p[0:])
|
||||||
h.Cmd = binary.LittleEndian.Uint16(p[4:])
|
h.Cmd = sendCmd(sendEndianess.Uint16(p[4:]))
|
||||||
h.Crc = binary.LittleEndian.Uint32(p[6:])
|
h.Crc = sendEndianess.Uint32(p[6:])
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const tlvHeaderSize = 4
|
||||||
|
|
||||||
type tlvHeader struct {
|
type tlvHeader struct {
|
||||||
Type tlvType
|
Type uint16
|
||||||
Len uint16 // len excluding the header
|
Len uint16 // len excluding the header
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *tlvHeader) Size() int { return 4 }
|
func (h *tlvHeader) Size() int { return tlvHeaderSize }
|
||||||
func (h *tlvHeader) Unmarshal(p []byte) error {
|
func (h *tlvHeader) Unmarshal(p []byte) error {
|
||||||
if len(p) < h.Size() {
|
if len(p) < tlvHeaderSize {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
h.Type = tlvType(binary.LittleEndian.Uint16(p[0:]))
|
h.Type = sendEndianess.Uint16(p[0:])
|
||||||
h.Len = binary.LittleEndian.Uint16(p[2:])
|
h.Len = sendEndianess.Uint16(p[2:])
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type sendCmd uint16
|
type sendCmd uint16
|
||||||
|
|
||||||
|
func (c sendCmd) String() string {
|
||||||
|
var name string
|
||||||
|
if int(c) < len(sendCmdTypeNames) {
|
||||||
|
name = sendCmdTypeNames[int(c)]
|
||||||
|
}
|
||||||
|
if name != "" {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
return strconv.FormatInt(int64(c), 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sendCmdTypeNames = []string{
|
||||||
|
"<zero>",
|
||||||
|
|
||||||
|
"subvol",
|
||||||
|
"snapshot",
|
||||||
|
|
||||||
|
"mkfile",
|
||||||
|
"mkdir",
|
||||||
|
"mknod",
|
||||||
|
"mkfifo",
|
||||||
|
"mksock",
|
||||||
|
"symlink",
|
||||||
|
|
||||||
|
"rename",
|
||||||
|
"link",
|
||||||
|
"unlink",
|
||||||
|
"rmdir",
|
||||||
|
|
||||||
|
"set_xattr",
|
||||||
|
"remove_xattr",
|
||||||
|
|
||||||
|
"write",
|
||||||
|
"clone",
|
||||||
|
|
||||||
|
"truncate",
|
||||||
|
"chmod",
|
||||||
|
"chown",
|
||||||
|
"utimes",
|
||||||
|
|
||||||
|
"end",
|
||||||
|
"update_extent",
|
||||||
|
"<max>",
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
_BTRFS_SEND_C_UNSPEC = sendCmd(iota)
|
sendCmdUnspec = sendCmd(iota)
|
||||||
|
|
||||||
_BTRFS_SEND_C_SUBVOL
|
sendCmdSubvol
|
||||||
_BTRFS_SEND_C_SNAPSHOT
|
sendCmdSnapshot
|
||||||
|
|
||||||
_BTRFS_SEND_C_MKFILE
|
sendCmdMkfile
|
||||||
_BTRFS_SEND_C_MKDIR
|
sendCmdMkdir
|
||||||
_BTRFS_SEND_C_MKNOD
|
sendCmdMknod
|
||||||
_BTRFS_SEND_C_MKFIFO
|
sendCmdMkfifo
|
||||||
_BTRFS_SEND_C_MKSOCK
|
sendCmdMksock
|
||||||
_BTRFS_SEND_C_SYMLINK
|
sendCmdSymlink
|
||||||
|
|
||||||
_BTRFS_SEND_C_RENAME
|
sendCmdRename
|
||||||
_BTRFS_SEND_C_LINK
|
sendCmdLink
|
||||||
_BTRFS_SEND_C_UNLINK
|
sendCmdUnlink
|
||||||
_BTRFS_SEND_C_RMDIR
|
sendCmdRmdir
|
||||||
|
|
||||||
_BTRFS_SEND_C_SET_XATTR
|
sendCmdSetXattr
|
||||||
_BTRFS_SEND_C_REMOVE_XATTR
|
sendCmdRemoveXattr
|
||||||
|
|
||||||
_BTRFS_SEND_C_WRITE
|
sendCmdWrite
|
||||||
_BTRFS_SEND_C_CLONE
|
sendCmdClone
|
||||||
|
|
||||||
_BTRFS_SEND_C_TRUNCATE
|
sendCmdTruncate
|
||||||
_BTRFS_SEND_C_CHMOD
|
sendCmdChmod
|
||||||
_BTRFS_SEND_C_CHOWN
|
sendCmdChown
|
||||||
_BTRFS_SEND_C_UTIMES
|
sendCmdUtimes
|
||||||
|
|
||||||
_BTRFS_SEND_C_END
|
sendCmdEnd
|
||||||
_BTRFS_SEND_C_UPDATE_EXTENT
|
sendCmdUpdateExtent
|
||||||
__BTRFS_SEND_C_MAX
|
_sendCmdMax
|
||||||
)
|
)
|
||||||
|
|
||||||
const _BTRFS_SEND_C_MAX = __BTRFS_SEND_C_MAX - 1
|
const sendCmdMax = _sendCmdMax - 1
|
||||||
|
|
||||||
type sendCmdAttr uint16
|
type sendCmdAttr uint16
|
||||||
|
|
||||||
|
func (c sendCmdAttr) String() string {
|
||||||
|
var name string
|
||||||
|
if int(c) < len(sendAttrNames) {
|
||||||
|
name = sendAttrNames[int(c)]
|
||||||
|
}
|
||||||
|
if name != "" {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
return strconv.FormatInt(int64(c), 16)
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
_BTRFS_SEND_A_UNSPEC = iota
|
sendAttrUnspec = sendCmdAttr(iota)
|
||||||
|
|
||||||
_BTRFS_SEND_A_UUID
|
sendAttrUuid
|
||||||
_BTRFS_SEND_A_CTRANSID
|
sendAttrCtransid
|
||||||
|
|
||||||
_BTRFS_SEND_A_INO
|
sendAttrIno
|
||||||
_BTRFS_SEND_A_SIZE
|
sendAttrSize
|
||||||
_BTRFS_SEND_A_MODE
|
sendAttrMode
|
||||||
_BTRFS_SEND_A_UID
|
sendAttrUid
|
||||||
_BTRFS_SEND_A_GID
|
sendAttrGid
|
||||||
_BTRFS_SEND_A_RDEV
|
sendAttrRdev
|
||||||
_BTRFS_SEND_A_CTIME
|
sendAttrCtime
|
||||||
_BTRFS_SEND_A_MTIME
|
sendAttrMtime
|
||||||
_BTRFS_SEND_A_ATIME
|
sendAttrAtime
|
||||||
_BTRFS_SEND_A_OTIME
|
sendAttrOtime
|
||||||
|
|
||||||
_BTRFS_SEND_A_XATTR_NAME
|
sendAttrXattrName
|
||||||
_BTRFS_SEND_A_XATTR_DATA
|
sendAttrXattrData
|
||||||
|
|
||||||
_BTRFS_SEND_A_PATH
|
sendAttrPath
|
||||||
_BTRFS_SEND_A_PATH_TO
|
sendAttrPathTo
|
||||||
_BTRFS_SEND_A_PATH_LINK
|
sendAttrPathLink
|
||||||
|
|
||||||
_BTRFS_SEND_A_FILE_OFFSET
|
sendAttrFileOffset
|
||||||
_BTRFS_SEND_A_DATA
|
sendAttrData
|
||||||
|
|
||||||
_BTRFS_SEND_A_CLONE_UUID
|
sendAttrCloneUuid
|
||||||
_BTRFS_SEND_A_CLONE_CTRANSID
|
sendAttrCloneCtransid
|
||||||
_BTRFS_SEND_A_CLONE_PATH
|
sendAttrClonePath
|
||||||
_BTRFS_SEND_A_CLONE_OFFSET
|
sendAttrCloneOffset
|
||||||
_BTRFS_SEND_A_CLONE_LEN
|
sendAttrCloneLen
|
||||||
|
|
||||||
__BTRFS_SEND_A_MAX
|
_sendAttrMax
|
||||||
)
|
)
|
||||||
const _BTRFS_SEND_A_MAX = __BTRFS_SEND_A_MAX - 1
|
const sendAttrMax = _sendAttrMax - 1
|
||||||
|
|
||||||
|
var sendAttrNames = []string{
|
||||||
|
"<zero>",
|
||||||
|
|
||||||
|
"uuid",
|
||||||
|
"ctransid",
|
||||||
|
|
||||||
|
"ino",
|
||||||
|
"size",
|
||||||
|
"mode",
|
||||||
|
"uid",
|
||||||
|
"gid",
|
||||||
|
"rdev",
|
||||||
|
"ctime",
|
||||||
|
"mtime",
|
||||||
|
"atime",
|
||||||
|
"otime",
|
||||||
|
|
||||||
|
"xattrname",
|
||||||
|
"xattrdata",
|
||||||
|
|
||||||
|
"path",
|
||||||
|
"pathto",
|
||||||
|
"pathlink",
|
||||||
|
|
||||||
|
"fileoffset",
|
||||||
|
"data",
|
||||||
|
|
||||||
|
"cloneuuid",
|
||||||
|
"clonectransid",
|
||||||
|
"clonepath",
|
||||||
|
"cloneoffset",
|
||||||
|
"clonelen",
|
||||||
|
|
||||||
|
"<max>",
|
||||||
|
}
|
||||||
|
@ -141,7 +141,7 @@ func SnapshotSubVolume(subvol, dst string, ro bool) error {
|
|||||||
//}
|
//}
|
||||||
copy(args.name[:], newName)
|
copy(args.name[:], newName)
|
||||||
if err := iocSnapCreateV2(fdst, &args); err != nil {
|
if err := iocSnapCreateV2(fdst, &args); err != nil {
|
||||||
return fmt.Errorf("ioc failed: %v", err)
|
return fmt.Errorf("snapshot create failed: %v", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user