From cc220f22d5d09913970dbc700cbe714a20e2c2e3 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Sun, 9 Feb 2020 20:16:10 -0700 Subject: [PATCH] Fix readv_at on device nodes Using readv_at on device nodes with a preferred sector sie > 1 never worked with unaligned buffers. A mistake in the test failed to check that the data was correctly copied back to users' buffers. This fixes it. --- CHANGELOG.md | 6 ++++++ src/file.rs | 18 +++++++++++++++--- tests/file.rs | 23 +++++++++++++++-------- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5327c4..4e797ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [Unreleased] - ReleaseDate +### Fixed +- Fixed `readv_at` on device nodes with unaligned buffers + (#[13](https://github.com/asomers/tokio-file/pull/13)) + + ## [0.5.1] - 2019-09-05 ### Changed diff --git a/src/file.rs b/src/file.rs index 2634d1c..0a8460c 100644 --- a/src/file.rs +++ b/src/file.rs @@ -179,15 +179,27 @@ impl Future for LioFut { }) }); let mut last_inner_result: Option = None; + let mut last_inner_ofs = 0; let iter = obuf_iter.map(move |mut obuf_ref| { - if let Some((buf_ref, mc)) = obuf_ref.take() { + if let Some((mut buf_ref, mc)) = obuf_ref.take() { if mc { last_inner_result = Some(inner_iter.next().unwrap()); + last_inner_ofs = 0; } let lir = last_inner_result.as_ref().unwrap(); if lir.value.is_ok() { - let len = buf_ref.len().unwrap() as isize; - LioResult{value: Ok(len), buf: buf_ref} + let len = buf_ref.len().unwrap(); + if let BufRef::BoxedMutSlice(ref mut bms) = buf_ref { + (**bms).borrow_mut().copy_from_slice( + &match &lir.buf { + BufRef::BoxedMutSlice(bms) => (**bms).borrow(), + BufRef::BoxedSlice(bs) => (**bs).borrow(), + BufRef::None => unreachable!() + }[last_inner_ofs..(last_inner_ofs + len)] + ); + last_inner_ofs += len; + } + LioResult{value: Ok(len as isize), buf: buf_ref} } else { let r = lir.value; LioResult{value: r, buf: buf_ref} diff --git a/tests/file.rs b/tests/file.rs index 596f84c..9f84555 100644 --- a/tests/file.rs +++ b/tests/file.rs @@ -325,8 +325,15 @@ test_suite! { Box::new(dbs.try_mut().unwrap()) as Box> }).collect::>(); let mut rt = current_thread::Runtime::new().unwrap(); - let file = t!(File::open(&path)); + fs::OpenOptions::new() + .write(true) + .open(&path) + .expect("open failed") + .write_all(&orig) + .expect("write failed"); + + let file = t!(File::open(&path)); let mut ri = rt.block_on(lazy(|| { file.readv_at(rbufs, 0).expect("readv_at failed early") })).unwrap(); @@ -339,13 +346,13 @@ test_suite! { assert!(ri.next().is_none()); drop(file); - assert_eq!(&vec![0u8; 100][..], &orig[0..100]); - assert_eq!(&vec![1u8; 412][..], &orig[100..512]); - assert_eq!(&vec![2u8; 512][..], &orig[512..1024]); - assert_eq!(&vec![3u8; 100][..], &orig[1024..1124]); - assert_eq!(&vec![4u8; 100][..], &orig[1124..1224]); - assert_eq!(&vec![5u8; 312][..], &orig[1224..1536]); - assert_eq!(&vec![6u8; 512][..], &orig[1536..2048]); + assert_eq!(&dbses[0].try_const().unwrap()[..], &orig[0..100]); + assert_eq!(&dbses[1].try_const().unwrap()[..], &orig[100..512]); + assert_eq!(&dbses[2].try_const().unwrap()[..], &orig[512..1024]); + assert_eq!(&dbses[3].try_const().unwrap()[..], &orig[1024..1124]); + assert_eq!(&dbses[4].try_const().unwrap()[..], &orig[1124..1224]); + assert_eq!(&dbses[5].try_const().unwrap()[..], &orig[1224..1536]); + assert_eq!(&dbses[6].try_const().unwrap()[..], &orig[1536..2048]); } else { println!("This test requires root privileges"); }