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  }