diff --git a/examples/null.rs b/examples/null.rs index d1eef16..bcf60ba 100755 --- a/examples/null.rs +++ b/examples/null.rs @@ -43,7 +43,15 @@ fn __test_add(id: i32, nr_queues: u32, depth: u32, ctrl_flags: u64, buf_size: u3 .nr_queues(nr_queues) .io_buf_bytes(buf_size) .ctrl_flags(ctrl_flags) - .dev_flags(UBLK_DEV_F_ADD_DEV | if aio { UBLK_DEV_F_ASYNC } else { 0 }) + .dev_flags( + UBLK_DEV_F_ADD_DEV + | if aio { UBLK_DEV_F_ASYNC } else { 0 } + | if (ctrl_flags & libublk::sys::UBLK_F_USER_COPY as u64) != 0 { + UBLK_DEV_F_DONT_ALLOC_BUF + } else { + 0 + }, + ) .build() .unwrap(); let tgt_init = |dev: &mut UblkDev| { diff --git a/examples/ramdisk.rs b/examples/ramdisk.rs index 63415cb..8b13596 100644 --- a/examples/ramdisk.rs +++ b/examples/ramdisk.rs @@ -8,12 +8,11 @@ use libublk::io::{UblkDev, UblkQueue}; use libublk::{ctrl::UblkCtrl, exe::Executor, UblkError}; use std::rc::Rc; -fn handle_io(q: &UblkQueue, tag: u16, start: u64) -> i32 { +fn handle_io(q: &UblkQueue, tag: u16, buf_addr: *mut u8, start: u64) -> i32 { let iod = q.get_iod(tag); let off = (iod.start_sector << 9) as u64; let bytes = (iod.nr_sectors << 9) as i32; let op = iod.op_flags & 0xff; - let buf_addr = q.get_io_buf_addr(tag); match op { libublk::sys::UBLK_IO_OP_READ => unsafe { @@ -45,7 +44,8 @@ fn rd_add_dev(dev_id: i32, buf_addr: u64, size: u64, for_add: bool) { UBLK_DEV_F_ADD_DEV } else { UBLK_DEV_F_RECOVER_DEV - } | UBLK_DEV_F_ASYNC; + } | UBLK_DEV_F_ASYNC + | UBLK_DEV_F_DONT_ALLOC_BUF; let depth = 128_u16; let sess = libublk::UblkSessionBuilder::default() @@ -66,20 +66,24 @@ fn rd_add_dev(dev_id: i32, buf_addr: u64, size: u64, for_add: bool) { let exe = Executor::new(dev.get_nr_ios()); let q_rc = Rc::new(UblkQueue::new(0, &dev).unwrap()); + let buf_size = dev.dev_info.max_io_buf_bytes as usize; for tag in 0..depth as u16 { let q = q_rc.clone(); + assert!(q.get_io_buf_addr(tag) == std::ptr::null_mut()); exe.spawn(tag as u16, async move { - let addr = q.get_io_buf_addr(tag); + let mut buffer: Vec = vec![0; buf_size]; + let addr = buffer.as_mut_ptr(); let mut cmd_op = libublk::sys::UBLK_IO_FETCH_REQ; let mut res = 0; + loop { let cmd_res = q.submit_io_cmd(tag, cmd_op, addr as u64, res).await; if cmd_res == libublk::sys::UBLK_IO_RES_ABORT { break; } - res = handle_io(&q, tag, buf_addr); + res = handle_io(&q, tag, addr, buf_addr); cmd_op = libublk::sys::UBLK_IO_COMMIT_AND_FETCH_REQ; } }); diff --git a/src/io.rs b/src/io.rs index 125d5f4..df38333 100644 --- a/src/io.rs +++ b/src/io.rs @@ -477,6 +477,12 @@ impl UblkQueue<'_> { let sq_depth = tgt.sq_depth; let cq_depth = tgt.cq_depth; + if ((dev.flags & UBLK_DEV_F_ASYNC) == 0) + && ((dev.dev_info.flags & (sys::UBLK_F_USER_COPY as u64)) == 0) + && ((dev.flags & UBLK_DEV_F_DONT_ALLOC_BUF) != 0) + { + return Err(UblkError::OtherError(-libc::EINVAL)); + } let ring = IoUring::::builder() .setup_cqsize(cq_depth as u32) .setup_coop_taskrun() @@ -521,7 +527,7 @@ impl UblkQueue<'_> { // extra io slot needn't to allocate buffer let addr = { if i < depth { - if (dev.dev_info.flags & (super::sys::UBLK_F_USER_COPY as u64)) == 0 { + if (dev.flags & UBLK_DEV_F_DONT_ALLOC_BUF) == 0 { super::ublk_alloc_buf(dev.dev_info.max_io_buf_bytes as usize, unsafe { libc::sysconf(libc::_SC_PAGESIZE).try_into().unwrap() }) diff --git a/src/lib.rs b/src/lib.rs index 7d2ae12..957c9c3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,8 +28,14 @@ pub mod dev_flags { /// use async/.await pub const UBLK_DEV_F_ASYNC: u32 = 1u32 << 3; - pub const UBLK_DEV_F_ALL: u32 = - UBLK_DEV_F_COMP_BATCH | UBLK_DEV_F_ADD_DEV | UBLK_DEV_F_RECOVER_DEV | UBLK_DEV_F_ASYNC; + /// need to preallocate io buffer + pub const UBLK_DEV_F_DONT_ALLOC_BUF: u32 = 1u32 << 4; + + pub const UBLK_DEV_F_ALL: u32 = UBLK_DEV_F_COMP_BATCH + | UBLK_DEV_F_ADD_DEV + | UBLK_DEV_F_RECOVER_DEV + | UBLK_DEV_F_ASYNC + | UBLK_DEV_F_DONT_ALLOC_BUF; } /// Ublk Fat completion result diff --git a/tests/basic.rs b/tests/basic.rs index 8dd404e..255979c 100644 --- a/tests/basic.rs +++ b/tests/basic.rs @@ -95,7 +95,10 @@ mod integration { .wait_and_handle_io(io_handler); } - __test_ublk_null(UBLK_DEV_F_ADD_DEV, null_handle_queue); + __test_ublk_null( + UBLK_DEV_F_ADD_DEV | UBLK_DEV_F_DONT_ALLOC_BUF, + null_handle_queue, + ); } /// make one ublk-null and test if /dev/ublkbN can be created successfully @@ -119,7 +122,7 @@ mod integration { } __test_ublk_null( - UBLK_DEV_F_ADD_DEV | UBLK_DEV_F_COMP_BATCH, + UBLK_DEV_F_ADD_DEV | UBLK_DEV_F_DONT_ALLOC_BUF | UBLK_DEV_F_COMP_BATCH, null_handle_queue_batch, ); } @@ -192,11 +195,11 @@ mod integration { let __dev_data = _dev_data.clone(); exe.spawn(tag as u16, async move { - let buf_addr = q.get_io_buf_addr(tag) as u64; let mut cmd_op = sys::UBLK_IO_FETCH_REQ; + let buf = q.get_io_buf_addr(tag); let mut res = 0; loop { - let cmd_res = q.submit_io_cmd(tag, cmd_op, buf_addr, res).await; + let cmd_res = q.submit_io_cmd(tag, cmd_op, buf as u64, res).await; if cmd_res == sys::UBLK_IO_RES_ABORT { break; } @@ -353,7 +356,10 @@ mod integration { .wait_and_handle_io(io_handler); } - __test_ublk_null(UBLK_DEV_F_ADD_DEV, null_queue_mut_io); + __test_ublk_null( + UBLK_DEV_F_ADD_DEV | UBLK_DEV_F_DONT_ALLOC_BUF, + null_queue_mut_io, + ); } /// run examples/ramdisk recovery test