github.com/dshulyak/uring@v0.0.0-20210209113719-1b2ec51f1542/fs/fs.go (about) 1 package fs 2 3 import ( 4 "os" 5 "syscall" 6 "unsafe" 7 8 "github.com/dshulyak/uring" 9 "github.com/dshulyak/uring/loop" 10 ) 11 12 const _AT_FDCWD int32 = -0x64 13 14 // FilesystemOption ... 15 type FilesystemOption func(*Filesystem) 16 17 // RegisterFiles enables file registration in uring when file is opened. 18 // n is a hint to for fds slice allocation. When fds slice needs to grow 19 // registration module will have to perform two syscalls (unregister files, register files). 20 func RegisterFiles(n int) FilesystemOption { 21 return func(fsm *Filesystem) { 22 fsm.fixedFiles = newFixedFiles(fsm.lp, n) 23 } 24 } 25 26 // NewFilesystem returns facade for interacting with uring-based filesystem functionality. 27 func NewFilesystem(lp *loop.Loop, opts ...FilesystemOption) *Filesystem { 28 fsm := &Filesystem{lp: lp} 29 for _, opt := range opts { 30 opt(fsm) 31 } 32 return fsm 33 } 34 35 // Filesystem is a facade for all fs-related functionality. 36 type Filesystem struct { 37 lp *loop.Loop 38 39 fixedFiles *fixedFiles 40 } 41 42 // Open a file. 43 func (fsm *Filesystem) Open(name string, flags int, mode os.FileMode) (*File, error) { 44 _p0, err := syscall.BytePtrFromString(name) 45 if err != nil { 46 return nil, err 47 } 48 cqe, err := fsm.lp.Syscall(func(sqe *uring.SQEntry) { 49 uring.Openat(sqe, _AT_FDCWD, _p0, uint32(flags), uint32(mode)) 50 }, uintptr(unsafe.Pointer(_p0))) 51 52 if err != nil { 53 return nil, err 54 } 55 if cqe.Result() < 0 { 56 return nil, syscall.Errno(-cqe.Result()) 57 } 58 59 fd := uintptr(cqe.Result()) 60 f := &File{ 61 fd: fd, 62 ufd: fd, 63 name: name, 64 lp: fsm.lp, 65 fixedFiles: fsm.fixedFiles, 66 } 67 if fsm.fixedFiles != nil { 68 idx, err := fsm.fixedFiles.register(f.Fd()) 69 if err != nil { 70 _ = f.Close() 71 return nil, err 72 } 73 f.ufd = idx 74 f.flags |= uring.IOSQE_FIXED_FILE 75 } 76 return f, nil 77 }