From 3e6a5807e26193348aabdfcfce693b5d6663683b Mon Sep 17 00:00:00 2001 From: Ben McClelland Date: Mon, 12 Apr 2021 18:20:20 -0700 Subject: [PATCH] update moveblocks and add stagemove to allow staging from tmpfiles --- c_defs_linux.go | 2 ++ scoutfs.go | 39 +++++++++++++++++++++++++++++++++++++++ scoutfsdefs.go | 8 ++++++-- 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/c_defs_linux.go b/c_defs_linux.go index ba70349..abd9fd6 100644 --- a/c_defs_linux.go +++ b/c_defs_linux.go @@ -88,6 +88,8 @@ const DATAWAITOPCHANGESIZE = C.SCOUTFS_IOC_DWO_CHANGE_SIZE const SEARCHXATTRSOFLAGEND = C.SCOUTFS_SEARCH_XATTRS_OFLAG_END +const MBSTAGEFLG = C.SCOUTFS_IOC_MB_STAGE + type InodesEntry C.scoutfs_ioctl_walk_inodes_entry_t type queryInodes C.scoutfs_ioctl_walk_inodes_t type inoPath C.scoutfs_ioctl_ino_path_t diff --git a/scoutfs.go b/scoutfs.go index eb21626..e44a4fd 100644 --- a/scoutfs.go +++ b/scoutfs.go @@ -787,3 +787,42 @@ func MoveData(from, to *os.File) error { return nil } + +// StageMove will move all of the extents in "from" file handle +// and stage the offline extents at offset "offset" in "to" file handle. +// The size of from and offset of "to" must be 4KB aligned boundary. +// errors this can return: +// EINVAL: from_off, len, or to_off aren't a multiple of 4KB; the source +// and destination files are the same inode; either the source or +// destination is not a regular file; the destination file has +// an existing overlapping extent. +// EOVERFLOW: either from_off + len or to_off + len exceeded 64bits. +// EBADF: from_fd isn't a valid open file descriptor. +// EXDEV: the source and destination files are in different filesystems. +// EISDIR: either the source or destination is a directory. +// ENODATA: either the source or destination file have offline extents. +func StageMove(from, to *os.File, offset, version uint64) error { + ffi, err := from.Stat() + if err != nil { + return fmt.Errorf("stat from: %v", err) + } + + mb := moveBlocks{ + From_fd: uint64(from.Fd()), + From_off: 0, + Len: uint64(ffi.Size()), + To_off: offset, + Data_version: version, + Flags: MBSTAGEFLG, + } + + _, err = scoutfsctl(to, IOCMOVEBLOCKS, unsafe.Pointer(&mb)) + if err != nil { + return err + } + + from.Truncate(0) + from.Seek(0, io.SeekStart) + + return nil +} diff --git a/scoutfsdefs.go b/scoutfsdefs.go index bce4ece..ab19f8c 100644 --- a/scoutfsdefs.go +++ b/scoutfsdefs.go @@ -1,5 +1,5 @@ // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs c_defs_linux.go +// cgo -godefs /workspace/go/src/github.com/versity/scoutfs-go/c_defs_linux.go package scoutfs @@ -15,7 +15,7 @@ const IOCSEARCHXATTRS = 0x80387309 const IOCSTATFSMORE = 0x8030730a const IOCDATAWAITERR = 0x8030730b const IOCALLOCDETAIL = 0x8010730c -const IOCMOVEBLOCKS = 0x8020730d +const IOCMOVEBLOCKS = 0x8030730d const QUERYINODESMETASEQ = 0x0 const QUERYINODESDATASEQ = 0x1 @@ -26,6 +26,8 @@ const DATAWAITOPCHANGESIZE = 0x4 const SEARCHXATTRSOFLAGEND = 0x1 +const MBSTAGEFLG = 0x1 + type InodesEntry struct { Major uint64 Ino uint64 @@ -138,6 +140,8 @@ type moveBlocks struct { From_off uint64 Len uint64 To_off uint64 + Data_version uint64 + Flags uint64 } const sizeofstatfsMore = 0x30