1
0
Fork 0
mirror of https://github.com/ii64/gouring.git synced 2025-04-26 05:42:48 +02:00

chore: basic usage example

This commit is contained in:
Xeffy Chen 2023-04-16 04:00:36 +07:00
parent ff91bfb1cd
commit 29583697c8
Signed by: Xeffy
GPG key ID: E41C08AD390E7C49
3 changed files with 255 additions and 0 deletions
examples

163
examples/nvme/nvme.go Normal file
View file

@ -0,0 +1,163 @@
package main
import (
"fmt"
"syscall"
"unsafe"
uring "github.com/ii64/gouring"
nvme "github.com/ii64/gouring/nvme"
"golang.org/x/sys/unix"
)
var (
// hardcoded device path
// devicePath = "/dev/nvme0n1"
devicePath = "/dev/ng0n1"
nsid uint32
lbaSize uint32
lbaShift int
BS uint64 = 8192
)
func DoNvmeGetInfo(devPath string) error {
fd, err := unix.Open(devPath, unix.O_RDONLY, 0)
if err != nil {
return err
}
defer func() {
if err := unix.Close(fd); err != nil {
panic(err)
}
}()
var (
ns nvme.NvmeIdNs
cmd nvme.NvmePassthruCmd
)
nsidRet, err := sys_ioctl(fd, uintptr(nvme.NVME_IOCTL_ID), 0)
if err != nil {
return err
}
nsid = uint32(nsidRet)
cmd = nvme.NvmePassthruCmd{
Opcode: nvme.NVME_ADMIN_IDENTIFY,
Nsid: nsid,
Addr: uint64(uintptr(unsafe.Pointer(&ns))),
DataLen: nvme.NVME_IDENTIFY_DATA_SIZE,
Cdw10: nvme.NVME_IDENTIFY_CNS_NS,
Cdw11: nvme.NVME_CSI_NVM << nvme.NVME_IDENTIFY_CSI_SHIFT,
TimeoutMs: nvme.NVME_DEFAULT_IOCTL_TIMEOUT,
}
_, err = sys_ioctl(fd, uintptr(nvme.NVME_IOCTL_ADMIN_CMD), uintptr(unsafe.Pointer(&cmd)))
if err != nil {
return err
}
lbaSize = 1 << ns.Lbaf[(ns.Flbas&0x0F)].Ds
lbaShift = ilog2(uint32(lbaSize))
return nil
}
func DoIoUring(devPath string) error {
ring, err := uring.New(64,
uring.IORING_SETUP_IOPOLL|
uring.IORING_SETUP_SQE128|uring.IORING_SETUP_CQE32)
if err != nil {
return err
}
defer ring.Close()
fd, err := unix.Open(devicePath, unix.O_RDONLY, 0) // 0 as it O_RDONLY
if err != nil {
panic(err)
}
defer unix.Close(fd)
var buf [0x1000]byte
sqe := ring.GetSqe()
uring.PrepRead(sqe, fd, &buf[0], len(buf), 0)
sqe.SetCmdOp(uint32(nvme.NVME_URING_CMD_IO))
sqe.Opcode = uring.IORING_OP_URING_CMD
var off uint64 = 0
var i uint32 = 1
sqe.UserData.SetUint64(uint64(off<<32) | uint64(i)) // temp
var slba uint64 = off >> lbaShift
var nlb uint64 = BS>>lbaShift - 1
// zero and init
cmd := nvme.NvmeUringCmd{
Opcode: nvme.NVME_CMD_READ,
// cdw10 and cdw11 represent starting lba
Cdw10: uint32(slba & 0xffff_ffff),
Cdw11: uint32(slba >> 32),
// represent number of lba's for read/write
Cdw12: uint32(nlb),
Nsid: nsid,
Addr: uint64(uintptr(unsafe.Pointer(&buf))),
DataLen: uint32(len(buf)),
}
cmdPtr := (*nvme.NvmeUringCmd)(sqe.GetCmd())
*cmdPtr = cmd // copy
fmt.Printf("CMD %+#v\n", cmdPtr)
submitted, err := ring.SubmitAndWait(1)
if err != nil {
return err
}
fmt.Println("submitted", submitted)
var cqe *uring.IoUringCqe
if err := ring.WaitCqe(&cqe); err != nil {
return err
}
ring.SeenCqe(cqe)
fmt.Printf("CQE:\t%+#v\n", cqe)
cqeExtra := (*[2]uint64)(cqe.GetBigCqe())
fmt.Printf("CQE Extra:\t%+#v\n", cqeExtra)
fmt.Printf("Buffer: %+#v\n", buf)
return nil
}
func main() {
err := DoNvmeGetInfo(devicePath)
if err != nil {
panic(err)
}
fmt.Printf("lbaSize: %d lbaShift: %d\n", lbaSize, lbaShift)
if err := DoIoUring(devicePath); err != nil {
panic(err)
}
}
func sys_ioctl(fd int, a1, a2 uintptr) (int, error) {
r1, _, err := syscall.Syscall(syscall.SYS_IOCTL,
uintptr(fd), a1, a2)
if err != 0 {
return 0, err
}
return int(r1), nil
}
func ilog2(i uint32) int {
log := -1
for i > 0 {
i >>= 1
log++
}
return log
}

48
examples/read/read.go Normal file
View file

@ -0,0 +1,48 @@
package main
import (
"log"
"github.com/ii64/gouring"
"golang.org/x/sys/unix"
)
func main() {
h, err := gouring.New(256, 0)
if err != nil {
log.Fatal(err)
}
defer h.Close()
fd, err := unix.Open("/tmp/test", unix.O_RDWR, 0677)
sqe := h.GetSqe()
b := make([]byte, 20)
gouring.PrepRead(sqe, fd, &b[0], len(b), 0)
log.Println("Buffer: ", b)
submitted, err := h.SubmitAndWait(1)
if err != nil {
log.Fatal(err)
}
println(submitted) // 1
var cqe *gouring.IoUringCqe
err = h.WaitCqe(&cqe)
if err != nil {
log.Fatal(err)
} // check also EINTR
if cqe == nil {
log.Fatal("CQE is NULL!")
}
h.SeenCqe(cqe)
log.Println("CQE: ", cqe)
log.Println("Buffer: ", b)
log.Println("Buffer: ", string(b))
_ = cqe.UserData
_ = cqe.Res
_ = cqe.Flags
}

44
examples/write/write.go Normal file
View file

@ -0,0 +1,44 @@
package main
import (
"log"
"github.com/ii64/gouring"
"golang.org/x/sys/unix"
)
func main() {
h, err := gouring.New(256, 0)
if err != nil {
log.Fatal(err)
}
defer h.Close()
fd, err := unix.Open("/tmp/test", unix.O_RDWR, 0677)
sqe := h.GetSqe()
b := []byte("hello from io_uring!\n")
gouring.PrepWrite(sqe, fd, &b[0], len(b), 0)
submitted, err := h.SubmitAndWait(1)
if err != nil { /*...*/
log.Fatal(err)
}
println(submitted) // 1
var cqe *gouring.IoUringCqe
err = h.WaitCqe(&cqe)
if err != nil {
log.Fatal(err)
} // check also EINTR
if cqe == nil {
log.Fatal("CQE is NULL!")
}
log.Println(cqe)
h.SeenCqe(cqe)
_ = cqe.UserData
_ = cqe.Res
_ = cqe.Flags
}