From cdc1bf5c04a55fc2396b1733e508efddcdfe77c5 Mon Sep 17 00:00:00 2001 From: Denys Smirnov Date: Mon, 13 Nov 2017 14:31:53 +0200 Subject: [PATCH] refactor send definitions --- btrfs_tree.go | 49 ++++++++++ receive.go | 10 +-- send_h.go | 243 +++++++++++++++++++++++++++++++++++--------------- subvolume.go | 2 +- 4 files changed, 226 insertions(+), 78 deletions(-) diff --git a/btrfs_tree.go b/btrfs_tree.go index 1f2f7ae..514e8cd 100644 --- a/btrfs_tree.go +++ b/btrfs_tree.go @@ -1,6 +1,7 @@ package btrfs import ( + "fmt" "time" "unsafe" ) @@ -52,6 +53,54 @@ func asRootRef(p []byte) rootRef { 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 type btrfs_disk_key_raw [17]byte diff --git a/receive.go b/receive.go index 9a7fe58..dcc042d 100644 --- a/receive.go +++ b/receive.go @@ -66,7 +66,7 @@ type streamReader struct { buf *bytes.Buffer } type sendCommandArgs struct { - Type tlvType + Type sendCmdAttr Data []byte } type sendCommand struct { @@ -110,12 +110,12 @@ func (sr *streamReader) ReadCommand() (*sendCommand, error) { return nil, err } 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) } b := make([]byte, th.Len) 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 } @@ -125,11 +125,11 @@ func newStreamReader(r io.Reader) (*streamReader, error) { _, err := io.ReadFull(r, buf) if err != nil { 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") } 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 &streamReader{r: r}, nil diff --git a/send_h.go b/send_h.go index 9c93c92..64b5058 100644 --- a/send_h.go +++ b/send_h.go @@ -3,17 +3,20 @@ package btrfs import ( "encoding/binary" "io" + "strconv" +) + +var sendEndianess = binary.LittleEndian + +const ( + sendStreamMagic = "btrfs-stream\x00" + sendStreamMagicSize = len(sendStreamMagic) + sendStreamVersion = 1 ) const ( - _BTRFS_SEND_STREAM_MAGIC = "btrfs-stream" - sendStreamMagicSize = len(_BTRFS_SEND_STREAM_MAGIC) - _BTRFS_SEND_STREAM_VERSION = 1 -) - -const ( - _BTRFS_SEND_BUF_SIZE = 64 * 1024 - _BTRFS_SEND_READ_SIZE = 48 * 1024 + sendBufSize = 64 * 1024 + sendReadSize = 48 * 1024 ) type tlvType uint16 @@ -30,115 +33,211 @@ const ( ) type streamHeader struct { - Magic [len(_BTRFS_SEND_STREAM_MAGIC)]byte + Magic [sendStreamMagicSize]byte Version uint32 } +const cmdHeaderSize = 10 + type cmdHeader struct { Len uint32 // len excluding the header - Cmd uint16 + Cmd sendCmd 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 { - if len(p) < h.Size() { + if len(p) < cmdHeaderSize { return io.ErrUnexpectedEOF } - h.Len = binary.LittleEndian.Uint32(p[0:]) - h.Cmd = binary.LittleEndian.Uint16(p[4:]) - h.Crc = binary.LittleEndian.Uint32(p[6:]) + h.Len = sendEndianess.Uint32(p[0:]) + h.Cmd = sendCmd(sendEndianess.Uint16(p[4:])) + h.Crc = sendEndianess.Uint32(p[6:]) return nil } +const tlvHeaderSize = 4 + type tlvHeader struct { - Type tlvType + Type uint16 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 { - if len(p) < h.Size() { + if len(p) < tlvHeaderSize { return io.ErrUnexpectedEOF } - h.Type = tlvType(binary.LittleEndian.Uint16(p[0:])) - h.Len = binary.LittleEndian.Uint16(p[2:]) + h.Type = sendEndianess.Uint16(p[0:]) + h.Len = sendEndianess.Uint16(p[2:]) return nil } 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{ + "", + + "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", + "", +} + const ( - _BTRFS_SEND_C_UNSPEC = sendCmd(iota) + sendCmdUnspec = sendCmd(iota) - _BTRFS_SEND_C_SUBVOL - _BTRFS_SEND_C_SNAPSHOT + sendCmdSubvol + sendCmdSnapshot - _BTRFS_SEND_C_MKFILE - _BTRFS_SEND_C_MKDIR - _BTRFS_SEND_C_MKNOD - _BTRFS_SEND_C_MKFIFO - _BTRFS_SEND_C_MKSOCK - _BTRFS_SEND_C_SYMLINK + sendCmdMkfile + sendCmdMkdir + sendCmdMknod + sendCmdMkfifo + sendCmdMksock + sendCmdSymlink - _BTRFS_SEND_C_RENAME - _BTRFS_SEND_C_LINK - _BTRFS_SEND_C_UNLINK - _BTRFS_SEND_C_RMDIR + sendCmdRename + sendCmdLink + sendCmdUnlink + sendCmdRmdir - _BTRFS_SEND_C_SET_XATTR - _BTRFS_SEND_C_REMOVE_XATTR + sendCmdSetXattr + sendCmdRemoveXattr - _BTRFS_SEND_C_WRITE - _BTRFS_SEND_C_CLONE + sendCmdWrite + sendCmdClone - _BTRFS_SEND_C_TRUNCATE - _BTRFS_SEND_C_CHMOD - _BTRFS_SEND_C_CHOWN - _BTRFS_SEND_C_UTIMES + sendCmdTruncate + sendCmdChmod + sendCmdChown + sendCmdUtimes - _BTRFS_SEND_C_END - _BTRFS_SEND_C_UPDATE_EXTENT - __BTRFS_SEND_C_MAX + sendCmdEnd + sendCmdUpdateExtent + _sendCmdMax ) -const _BTRFS_SEND_C_MAX = __BTRFS_SEND_C_MAX - 1 +const sendCmdMax = _sendCmdMax - 1 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 ( - _BTRFS_SEND_A_UNSPEC = iota + sendAttrUnspec = sendCmdAttr(iota) - _BTRFS_SEND_A_UUID - _BTRFS_SEND_A_CTRANSID + sendAttrUuid + sendAttrCtransid - _BTRFS_SEND_A_INO - _BTRFS_SEND_A_SIZE - _BTRFS_SEND_A_MODE - _BTRFS_SEND_A_UID - _BTRFS_SEND_A_GID - _BTRFS_SEND_A_RDEV - _BTRFS_SEND_A_CTIME - _BTRFS_SEND_A_MTIME - _BTRFS_SEND_A_ATIME - _BTRFS_SEND_A_OTIME + sendAttrIno + sendAttrSize + sendAttrMode + sendAttrUid + sendAttrGid + sendAttrRdev + sendAttrCtime + sendAttrMtime + sendAttrAtime + sendAttrOtime - _BTRFS_SEND_A_XATTR_NAME - _BTRFS_SEND_A_XATTR_DATA + sendAttrXattrName + sendAttrXattrData - _BTRFS_SEND_A_PATH - _BTRFS_SEND_A_PATH_TO - _BTRFS_SEND_A_PATH_LINK + sendAttrPath + sendAttrPathTo + sendAttrPathLink - _BTRFS_SEND_A_FILE_OFFSET - _BTRFS_SEND_A_DATA + sendAttrFileOffset + sendAttrData - _BTRFS_SEND_A_CLONE_UUID - _BTRFS_SEND_A_CLONE_CTRANSID - _BTRFS_SEND_A_CLONE_PATH - _BTRFS_SEND_A_CLONE_OFFSET - _BTRFS_SEND_A_CLONE_LEN + sendAttrCloneUuid + sendAttrCloneCtransid + sendAttrClonePath + sendAttrCloneOffset + sendAttrCloneLen - __BTRFS_SEND_A_MAX + _sendAttrMax ) -const _BTRFS_SEND_A_MAX = __BTRFS_SEND_A_MAX - 1 +const sendAttrMax = _sendAttrMax - 1 + +var sendAttrNames = []string{ + "", + + "uuid", + "ctransid", + + "ino", + "size", + "mode", + "uid", + "gid", + "rdev", + "ctime", + "mtime", + "atime", + "otime", + + "xattrname", + "xattrdata", + + "path", + "pathto", + "pathlink", + + "fileoffset", + "data", + + "cloneuuid", + "clonectransid", + "clonepath", + "cloneoffset", + "clonelen", + + "", +} diff --git a/subvolume.go b/subvolume.go index 7fd4e82..2e52886 100644 --- a/subvolume.go +++ b/subvolume.go @@ -141,7 +141,7 @@ func SnapshotSubVolume(subvol, dst string, ro bool) error { //} copy(args.name[:], newName) if err := iocSnapCreateV2(fdst, &args); err != nil { - return fmt.Errorf("ioc failed: %v", err) + return fmt.Errorf("snapshot create failed: %v", err) } return nil }