add scoutfs move_blocks

This commit is contained in:
Ben McClelland
2021-01-15 11:53:40 -07:00
parent bd2ba82da4
commit c19fddb618
4 changed files with 93 additions and 0 deletions

View File

@@ -62,6 +62,7 @@ package scoutfs
// };
//
// typedef struct scoutfs_ioctl_alloc_detail_entry_mod scoutfs_ioctl_alloc_detail_entry_t;
// typedef struct scoutfs_ioctl_move_blocks scoutfs_ioctl_move_blocks_t;
import "C"
const IOCQUERYINODES = C.SCOUTFS_IOC_WALK_INODES
@@ -76,6 +77,7 @@ const IOCSEARCHXATTRS = C.SCOUTFS_IOC_SEARCH_XATTRS
const IOCSTATFSMORE = C.SCOUTFS_IOC_STATFS_MORE
const IOCDATAWAITERR = C.SCOUTFS_IOC_DATA_WAIT_ERR
const IOCALLOCDETAIL = C.SCOUTFS_IOC_ALLOC_DETAIL
const IOCMOVEBLOCKS = C.SCOUTFS_IOC_MOVE_BLOCKS
const QUERYINODESMETASEQ = C.SCOUTFS_IOC_WALK_INODES_META_SEQ
const QUERYINODESDATASEQ = C.SCOUTFS_IOC_WALK_INODES_DATA_SEQ
@@ -101,5 +103,6 @@ type searchXattrs C.scoutfs_ioctl_search_xattrs_t
type statfsMore C.scoutfs_ioctl_statfs_more_t
type allocDetail C.scoutfs_ioctl_alloc_detail_t
type allocDetailEntry C.scoutfs_ioctl_alloc_detail_entry_t
type moveBlocks C.scoutfs_ioctl_move_blocks_t
const sizeofstatfsMore = C.sizeof_scoutfs_ioctl_statfs_more_t

View File

@@ -0,0 +1,41 @@
// Copyright (c) 2021 Versity Software, Inc.
//
// Use of this source code is governed by a BSD-3-Clause license
// that can be found in the LICENSE file in the root of the source
// tree.
package main
import (
"fmt"
"os"
scoutfs "github.com/versity/scoutfs-go"
)
func main() {
if len(os.Args) != 3 || os.Args[1] == "-h" {
fmt.Fprintln(os.Stderr, "usage:", os.Args[0], "<file_to_move_blocks_from> <file_to_append_blocks_to>")
os.Exit(1)
}
ffrom, err := os.OpenFile(os.Args[1], os.O_RDWR, 0666)
if err != nil {
fmt.Fprintf(os.Stderr, "open %v: %v\n", os.Args[1], err)
os.Exit(1)
}
defer ffrom.Close()
fto, err := os.OpenFile(os.Args[2], os.O_RDWR, 0666)
if err != nil {
fmt.Fprintf(os.Stderr, "open %v: %v\n", os.Args[2], err)
os.Exit(1)
}
defer fto.Close()
err = scoutfs.MoveData(ffrom, fto)
if err != nil {
fmt.Fprintf(os.Stderr, "move blocks: %v\n", err)
os.Exit(1)
}
}

View File

@@ -10,6 +10,7 @@ import (
"bytes"
"encoding/binary"
"fmt"
"io"
"io/ioutil"
"math"
"os"
@@ -716,3 +717,44 @@ func GetDF(f *os.File) (DiskUsage, error) {
FreeDataBlocks: dataFree,
}, nil
}
// MoveData will move all of the extents in "from" file handle
// and append to the end of "to" file handle.
// The end 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 MoveData(from, to *os.File) error {
ffi, err := from.Stat()
if err != nil {
return fmt.Errorf("stat from: %v", err)
}
tfi, err := to.Stat()
if err != nil {
return fmt.Errorf("stat to: %v", err)
}
mb := moveBlocks{
From_fd: uint64(from.Fd()),
From_off: 0,
Len: uint64(ffi.Size()),
To_off: uint64(tfi.Size()),
}
_, err = scoutfsctl(to, IOCMOVEBLOCKS, unsafe.Pointer(&mb))
if err != nil {
return err
}
from.Truncate(0)
from.Seek(0, io.SeekStart)
return nil
}

View File

@@ -15,6 +15,7 @@ const IOCSEARCHXATTRS = 0x80387309
const IOCSTATFSMORE = 0x8030730a
const IOCDATAWAITERR = 0x8030730b
const IOCALLOCDETAIL = 0x8010730c
const IOCMOVEBLOCKS = 0x8020730d
const QUERYINODESMETASEQ = 0x0
const QUERYINODESDATASEQ = 0x1
@@ -132,5 +133,11 @@ type allocDetailEntry struct {
Flags uint8
Pad_cgo_0 [6]byte
}
type moveBlocks struct {
From_fd uint64
From_off uint64
Len uint64
To_off uint64
}
const sizeofstatfsMore = 0x30