mirror of
https://github.com/versity/scoutfs-go.git
synced 2026-01-07 12:15:20 +00:00
Merge pull request #2 from versity/ben/get-referring-entries
add support for get-referring-entries
This commit is contained in:
@@ -53,6 +53,8 @@ package scoutfs
|
|||||||
// typedef struct scoutfs_ioctl_alloc_detail scoutfs_ioctl_alloc_detail_t;
|
// typedef struct scoutfs_ioctl_alloc_detail scoutfs_ioctl_alloc_detail_t;
|
||||||
// typedef struct scoutfs_ioctl_read_xattr_totals scoutfs_ioctl_read_xattr_totals_t;
|
// typedef struct scoutfs_ioctl_read_xattr_totals scoutfs_ioctl_read_xattr_totals_t;
|
||||||
// typedef struct scoutfs_ioctl_xattr_total scoutfs_ioctl_xattr_total_t;
|
// typedef struct scoutfs_ioctl_xattr_total scoutfs_ioctl_xattr_total_t;
|
||||||
|
// typedef struct scoutfs_ioctl_get_referring_entries scoutfs_ioctl_get_referring_entries_t;
|
||||||
|
// typedef struct scoutfs_ioctl_dirent scoutfs_ioctl_dirent_t;
|
||||||
//
|
//
|
||||||
// // Go doesnt handle bitfields in structs, so we need to override the scoutfs
|
// // Go doesnt handle bitfields in structs, so we need to override the scoutfs
|
||||||
// // struct definition here
|
// // struct definition here
|
||||||
@@ -81,6 +83,7 @@ const IOCDATAWAITERR = C.SCOUTFS_IOC_DATA_WAIT_ERR
|
|||||||
const IOCALLOCDETAIL = C.SCOUTFS_IOC_ALLOC_DETAIL
|
const IOCALLOCDETAIL = C.SCOUTFS_IOC_ALLOC_DETAIL
|
||||||
const IOCMOVEBLOCKS = C.SCOUTFS_IOC_MOVE_BLOCKS
|
const IOCMOVEBLOCKS = C.SCOUTFS_IOC_MOVE_BLOCKS
|
||||||
const IOCREADXATTRTOTALS = C.SCOUTFS_IOC_READ_XATTR_TOTALS
|
const IOCREADXATTRTOTALS = C.SCOUTFS_IOC_READ_XATTR_TOTALS
|
||||||
|
const IOCGETREFERRINGENTRIES = C.SCOUTFS_IOC_GET_REFERRING_ENTRIES
|
||||||
|
|
||||||
const QUERYINODESMETASEQ = C.SCOUTFS_IOC_WALK_INODES_META_SEQ
|
const QUERYINODESMETASEQ = C.SCOUTFS_IOC_WALK_INODES_META_SEQ
|
||||||
const QUERYINODESDATASEQ = C.SCOUTFS_IOC_WALK_INODES_DATA_SEQ
|
const QUERYINODESDATASEQ = C.SCOUTFS_IOC_WALK_INODES_DATA_SEQ
|
||||||
@@ -93,6 +96,8 @@ const SEARCHXATTRSOFLAGEND = C.SCOUTFS_SEARCH_XATTRS_OFLAG_END
|
|||||||
|
|
||||||
const MBSTAGEFLG = C.SCOUTFS_IOC_MB_STAGE
|
const MBSTAGEFLG = C.SCOUTFS_IOC_MB_STAGE
|
||||||
|
|
||||||
|
const DIRENTFLAGLAST = C.SCOUTFS_IOCTL_DIRENT_FLAG_LAST
|
||||||
|
|
||||||
type InodesEntry C.scoutfs_ioctl_walk_inodes_entry_t
|
type InodesEntry C.scoutfs_ioctl_walk_inodes_entry_t
|
||||||
type queryInodes C.scoutfs_ioctl_walk_inodes_t
|
type queryInodes C.scoutfs_ioctl_walk_inodes_t
|
||||||
type inoPath C.scoutfs_ioctl_ino_path_t
|
type inoPath C.scoutfs_ioctl_ino_path_t
|
||||||
@@ -111,6 +116,8 @@ type allocDetailEntry C.scoutfs_ioctl_alloc_detail_entry_t
|
|||||||
type moveBlocks C.scoutfs_ioctl_move_blocks_t
|
type moveBlocks C.scoutfs_ioctl_move_blocks_t
|
||||||
type readXattrTotals C.scoutfs_ioctl_read_xattr_totals_t
|
type readXattrTotals C.scoutfs_ioctl_read_xattr_totals_t
|
||||||
type xattrTotal C.scoutfs_ioctl_xattr_total_t
|
type xattrTotal C.scoutfs_ioctl_xattr_total_t
|
||||||
|
type getReferringEntries C.scoutfs_ioctl_get_referring_entries_t
|
||||||
|
type scoutfsDirent C.scoutfs_ioctl_dirent_t
|
||||||
|
|
||||||
const sizeofstatfsMore = C.sizeof_scoutfs_ioctl_statfs_more_t
|
const sizeofstatfsMore = C.sizeof_scoutfs_ioctl_statfs_more_t
|
||||||
const sizeofxattrTotal = C.sizeof_scoutfs_ioctl_xattr_total_t
|
const sizeofxattrTotal = C.sizeof_scoutfs_ioctl_xattr_total_t
|
||||||
|
|||||||
41
examples/getparents/main.go
Normal file
41
examples/getparents/main.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
// Copyright (c) 2018 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"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
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], "<scoutfs mount point> <inode>")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.Open(os.Args[1])
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("error open mount:", err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
u, err := strconv.ParseUint(os.Args[2], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("error parsing inode:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s, err := scoutfs.GetParents(f, u, nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("error get parents:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(s)
|
||||||
|
}
|
||||||
129
scoutfs.go
129
scoutfs.go
@@ -10,6 +10,7 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
@@ -23,13 +24,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
max64 = 0xffffffffffffffff
|
max64 = 0xffffffffffffffff
|
||||||
max32 = 0xffffffff
|
max32 = 0xffffffff
|
||||||
pathmax = 4096
|
pathmax = 4096
|
||||||
sysscoutfs = "/sys/fs/scoutfs/"
|
sysscoutfs = "/sys/fs/scoutfs/"
|
||||||
statusfile = "quorum/status"
|
statusfile = "quorum/status"
|
||||||
listattrBufsize = 256 * 1024
|
listattrBufsize = 256 * 1024
|
||||||
scoutfsBS = 4096
|
getparentBufsize = 4096 * 1024
|
||||||
|
scoutfsBS = 4096
|
||||||
//leaderfile = "quorum/is_leader"
|
//leaderfile = "quorum/is_leader"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1019,3 +1021,116 @@ func (t *TotalsGroup) Reset() {
|
|||||||
t.pos[1] = t.id2
|
t.pos[1] = t.id2
|
||||||
t.pos[2] = 0
|
t.pos[2] = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parent contains inode of parent and what the child inode is named within
|
||||||
|
// this parent
|
||||||
|
type Parent struct {
|
||||||
|
Ino uint64 // Parent inode
|
||||||
|
Pos uint64 // Entry directory position in parent
|
||||||
|
Type uint8 // Entry inode type matching DT_ enum values in readdir(3)
|
||||||
|
Ent string // Entry name as known by parent
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetParents returns all parents for the given inode
|
||||||
|
// An open file within scoutfs is supplied for ioctls
|
||||||
|
// (usually just the base mount point directory)
|
||||||
|
// If passed in buffer is nil, call will allocate its own buffer.
|
||||||
|
func GetParents(dirfd *os.File, ino uint64, b []byte) ([]Parent, error) {
|
||||||
|
if b == nil {
|
||||||
|
b = make([]byte, getparentBufsize)
|
||||||
|
}
|
||||||
|
|
||||||
|
gre := getReferringEntries{}
|
||||||
|
|
||||||
|
gre.Entries_bytes = uint64(len(b))
|
||||||
|
gre.Entries_ptr = uint64(uintptr(unsafe.Pointer(&b[0])))
|
||||||
|
gre.Ino = ino
|
||||||
|
|
||||||
|
var parents []Parent
|
||||||
|
|
||||||
|
for {
|
||||||
|
n, err := scoutfsctl(dirfd, IOCGETREFERRINGENTRIES, unsafe.Pointer(&gre))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if n == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
ents, isLast, err := parseDents(b)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
parents = append(parents, ents...)
|
||||||
|
if isLast {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parents, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseDents(b []byte) ([]Parent, bool, error) {
|
||||||
|
r := bytes.NewReader(b)
|
||||||
|
var parents []Parent
|
||||||
|
var isLast bool
|
||||||
|
for {
|
||||||
|
var err error
|
||||||
|
var parent Parent
|
||||||
|
parent, isLast, err = parseDent(r)
|
||||||
|
if errors.Is(err, io.EOF) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
parents = append(parents, parent)
|
||||||
|
if isLast {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if r.Len() == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return parents, isLast, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type dirent struct {
|
||||||
|
Dir_ino uint64
|
||||||
|
Dir_pos uint64
|
||||||
|
Ino uint64
|
||||||
|
Entry_bytes uint16
|
||||||
|
Flags uint8
|
||||||
|
D_type uint8
|
||||||
|
Name_len uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseDent(r *bytes.Reader) (Parent, bool, error) {
|
||||||
|
var dent dirent
|
||||||
|
err := binary.Read(r, binary.LittleEndian, &dent)
|
||||||
|
if err != nil {
|
||||||
|
return Parent{}, false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
b := new(strings.Builder)
|
||||||
|
_, err = io.CopyN(b, r, int64(dent.Name_len))
|
||||||
|
if err != nil {
|
||||||
|
return Parent{}, false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pad := int(dent.Entry_bytes) - int(unsafe.Sizeof(dent)) + int(dent.Name_len)
|
||||||
|
for i := 0; i < pad; i++ {
|
||||||
|
_, err = r.ReadByte()
|
||||||
|
if err != nil {
|
||||||
|
return Parent{}, false, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Parent{
|
||||||
|
Ino: dent.Dir_ino,
|
||||||
|
Pos: dent.Dir_pos,
|
||||||
|
Type: dent.D_type,
|
||||||
|
Ent: b.String(),
|
||||||
|
}, dent.Flags&DIRENTFLAGLAST == DIRENTFLAGLAST, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||||
// cgo -godefs /workspace/go/src/github.com/versity/scoutfs-go/c_defs_linux.go
|
// cgo -godefs c_defs_linux.go
|
||||||
|
|
||||||
package scoutfs
|
package scoutfs
|
||||||
|
|
||||||
@@ -17,6 +17,7 @@ const IOCDATAWAITERR = 0x4030e80b
|
|||||||
const IOCALLOCDETAIL = 0x4010e80c
|
const IOCALLOCDETAIL = 0x4010e80c
|
||||||
const IOCMOVEBLOCKS = 0x4030e80d
|
const IOCMOVEBLOCKS = 0x4030e80d
|
||||||
const IOCREADXATTRTOTALS = 0x4028e80f
|
const IOCREADXATTRTOTALS = 0x4028e80f
|
||||||
|
const IOCGETREFERRINGENTRIES = 0x4028e811
|
||||||
|
|
||||||
const QUERYINODESMETASEQ = 0x0
|
const QUERYINODESMETASEQ = 0x0
|
||||||
const QUERYINODESDATASEQ = 0x1
|
const QUERYINODESDATASEQ = 0x1
|
||||||
@@ -29,6 +30,8 @@ const SEARCHXATTRSOFLAGEND = 0x1
|
|||||||
|
|
||||||
const MBSTAGEFLG = 0x1
|
const MBSTAGEFLG = 0x1
|
||||||
|
|
||||||
|
const DIRENTFLAGLAST = 0x1
|
||||||
|
|
||||||
type InodesEntry struct {
|
type InodesEntry struct {
|
||||||
Major uint64
|
Major uint64
|
||||||
Ino uint64
|
Ino uint64
|
||||||
@@ -157,6 +160,23 @@ type xattrTotal struct {
|
|||||||
Total uint64
|
Total uint64
|
||||||
Count uint64
|
Count uint64
|
||||||
}
|
}
|
||||||
|
type getReferringEntries struct {
|
||||||
|
Ino uint64
|
||||||
|
Dir_ino uint64
|
||||||
|
Dir_pos uint64
|
||||||
|
Entries_ptr uint64
|
||||||
|
Entries_bytes uint64
|
||||||
|
}
|
||||||
|
type scoutfsDirent struct {
|
||||||
|
Dir_ino uint64
|
||||||
|
Dir_pos uint64
|
||||||
|
Ino uint64
|
||||||
|
Entry_bytes uint16
|
||||||
|
Flags uint8
|
||||||
|
D_type uint8
|
||||||
|
Name_len uint8
|
||||||
|
Name [3]uint8
|
||||||
|
}
|
||||||
|
|
||||||
const sizeofstatfsMore = 0x30
|
const sizeofstatfsMore = 0x30
|
||||||
const sizeofxattrTotal = 0x28
|
const sizeofxattrTotal = 0x28
|
||||||
|
|||||||
Reference in New Issue
Block a user