refactor send definitions

This commit is contained in:
Denys Smirnov 2017-11-13 14:31:53 +02:00
parent 3db12b2294
commit cdc1bf5c04
4 changed files with 226 additions and 78 deletions

View File

@ -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

View File

@ -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
View File

@ -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>",
}

View File

@ -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
} }