add inode to path and open by id

This commit is contained in:
Ben McClelland
2018-12-02 15:48:41 -08:00
parent 5993eee035
commit 58a5d5e0d7
6 changed files with 246 additions and 30 deletions
+6 -1
View File
@@ -27,13 +27,18 @@ type server struct {
}
func queryPopulation(basedir string, update chan<- int) error {
f, err := os.Open(path)
if err != nil {
return err
}
defer f.Close()
h, err := scoutfs.NewQuery(basedir,
scoutfs.ByMSeq(scoutfs.InodesEntry{},
scoutfs.InodesEntry{Major: max64, Minor: max32, Ino: max64}))
if err != nil {
return fmt.Errorf("scoutfs new handle: %v", err)
}
defer h.Close()
count := 0
for {
+37
View File
@@ -0,0 +1,37 @@
// 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.InoToPath(f, u)
fmt.Println(s)
}
+48
View File
@@ -0,0 +1,48 @@
// 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)
}
dirf, err := os.Open(os.Args[1])
if err != nil {
log.Fatalln("error open mount:", err)
}
defer dirf.Close()
u, err := strconv.ParseUint(os.Args[2], 10, 64)
if err != nil {
log.Fatalln("error parsing inode:", err)
}
f, err := scoutfs.OpenByID(dirf, u, os.O_RDONLY)
if err != nil {
log.Fatalln("error open by id:", err)
}
fi, err := f.Stat()
if err != nil {
log.Fatalln("error stat:", err)
}
fmt.Println("Name:", fi.Name())
fmt.Println("Size:", fi.Size())
fmt.Println("Mode:", fi.Mode())
}
+39 -18
View File
@@ -10,7 +10,6 @@ import (
"bytes"
"encoding/binary"
"os"
"syscall"
"unsafe"
)
@@ -38,12 +37,9 @@ type Time struct {
// Specify query type with By*() option
// (only 1 allowed, last one wins)
// and specify batching with WithBatchSize()
func NewQuery(path string, opts ...Option) (*Query, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
// An open file within scoutfs is supplied for ioctls
// (usually just the base mount point directory)
func NewQuery(f *os.File, opts ...Option) *Query {
q := &Query{
//default batch size is 128
batch: 128,
@@ -54,7 +50,7 @@ func NewQuery(path string, opts ...Option) (*Query, error) {
opt(q)
}
return q, nil
return q
}
// Option sets various options for NewWalkHandle
@@ -146,11 +142,6 @@ func (q *Query) Next() ([]InodesEntry, error) {
return inodes, nil
}
// Close queryHandle and cleanup
func (q *Query) Close() {
q.fsfd.Close()
}
// StatMore returns scoutfs specific metadata for path
func StatMore(path string) (Stat, error) {
f, err := os.Open(path)
@@ -169,10 +160,40 @@ func StatMore(path string) (Stat, error) {
return s, nil
}
func scoutfsctl(fd, cmd, ptr uintptr) (int, error) {
count, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, cmd, ptr)
if err != 0 {
return 0, err
// InoToPath converts an inode number to a path in the filesystem
// An open file within scoutfs is supplied for ioctls
// (usually just the base mount point directory)
func InoToPath(dirfd *os.File, ino uint64) (string, error) {
var res InoPathResult
ip := InoPath{
Ino: ino,
ResultPtr: uint64(uintptr(unsafe.Pointer(&res))),
ResultSize: uint16(unsafe.Sizeof(res)),
}
return int(count), nil
_, err := scoutfsctl(dirfd.Fd(), IOCINOPATH, uintptr(unsafe.Pointer(&ip)))
if err != nil {
return "", err
}
return string(res.Path[:res.PathSize]), nil
}
// OpenByID will open a file by inode returning a typical *os.File
// An open file within scoutfs is supplied for ioctls
// (usually just the base mount point directory)
// The filename is available through the *os.File and is populated with
// the scoutfs InoToPath
func OpenByID(dirfd *os.File, ino uint64, flags int) (*os.File, error) {
name, err := InoToPath(dirfd, ino)
if err != nil {
return nil, err
}
fd, err := OpenByHandle(dirfd, ino, flags)
if err != nil {
return nil, err
}
return os.NewFile(fd, name), nil
}
+47 -11
View File
@@ -16,7 +16,7 @@ const (
//IOCQUERYINODES scoutfs ioctl
IOCQUERYINODES = 0x40357301
//IOCINOPATH scoutfs ioctl
IOCINOPATH = 0x401c7302
IOCINOPATH = 0x40227302
//IOCDATAVERSION scoutfs ioctl
IOCDATAVERSION = 0x40087304
//IOCRELEASE scoutfs ioctl
@@ -30,6 +30,8 @@ const (
QUERYINODESMETASEQ = '\u0000'
//QUERYINODESDATASEQ find inodes by data sequence
QUERYINODESDATASEQ = '\u0001'
pathmax = 1024
)
/* pahole for scoutfs_ioctl_walk_inodes_entry
@@ -128,11 +130,11 @@ struct scoutfs_ioctl_ino_path {
// InoPath ioctl struct
type InoPath struct {
Ino uint64
DirIno uint64
DirPos uint64
ResultPtr uint64
ResultBytes uint64
Ino uint64
DirIno uint64
DirPos uint64
ResultPtr uint64
ResultSize uint16
}
/* pahole for scoutfs_ioctl_ino_path_result
@@ -149,10 +151,10 @@ struct scoutfs_ioctl_ino_path_result {
// InoPathResult ioctl struct
type InoPathResult struct {
DirIno uint64
DirPos uint64
PathBytes uint16
ResultBytes uint64
DirIno uint64
DirPos uint64
PathSize uint16
Path [pathmax]byte
}
/* pahole for scoutfs_ioctl_release
@@ -207,7 +209,7 @@ struct scoutfs_ioctl_stat_more {
};
*/
//Stat holds scoutfs specific per file metadata
// Stat holds scoutfs specific per file metadata
type Stat struct {
ValidBytes uint64
MetaSeq uint64
@@ -216,3 +218,37 @@ type Stat struct {
OnlineBlocks uint64
OfflineBlocks uint64
}
/* pahole for scoutfs_fid
struct scoutfs_fid {
__le64 ino; // 0 8
__le64 parent_ino; // 8 8
// size: 16, cachelines: 1, members: 2
// last cacheline: 16 bytes
};
*/
// FileID for file by ID operations
type FileID struct {
Ino uint64
ParentIno uint64
}
/* pahole for scoutfs_file_handle
struct scoutfs_file_handle {
unsigned int handle_bytes; // 0 4
int handle_type; // 4 4
struct scoutfs_fid fid; // 8 16
// size: 24, cachelines: 1, members: 3
// last cacheline: 24 bytes
};
*/
// FileHandle is the scoutfs specific file handle for open by handle operations
type FileHandle struct {
FidSize uint32
HandleType int32
FID FileID
}
+69
View File
@@ -0,0 +1,69 @@
package scoutfs
import (
"os"
"syscall"
"unsafe"
)
const (
// SYS_OPENBYHANDLEAT linux system call
SYS_OPENBYHANDLEAT = 304
// FILEID_SCOUTFS for scoutfs file handle
FILEID_SCOUTFS = 0x81
)
// OpenByHandle is similar to OpenByID, but returns just the file descriptor
// and does not have the added overhead of getting the filename
// An open file within scoutfs is supplied for ioctls
// (usually just the base mount point directory)
func OpenByHandle(dirfd *os.File, ino uint64, flags int) (uintptr, error) {
h := &FileHandle{
FidSize: uint32(unsafe.Sizeof(FileID{})),
HandleType: FILEID_SCOUTFS,
FID: FileID{Ino: ino},
}
return openbyhandleat(dirfd.Fd(), h, flags)
}
func openbyhandleat(dirfd uintptr, handle *FileHandle, flags int) (uintptr, error) {
fd, _, e1 := syscall.Syscall6(SYS_OPENBYHANDLEAT, dirfd, uintptr(unsafe.Pointer(handle)), uintptr(flags), 0, 0, 0)
var err error
if e1 != 0 {
err = errnoErr(e1)
}
return fd, err
}
func scoutfsctl(fd, cmd, ptr uintptr) (int, error) {
count, _, e1 := syscall.Syscall(syscall.SYS_IOCTL, fd, cmd, ptr)
var err error
if e1 != 0 {
err = errnoErr(e1)
}
return int(count), err
}
// Do the interface allocations only once for common
// Errno values.
var (
errEAGAIN error = syscall.EAGAIN
errEINVAL error = syscall.EINVAL
errENOENT error = syscall.ENOENT
)
// errnoErr returns common boxed Errno values, to prevent
// allocations at runtime.
func errnoErr(e syscall.Errno) error {
switch e {
case 0:
return nil
case syscall.EAGAIN:
return errEAGAIN
case syscall.EINVAL:
return errEINVAL
case syscall.ENOENT:
return errENOENT
}
return e
}