github.com/dshulyak/uring@v0.0.0-20210209113719-1b2ec51f1542/fs/file.go (about)

     1  package fs
     2  
     3  import (
     4  	"sync"
     5  	"syscall"
     6  	"unsafe"
     7  
     8  	"github.com/dshulyak/uring"
     9  	"github.com/dshulyak/uring/fixed"
    10  	"github.com/dshulyak/uring/loop"
    11  )
    12  
    13  func ioRst(cqe uring.CQEntry, err error) (int, error) {
    14  	if err != nil {
    15  		return 0, err
    16  	}
    17  	if cqe.Result() < 0 {
    18  		return 0, syscall.Errno(-cqe.Result())
    19  	}
    20  	return int(cqe.Result()), nil
    21  }
    22  
    23  // File ...
    24  type File struct {
    25  	mu   sync.Mutex
    26  	fd   uintptr
    27  	name string
    28  	// ufd is used for uring operations.
    29  	// will be equal to fd is fd is not registered, otherwise will be an index in the array
    30  	// with all registered fds
    31  	ufd uintptr
    32  	// additional sqe flags
    33  	flags uint8
    34  
    35  	lp         *loop.Loop
    36  	fixedFiles *fixedFiles
    37  }
    38  
    39  // Name ...
    40  func (f *File) Name() string {
    41  	return f.name
    42  }
    43  
    44  // Fd ...
    45  func (f *File) Fd() uintptr {
    46  	return f.fd
    47  }
    48  
    49  // Close ...
    50  func (f *File) Close() error {
    51  	if f.fixedFiles != nil {
    52  		_ = f.fixedFiles.unregister(f.ufd)
    53  	}
    54  	cqe, err := f.lp.Syscall(func(sqe *uring.SQEntry) {
    55  		uring.Close(sqe, f.fd)
    56  	})
    57  	if err != nil {
    58  		return err
    59  	}
    60  	if cqe.Result() < 0 {
    61  		return syscall.Errno(-cqe.Result())
    62  	}
    63  	return nil
    64  }
    65  
    66  // WriteAt ...
    67  func (f *File) WriteAt(buf []byte, off int64) (int, error) {
    68  	if len(buf) == 0 {
    69  		return 0, nil
    70  	}
    71  	iovec := []syscall.Iovec{{Base: &buf[0], Len: uint64(len(buf))}}
    72  	return ioRst(f.lp.Syscall(func(sqe *uring.SQEntry) {
    73  		uring.Writev(sqe, f.ufd, iovec, uint64(off), 0)
    74  		sqe.SetFlags(f.flags)
    75  	}, uintptr(unsafe.Pointer(&iovec[0]))))
    76  }
    77  
    78  // ReadAt ...
    79  func (f *File) ReadAt(buf []byte, off int64) (int, error) {
    80  	if len(buf) == 0 {
    81  		return 0, nil
    82  	}
    83  	iovec := []syscall.Iovec{{Base: &buf[0], Len: uint64(len(buf))}}
    84  	return ioRst(f.lp.Syscall(func(sqe *uring.SQEntry) {
    85  		uring.Readv(sqe, f.ufd, iovec, uint64(off), 0)
    86  		sqe.SetFlags(f.flags)
    87  	}, uintptr(unsafe.Pointer(&iovec[0]))))
    88  }
    89  
    90  // WriteAtFixed ...
    91  // FIXME(dshulyak) write after canceled write will hang
    92  // see https://github.com/axboe/liburing/issues/179
    93  func (f *File) WriteAtFixed(b *fixed.Buffer, off int64) (int, error) {
    94  	if b.Len() == 0 {
    95  		return 0, nil
    96  	}
    97  	return ioRst(f.lp.Syscall(func(sqe *uring.SQEntry) {
    98  		uring.WriteFixed(sqe, f.ufd, b.Base(), b.Len(), uint64(off), 0, b.Index())
    99  		sqe.SetFlags(f.flags)
   100  	}))
   101  }
   102  
   103  // ReadAtFixed ...
   104  func (f *File) ReadAtFixed(b *fixed.Buffer, off int64) (int, error) {
   105  	if b.Len() == 0 {
   106  		return 0, nil
   107  	}
   108  	return ioRst(f.lp.Syscall(func(sqe *uring.SQEntry) {
   109  		uring.ReadFixed(sqe, f.ufd, b.Base(), b.Len(), uint64(off), 0, b.Index())
   110  		sqe.SetFlags(f.flags)
   111  	}))
   112  
   113  }
   114  
   115  // Sync ...
   116  func (f *File) Sync() error {
   117  	cqe, err := f.lp.Syscall(func(sqe *uring.SQEntry) {
   118  		uring.Fsync(sqe, f.fd)
   119  	})
   120  	if err != nil {
   121  		return err
   122  	}
   123  	if cqe.Result() < 0 {
   124  		return syscall.Errno(-cqe.Result())
   125  	}
   126  	return nil
   127  }
   128  
   129  // Datasync ...
   130  func (f *File) Datasync() error {
   131  	cqe, err := f.lp.Syscall(func(sqe *uring.SQEntry) {
   132  		uring.Fdatasync(sqe, f.fd)
   133  	})
   134  	if err != nil {
   135  		return err
   136  	}
   137  	if cqe.Result() < 0 {
   138  		return syscall.Errno(-cqe.Result())
   139  	}
   140  	return nil
   141  }
   142  
   143  // Write ...
   144  type Write struct {
   145  	Buf    []byte
   146  	Offset uint64
   147  }