mirror of
https://github.com/versity/scoutfs-go.git
synced 2025-12-23 05:05:17 +00:00
Merge pull request #9 from versity/ben/xattr_index
add xattr index query interfaces
This commit is contained in:
@@ -93,6 +93,7 @@ const IOCDELQUOTARULE = C.SCOUTFS_IOC_DEL_QUOTA_RULE
|
||||
const IOCADDQUOTARULE = C.SCOUTFS_IOC_ADD_QUOTA_RULE
|
||||
const IOCGETPROJECTID = C.SCOUTFS_IOC_GET_PROJECT_ID
|
||||
const IOCSETPROJECTID = C.SCOUTFS_IOC_SET_PROJECT_ID
|
||||
const IOCREADXATTRINDEX = C.SCOUTFS_IOC_READ_XATTR_INDEX
|
||||
|
||||
const QUERYINODESMETASEQ = C.SCOUTFS_IOC_WALK_INODES_META_SEQ
|
||||
const QUERYINODESDATASEQ = C.SCOUTFS_IOC_WALK_INODES_DATA_SEQ
|
||||
|
||||
55
examples/xattridx/main.go
Normal file
55
examples/xattridx/main.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/versity/scoutfs-go"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// flags mount path name
|
||||
mountPath := flag.String("mount", "", "mount path name")
|
||||
// flags index type uint64
|
||||
indexType := flag.Uint64("type", 0, "index type")
|
||||
// flags index start uint64
|
||||
indexStart := flag.Uint64("start", 0, "index start")
|
||||
// flags index end uint64
|
||||
indexEnd := flag.Uint64("end", 0, "index end")
|
||||
// flags show filenames
|
||||
resolveNames := flag.Bool("resolve", false, "show filenames")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
f, err := os.Open(*mountPath)
|
||||
if err != nil {
|
||||
log.Fatalf("Error opening mount: %s", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
idx := scoutfs.NewIndexSearch(f, *indexType, *indexStart, *indexEnd)
|
||||
for {
|
||||
ents, err := idx.Next()
|
||||
if err != nil {
|
||||
log.Fatalf("Error reading index: %v", err)
|
||||
}
|
||||
if ents == nil {
|
||||
break
|
||||
}
|
||||
|
||||
for _, e := range ents {
|
||||
if *resolveNames {
|
||||
name, err := scoutfs.InoToPath(f, e.Inode)
|
||||
if err != nil {
|
||||
log.Fatalf("Error resolving name for %v: %V", e.Inode, err)
|
||||
continue
|
||||
}
|
||||
fmt.Println(name)
|
||||
continue
|
||||
}
|
||||
fmt.Println(e.Inode, "=", e.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
124
scoutfs.go
124
scoutfs.go
@@ -495,7 +495,7 @@ type XattrQuery struct {
|
||||
|
||||
// NewXattrQuery creates a new scoutfs Xattr Query
|
||||
// Specify query xattr key
|
||||
// and specify optinally batching with WithXBatchSize()
|
||||
// and specify optionally batching with WithXBatchSize()
|
||||
// An open file within scoutfs is supplied for ioctls
|
||||
// (usually just the base mount point directory)
|
||||
func NewXattrQuery(f *os.File, key string, opts ...XOption) *XattrQuery {
|
||||
@@ -577,7 +577,9 @@ func (q *XattrQuery) Next() ([]uint64, error) {
|
||||
}
|
||||
|
||||
q.next = e
|
||||
q.next++
|
||||
if q.next < math.MaxUint64 {
|
||||
q.next++
|
||||
}
|
||||
|
||||
return inodes, nil
|
||||
}
|
||||
@@ -1660,3 +1662,121 @@ func SetProjectID(f *os.File, projectid uint64) error {
|
||||
_, err := scoutfsctl(f, IOCSETPROJECTID, unsafe.Pointer(&projectid))
|
||||
return err
|
||||
}
|
||||
|
||||
type IndexSearch struct {
|
||||
// file handle for ioctls
|
||||
f *os.File
|
||||
// The index search end
|
||||
end indexEntry
|
||||
// last returned position
|
||||
pos indexEntry
|
||||
// max number of inodes to return per Next() call
|
||||
batch uint64
|
||||
// buffer for return results
|
||||
buf []byte
|
||||
}
|
||||
|
||||
const (
|
||||
indexXattrBatch = 1024
|
||||
)
|
||||
|
||||
func NewIndexSearch(f *os.File, key, start, end uint64, opts ...IOption) *IndexSearch {
|
||||
i := &IndexSearch{
|
||||
f: f,
|
||||
pos: indexEntry{
|
||||
A: key,
|
||||
B: start,
|
||||
},
|
||||
end: indexEntry{
|
||||
A: key,
|
||||
B: end,
|
||||
Ino: math.MaxUint64,
|
||||
},
|
||||
batch: indexXattrBatch,
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(i)
|
||||
}
|
||||
|
||||
i.buf = make([]byte, int(unsafe.Sizeof(indexEntry{}))*indexXattrBatch)
|
||||
|
||||
return i
|
||||
}
|
||||
|
||||
// IOption sets various options for NewIndexSearch
|
||||
type IOption func(*IndexSearch)
|
||||
|
||||
// WithIBatchSize sets the max number of inodes to be returned at a time
|
||||
func WithIBatchSize(size uint64) IOption {
|
||||
return func(q *IndexSearch) {
|
||||
q.batch = size
|
||||
}
|
||||
}
|
||||
|
||||
// WithIStartIno starts query at speficied inode
|
||||
func WithIStartIno(ino uint64) IOption {
|
||||
return func(q *IndexSearch) {
|
||||
q.pos.Ino = ino
|
||||
}
|
||||
}
|
||||
|
||||
// WithIEndIno stop query at speficied inode
|
||||
func WithIEndIno(ino uint64) IOption {
|
||||
return func(q *IndexSearch) {
|
||||
q.end.Ino = ino
|
||||
}
|
||||
}
|
||||
|
||||
// IndexEnt is type returned by index query Next() call
|
||||
type IndexEnt struct {
|
||||
Inode uint64
|
||||
Value uint64
|
||||
}
|
||||
|
||||
func (i *IndexSearch) Next() ([]IndexEnt, error) {
|
||||
query := readXattrIndex{
|
||||
First: i.pos,
|
||||
Last: i.end,
|
||||
Ptr: uint64(uintptr(unsafe.Pointer(&i.buf[0]))),
|
||||
Nr: indexXattrBatch,
|
||||
}
|
||||
|
||||
n, err := scoutfsctl(i.f, IOCREADXATTRINDEX, unsafe.Pointer(&query))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if n == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
rbuf := bytes.NewReader(i.buf)
|
||||
inodes := make([]IndexEnt, n)
|
||||
|
||||
var e indexEntry
|
||||
for i := 0; i < n; i++ {
|
||||
err := binary.Read(rbuf, binary.LittleEndian, &e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
inodes[i].Inode = e.Ino
|
||||
inodes[i].Value = e.B
|
||||
}
|
||||
i.pos = e.increment()
|
||||
|
||||
return inodes, nil
|
||||
}
|
||||
|
||||
// increment returns the next seq entry position
|
||||
func (i indexEntry) increment() indexEntry {
|
||||
i.Ino++
|
||||
if i.Ino == 0 {
|
||||
i.B++
|
||||
if i.B == 0 {
|
||||
i.A++
|
||||
}
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ const IOCDELQUOTARULE = 0x4030e816
|
||||
const IOCADDQUOTARULE = 0x4030e815
|
||||
const IOCGETPROJECTID = 0x8008e812
|
||||
const IOCSETPROJECTID = 0x4008e813
|
||||
const IOCREADXATTRINDEX = 0x8048e817
|
||||
|
||||
const QUERYINODESMETASEQ = 0x0
|
||||
const QUERYINODESDATASEQ = 0x1
|
||||
|
||||
Reference in New Issue
Block a user