mirror of
https://github.com/versity/scoutfs-go.git
synced 2026-01-04 11:03:59 +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_read_xattr_totals scoutfs_ioctl_read_xattr_totals_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
|
||||
// // struct definition here
|
||||
@@ -81,6 +83,7 @@ const IOCDATAWAITERR = C.SCOUTFS_IOC_DATA_WAIT_ERR
|
||||
const IOCALLOCDETAIL = C.SCOUTFS_IOC_ALLOC_DETAIL
|
||||
const IOCMOVEBLOCKS = C.SCOUTFS_IOC_MOVE_BLOCKS
|
||||
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 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 DIRENTFLAGLAST = C.SCOUTFS_IOCTL_DIRENT_FLAG_LAST
|
||||
|
||||
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
|
||||
@@ -111,6 +116,8 @@ type allocDetailEntry C.scoutfs_ioctl_alloc_detail_entry_t
|
||||
type moveBlocks C.scoutfs_ioctl_move_blocks_t
|
||||
type readXattrTotals C.scoutfs_ioctl_read_xattr_totals_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 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"
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
@@ -23,13 +24,14 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
max64 = 0xffffffffffffffff
|
||||
max32 = 0xffffffff
|
||||
pathmax = 4096
|
||||
sysscoutfs = "/sys/fs/scoutfs/"
|
||||
statusfile = "quorum/status"
|
||||
listattrBufsize = 256 * 1024
|
||||
scoutfsBS = 4096
|
||||
max64 = 0xffffffffffffffff
|
||||
max32 = 0xffffffff
|
||||
pathmax = 4096
|
||||
sysscoutfs = "/sys/fs/scoutfs/"
|
||||
statusfile = "quorum/status"
|
||||
listattrBufsize = 256 * 1024
|
||||
getparentBufsize = 4096 * 1024
|
||||
scoutfsBS = 4096
|
||||
//leaderfile = "quorum/is_leader"
|
||||
)
|
||||
|
||||
@@ -1019,3 +1021,116 @@ func (t *TotalsGroup) Reset() {
|
||||
t.pos[1] = t.id2
|
||||
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.
|
||||
// cgo -godefs /workspace/go/src/github.com/versity/scoutfs-go/c_defs_linux.go
|
||||
// cgo -godefs c_defs_linux.go
|
||||
|
||||
package scoutfs
|
||||
|
||||
@@ -17,6 +17,7 @@ const IOCDATAWAITERR = 0x4030e80b
|
||||
const IOCALLOCDETAIL = 0x4010e80c
|
||||
const IOCMOVEBLOCKS = 0x4030e80d
|
||||
const IOCREADXATTRTOTALS = 0x4028e80f
|
||||
const IOCGETREFERRINGENTRIES = 0x4028e811
|
||||
|
||||
const QUERYINODESMETASEQ = 0x0
|
||||
const QUERYINODESDATASEQ = 0x1
|
||||
@@ -29,6 +30,8 @@ const SEARCHXATTRSOFLAGEND = 0x1
|
||||
|
||||
const MBSTAGEFLG = 0x1
|
||||
|
||||
const DIRENTFLAGLAST = 0x1
|
||||
|
||||
type InodesEntry struct {
|
||||
Major uint64
|
||||
Ino uint64
|
||||
@@ -157,6 +160,23 @@ type xattrTotal struct {
|
||||
Total 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 sizeofxattrTotal = 0x28
|
||||
|
||||
Reference in New Issue
Block a user