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 }