Merge pull request #12 from versity/ben/punch-hole

add PunchHole() to convert offline range to sparse
This commit is contained in:
Ben McClelland
2026-04-13 17:08:39 -07:00
committed by GitHub
3 changed files with 38 additions and 5 deletions
+3
View File
@@ -72,6 +72,7 @@ package scoutfs
// typedef struct scoutfs_ioctl_xattr_index_entry scoutfs_ioctl_xattr_index_entry_t;
// typedef struct scoutfs_ioctl_read_xattr_index scoutfs_ioctl_read_xattr_index_t;
// typedef struct scoutfs_ioctl_inode_attr_x scoutfs_ioctl_inode_attr_x_t;
// typedef struct scoutfs_ioctl_punch_offline scoutfs_ioctl_punch_offline_t;
import "C"
const IOCQUERYINODES = C.SCOUTFS_IOC_WALK_INODES
@@ -122,6 +123,7 @@ const IOCIAXPROJECTID = C.SCOUTFS_IOC_IAX_PROJECT_ID
const IOCIAXBITS = C.SCOUTFS_IOC_IAX__BITS
const IOCGETATTRX = C.SCOUTFS_IOC_GET_ATTR_X
const IOCSETATTRX = C.SCOUTFS_IOC_SET_ATTR_X
const IOCPUNCHOFFLINE = C.SCOUTFS_IOC_PUNCH_OFFLINE
type InodesEntry C.scoutfs_ioctl_walk_inodes_entry_t
type queryInodes C.scoutfs_ioctl_walk_inodes_t
@@ -148,6 +150,7 @@ type getQuotaRules C.scoutfs_ioctl_get_quota_rules_t
type indexEntry C.scoutfs_ioctl_xattr_index_entry_t
type readXattrIndex C.scoutfs_ioctl_read_xattr_index_t
type inodeAttrX C.scoutfs_ioctl_inode_attr_x_t
type punchOffline C.scoutfs_ioctl_punch_offline_t
const sizeofstatfsMore = C.sizeof_scoutfs_ioctl_statfs_more_t
const sizeofxattrTotal = C.sizeof_scoutfs_ioctl_xattr_total_t
+28 -5
View File
@@ -905,11 +905,7 @@ func StageMoveAt(from, to *os.File, len, fromOffset, toOffset, version uint64) e
}
_, err := scoutfsctl(to, IOCMOVEBLOCKS, unsafe.Pointer(&mb))
if err != nil {
return err
}
return nil
return err
}
// XattrTotal has the total values matching id triple
@@ -1807,3 +1803,30 @@ func (i indexEntry) increment() indexEntry {
}
return i
}
// PunchHole is a limited and specific version of hole punching. It's an
// archive layer operation that only converts unmapped offline extents
// into sparse extents. It is intended to be used when restoring sparse
// files after the initial creation set the entire file size offline.
//
// The offset and len fields are in units of bytes and must be aligned
// to the small (4KiB) block size. All regions of offline extents
// covered by the region will be converted into sparse online extents,
// including regions that straddle the boundaries of the region. Any
// existing sparse extents in the region are ignored.
//
// The data_version must match the inode or EINVAL is returned. The
// data_version is not modified by this operation.
//
// EINVAL is returned if any mapped extents are found in the region. If
// an error is returned then partial progress may have been made.
func PunchHole(f *os.File, length, offset, version uint64) error {
po := punchOffline{
Offset: offset,
Len: length,
Version: version,
}
_, err := scoutfsctl(f, IOCPUNCHOFFLINE, unsafe.Pointer(&po))
return err
}
+7
View File
@@ -51,6 +51,7 @@ const IOCIAXPROJECTID = 0x200
const IOCIAXBITS = 0x100
const IOCGETATTRX = 0x4068e812
const IOCSETATTRX = 0x4068e813
const IOCPUNCHOFFLINE = 0x4020e818
type InodesEntry struct {
Major uint64
@@ -241,6 +242,12 @@ type inodeAttrX struct {
Bits uint64
Project_id uint64
}
type punchOffline struct {
Offset uint64
Len uint64
Version uint64
Flags uint64
}
const sizeofstatfsMore = 0x30
const sizeofxattrTotal = 0x28