mirror of
https://github.com/versity/scoutfs-go.git
synced 2026-01-03 10:35:15 +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 IOCADDQUOTARULE = C.SCOUTFS_IOC_ADD_QUOTA_RULE
|
||||||
const IOCGETPROJECTID = C.SCOUTFS_IOC_GET_PROJECT_ID
|
const IOCGETPROJECTID = C.SCOUTFS_IOC_GET_PROJECT_ID
|
||||||
const IOCSETPROJECTID = C.SCOUTFS_IOC_SET_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 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
|
||||||
|
|||||||
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
|
// NewXattrQuery creates a new scoutfs Xattr Query
|
||||||
// Specify query xattr key
|
// 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
|
// An open file within scoutfs is supplied for ioctls
|
||||||
// (usually just the base mount point directory)
|
// (usually just the base mount point directory)
|
||||||
func NewXattrQuery(f *os.File, key string, opts ...XOption) *XattrQuery {
|
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 = e
|
||||||
q.next++
|
if q.next < math.MaxUint64 {
|
||||||
|
q.next++
|
||||||
|
}
|
||||||
|
|
||||||
return inodes, nil
|
return inodes, nil
|
||||||
}
|
}
|
||||||
@@ -1660,3 +1662,121 @@ func SetProjectID(f *os.File, projectid uint64) error {
|
|||||||
_, err := scoutfsctl(f, IOCSETPROJECTID, unsafe.Pointer(&projectid))
|
_, err := scoutfsctl(f, IOCSETPROJECTID, unsafe.Pointer(&projectid))
|
||||||
return err
|
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 IOCADDQUOTARULE = 0x4030e815
|
||||||
const IOCGETPROJECTID = 0x8008e812
|
const IOCGETPROJECTID = 0x8008e812
|
||||||
const IOCSETPROJECTID = 0x4008e813
|
const IOCSETPROJECTID = 0x4008e813
|
||||||
|
const IOCREADXATTRINDEX = 0x8048e817
|
||||||
|
|
||||||
const QUERYINODESMETASEQ = 0x0
|
const QUERYINODESMETASEQ = 0x0
|
||||||
const QUERYINODESDATASEQ = 0x1
|
const QUERYINODESDATASEQ = 0x1
|
||||||
|
|||||||
Reference in New Issue
Block a user