diff --git a/CHANGELOG.md b/CHANGELOG.md
index f3b4c538e2..cba9ae2ca3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 ## [Unreleased]
 
 ### Added
+- Added safe support for nearly any buffer type in the `sys::aio` module.
+  ([#872](https://github.com/nix-rust/nix/pull/872))
 - Added `sys::aio::LioCb` as a wrapper for `libc::lio_listio`.
   ([#872](https://github.com/nix-rust/nix/pull/872))
 - Added `getsid` in `::nix::unistd`
@@ -31,6 +33,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
   ([#837](https://github.com/nix-rust/nix/pull/837))
 
 ### Removed
+- Removed explicit support for the `bytes` crate from the `sys::aio` module.
+  See `sys::aio::AioCb::from_boxed_slice`s examples for alternatives.
+  ([#872](https://github.com/nix-rust/nix/pull/872))
 - Removed `sys::aio::lio_listio`.  Use `sys::aio::LioCb::listio` instead.
   ([#872](https://github.com/nix-rust/nix/pull/872))
 
diff --git a/Cargo.toml b/Cargo.toml
index 651c2184ce..17a1bac94c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,15 +17,13 @@ bitflags = "1.0"
 cfg-if = "0.1.0"
 void = "1.0.2"
 
-[dependencies.bytes]
-version = "0.4.5"
-# Don't include the optional serde feature
-default-features = false
-
 [target.'cfg(target_os = "dragonfly")'.build-dependencies]
 gcc = "0.3"
 
 [dev-dependencies]
+# The examples use on a new feature of Bytes which should be available in 0.5.0
+# https://github.com/carllerche/bytes/pull/185
+bytes = { git = "https://github.com/carllerche/bytes", rev = "ae1b454" }
 lazy_static = "1"
 rand = "0.4"
 tempdir = "0.3"
diff --git a/src/lib.rs b/src/lib.rs
index 3873f4a18b..07e84c1272 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -16,7 +16,6 @@
 #![deny(missing_debug_implementations)]
 
 // External crates
-extern crate bytes;
 #[macro_use]
 extern crate bitflags;
 #[macro_use]
diff --git a/src/sys/aio.rs b/src/sys/aio.rs
index 5cb3b81850..8a958c8411 100644
--- a/src/sys/aio.rs
+++ b/src/sys/aio.rs
@@ -21,16 +21,15 @@
 //! not support this for all filesystems and devices.
 
 use {Error, Result};
-use bytes::{Bytes, BytesMut};
 use errno::Errno;
 use std::os::unix::io::RawFd;
 use libc::{c_void, off_t, size_t};
 use libc;
+use std::borrow::{Borrow, BorrowMut};
 use std::fmt;
 use std::fmt::Debug;
 use std::marker::PhantomData;
 use std::mem;
-use std::ops::Deref;
 use std::ptr::{null, null_mut};
 use std::thread;
 use sys::signal::*;
@@ -93,46 +92,38 @@ pub enum AioCancelStat {
 
 /// Owns (uniquely or shared) a memory buffer to keep it from `Drop`ing while
 /// the kernel has a pointer to it.
-#[derive(Clone, Debug)]
 pub enum Buffer<'a> {
     /// No buffer to own.
     ///
     /// Used for operations like `aio_fsync` that have no data, or for unsafe
     /// operations that work with raw pointers.
     None,
-    /// Immutable shared ownership `Bytes` object
-    // Must use out-of-line allocation so the address of the data will be
-    // stable.  `Bytes` and `BytesMut` sometimes dynamically allocate a buffer,
-    // and sometimes inline the data within the struct itself.
-    Bytes(Bytes),
-    /// Mutable uniquely owned `BytesMut` object
-    BytesMut(BytesMut),
     /// Keeps a reference to a slice
-    Phantom(PhantomData<&'a mut [u8]>)
+    Phantom(PhantomData<&'a mut [u8]>),
+    /// Generic thing that keeps a buffer from dropping
+    BoxedSlice(Box<Borrow<[u8]>>),
+    /// Generic thing that keeps a mutable buffer from dropping
+    BoxedMutSlice(Box<BorrowMut<[u8]>>),
 }
 
-impl<'a> Buffer<'a> {
-    /// Return the inner `Bytes`, if any
-    pub fn bytes(&self) -> Option<&Bytes> {
-        match *self {
-            Buffer::Bytes(ref x) => Some(x),
-            _ => None
-        }
-    }
-
-    /// Return the inner `BytesMut`, if any
-    pub fn bytes_mut(&self) -> Option<&BytesMut> {
-        match *self {
-            Buffer::BytesMut(ref x) => Some(x),
-            _ => None
-        }
-    }
-
-    /// Is this `Buffer` `None`?
-    pub fn is_none(&self) -> bool {
-        match *self {
-            Buffer::None => true,
-            _ => false,
+impl<'a> Debug for Buffer<'a> {
+    // Note: someday it may be possible to Derive Debug for a trait object, but
+    // not today.
+    // https://github.com/rust-lang/rust/issues/1563
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            &Buffer::None => write!(fmt, "None"),
+            &Buffer::Phantom(p) => p.fmt(fmt),
+            &Buffer::BoxedSlice(ref bs) => {
+                let borrowed : &Borrow<[u8]> = bs.borrow();
+                write!(fmt, "BoxedSlice({:?})",
+                    borrowed as *const Borrow<[u8]>)
+            },
+            &Buffer::BoxedMutSlice(ref bms) => {
+                let borrowed : &BorrowMut<[u8]> = bms.borrow();
+                write!(fmt, "BoxedMutSlice({:?})",
+                    borrowed as *const BorrowMut<[u8]>)
+            }
         }
     }
 }
@@ -150,7 +141,7 @@ pub struct AioCb<'a> {
     /// Optionally keeps a reference to the data.
     ///
     /// Used to keep buffers from `Drop`'ing, and may be returned once the
-    /// `AioCb` is completed by `into_buffer`.
+    /// `AioCb` is completed by [`buffer`](#method.buffer).
     buffer: Buffer<'a>
 }
 
@@ -166,6 +157,50 @@ impl<'a> AioCb<'a> {
         x
     }
 
+    /// Remove the inner boxed slice, if any, and return it.
+    ///
+    /// The returned value will be the argument that was passed to
+    /// `from_boxed_slice` when this `AioCb` was created.
+    ///
+    /// It is an error to call this method while the `AioCb` is still in
+    /// progress.
+    pub fn boxed_slice(&mut self) -> Option<Box<Borrow<[u8]>>> {
+        assert!(!self.in_progress, "Can't remove the buffer from an AioCb that's still in-progress.  Did you forget to call aio_return?");
+        if let Buffer::BoxedSlice(_) = self.buffer {
+            let mut oldbuffer = Buffer::None;
+            mem::swap(&mut self.buffer, &mut oldbuffer);
+            if let Buffer::BoxedSlice(inner) = oldbuffer {
+                Some(inner)
+            } else {
+                unreachable!();
+            }
+        } else {
+            None
+        }
+    }
+
+    /// Remove the inner boxed mutable slice, if any, and return it.
+    ///
+    /// The returned value will be the argument that was passed to
+    /// `from_boxed_mut_slice` when this `AioCb` was created.
+    ///
+    /// It is an error to call this method while the `AioCb` is still in
+    /// progress.
+    pub fn boxed_mut_slice(&mut self) -> Option<Box<BorrowMut<[u8]>>> {
+        assert!(!self.in_progress, "Can't remove the buffer from an AioCb that's still in-progress.  Did you forget to call aio_return?");
+        if let Buffer::BoxedMutSlice(_) = self.buffer {
+            let mut oldbuffer = Buffer::None;
+            mem::swap(&mut self.buffer, &mut oldbuffer);
+            if let Buffer::BoxedMutSlice(inner) = oldbuffer {
+                Some(inner)
+            } else {
+                unreachable!();
+            }
+        } else {
+            None
+        }
+    }
+
     /// Returns the underlying file descriptor associated with the `AioCb`
     pub fn fd(&self) -> RawFd {
         self.aiocb.aio_fildes
@@ -187,7 +222,7 @@ impl<'a> AioCb<'a> {
     /// # Examples
     ///
     /// Create an `AioCb` from a raw file descriptor and use it for an
-    /// [`fsync`](#method.from_bytes_mut) operation.
+    /// [`fsync`](#method.fsync) operation.
     ///
     /// ```
     /// # extern crate tempfile;
@@ -300,17 +335,19 @@ impl<'a> AioCb<'a> {
         }
     }
 
-    /// Constructs a new `AioCb` from a `Bytes` object.
+    /// The safest and most flexible way to create an `AioCb`.
     ///
-    /// Unlike `from_slice`, this method returns a structure suitable for
+    /// Unlike [`from_slice`], this method returns a structure suitable for
     /// placement on the heap.  It may be used for write operations, but not
-    /// read operations.
+    /// read operations.  Unlike `from_ptr`, this method will ensure that the
+    /// buffer doesn't `drop` while the kernel is still processing it.  Any
+    /// object that can be borrowed as a boxed slice will work.
     ///
     /// # Parameters
     ///
     /// * `fd`:           File descriptor.  Required for all aio functions.
     /// * `offs`:         File offset
-    /// * `buf`:          A shared memory buffer
+    /// * `buf`:          A boxed slice-like object
     /// * `prio`:         If POSIX Prioritized IO is supported, then the
     ///                   operation will be prioritized at the process's
     ///                   priority level minus `prio`
@@ -322,15 +359,13 @@ impl<'a> AioCb<'a> {
     ///
     /// # Examples
     ///
-    /// Create an `AioCb` from a `Bytes` object and use it for writing.
+    /// Create an `AioCb` from a Vector and use it for writing
     ///
     /// ```
-    /// # extern crate bytes;
     /// # extern crate tempfile;
     /// # extern crate nix;
     /// # use nix::errno::Errno;
     /// # use nix::Error;
-    /// # use bytes::Bytes;
     /// # use nix::sys::aio::*;
     /// # use nix::sys::signal::SigevNotify;
     /// # use std::{thread, time};
@@ -338,11 +373,12 @@ impl<'a> AioCb<'a> {
     /// # use std::os::unix::io::AsRawFd;
     /// # use tempfile::tempfile;
     /// # fn main() {
-    /// let wbuf = Bytes::from(&b"CDEF"[..]);
+    /// let wbuf = Box::new(Vec::from("CDEF"));
+    /// let expected_len = wbuf.len();
     /// let mut f = tempfile().unwrap();
-    /// let mut aiocb = AioCb::from_bytes( f.as_raw_fd(),
+    /// let mut aiocb = AioCb::from_boxed_slice( f.as_raw_fd(),
     ///     2,   //offset
-    ///     wbuf.clone(),
+    ///     wbuf,
     ///     0,   //priority
     ///     SigevNotify::SigevNone,
     ///     LioOpcode::LIO_NOP);
@@ -350,72 +386,103 @@ impl<'a> AioCb<'a> {
     /// while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
     ///     thread::sleep(time::Duration::from_millis(10));
     /// }
-    /// assert_eq!(aiocb.aio_return().unwrap() as usize, wbuf.len());
+    /// assert_eq!(aiocb.aio_return().unwrap() as usize, expected_len);
+    /// # }
+    /// ```
+    ///
+    /// Create an `AioCb` from a `Bytes` object
+    ///
+    /// ```
+    /// # extern crate bytes;
+    /// # extern crate tempfile;
+    /// # extern crate nix;
+    /// # use bytes::Bytes;
+    /// # use nix::sys::aio::*;
+    /// # use nix::sys::signal::SigevNotify;
+    /// # use std::os::unix::io::AsRawFd;
+    /// # use tempfile::tempfile;
+    /// # fn main() {
+    /// let wbuf = Box::new(Bytes::from(&b"CDEF"[..]));
+    /// let mut f = tempfile().unwrap();
+    /// let mut aiocb = AioCb::from_boxed_slice( f.as_raw_fd(),
+    ///     2,   //offset
+    ///     wbuf,
+    ///     0,   //priority
+    ///     SigevNotify::SigevNone,
+    ///     LioOpcode::LIO_NOP);
     /// # }
     /// ```
-    pub fn from_bytes(fd: RawFd, offs: off_t, buf: Bytes,
+    ///
+    /// If a library needs to work with buffers that aren't `Box`ed, it can
+    /// create a `Box`ed container for use with this method.  Here's an example
+    /// using an un`Box`ed `Bytes` object.
+    ///
+    /// ```
+    /// # extern crate bytes;
+    /// # extern crate tempfile;
+    /// # extern crate nix;
+    /// # use bytes::Bytes;
+    /// # use nix::sys::aio::*;
+    /// # use nix::sys::signal::SigevNotify;
+    /// # use std::borrow::Borrow;
+    /// # use std::os::unix::io::AsRawFd;
+    /// # use tempfile::tempfile;
+    /// struct BytesContainer(Bytes);
+    /// impl Borrow<[u8]> for BytesContainer {
+    ///     fn borrow(&self) -> &[u8] {
+    ///         self.0.as_ref()
+    ///     }
+    /// }
+    /// fn main() {
+    ///     let wbuf = Bytes::from(&b"CDEF"[..]);
+    ///     let boxed_wbuf = Box::new(BytesContainer(wbuf));
+    ///     let mut f = tempfile().unwrap();
+    ///     let mut aiocb = AioCb::from_boxed_slice( f.as_raw_fd(),
+    ///         2,   //offset
+    ///         boxed_wbuf,
+    ///         0,   //priority
+    ///         SigevNotify::SigevNone,
+    ///         LioOpcode::LIO_NOP);
+    /// }
+    /// ```
+    ///
+    /// [`from_slice`]: #method.from_slice
+    pub fn from_boxed_slice(fd: RawFd, offs: off_t, buf: Box<Borrow<[u8]>>,
                       prio: libc::c_int, sigev_notify: SigevNotify,
                       opcode: LioOpcode) -> AioCb<'a> {
-        // Small BytesMuts are stored inline.  Inline storage is a no-no,
-        // because we store a pointer to the buffer in the AioCb before
-        // returning the Buffer by move.  If the buffer is too small, reallocate
-        // it to force out-of-line storage
-        // TODO: Add an is_inline() method to BytesMut, and a way to explicitly
-        // force out-of-line allocation.
-        let buf2 = if buf.len() < 64 {
-            // Reallocate to force out-of-line allocation
-            let mut ool = Bytes::with_capacity(64);
-            ool.extend_from_slice(buf.deref());
-            ool
-        } else {
-            buf
-        };
         let mut a = AioCb::common_init(fd, prio, sigev_notify);
+        {
+            let borrowed : &Borrow<[u8]> = buf.borrow();
+            let slice : &[u8] = borrowed.borrow();
+            a.aio_nbytes = slice.len() as size_t;
+            a.aio_buf = slice.as_ptr() as *mut c_void;
+        }
         a.aio_offset = offs;
-        a.aio_nbytes = buf2.len() as size_t;
-        a.aio_buf = buf2.as_ptr() as *mut c_void;
         a.aio_lio_opcode = opcode as libc::c_int;
 
         AioCb {
             aiocb: a,
             mutable: false,
             in_progress: false,
-            buffer: Buffer::Bytes(buf2),
+            buffer: Buffer::BoxedSlice(buf),
         }
     }
 
-    /// Constructs a new `AioCb` from a `BytesMut` object.
-    ///
-    /// Unlike `from_mut_slice`, this method returns a structure suitable for
-    /// placement on the heap.  It may be used for both reads and writes.
-    ///
-    /// # Parameters
+    /// The safest and most flexible way to create an `AioCb` for reading.
     ///
-    /// * `fd`:           File descriptor.  Required for all aio functions.
-    /// * `offs`:         File offset
-    /// * `buf`:          An owned memory buffer
-    /// * `prio`:         If POSIX Prioritized IO is supported, then the
-    ///                   operation will be prioritized at the process's
-    ///                   priority level minus `prio`
-    /// * `sigev_notify`: Determines how you will be notified of event
-    ///                   completion.
-    /// * `opcode`:       This field is only used for `lio_listio`.  It
-    ///                   determines which operation to use for this individual
-    ///                   aiocb
+    /// Like [`from_boxed_slice`], but the slice is a mutable one.  More
+    /// flexible than [`from_mut_slice`], because a wide range of objects can be
+    /// used.
     ///
     /// # Examples
     ///
-    /// Create an `AioCb` from a `BytesMut` and use it for reading.  In this
-    /// example the `AioCb` is stack-allocated, so we could've used
-    /// `from_mut_slice` instead.
+    /// Create an `AioCb` from a Vector and use it for reading
     ///
     /// ```
-    /// # extern crate bytes;
     /// # extern crate tempfile;
     /// # extern crate nix;
     /// # use nix::errno::Errno;
     /// # use nix::Error;
-    /// # use bytes::BytesMut;
     /// # use nix::sys::aio::*;
     /// # use nix::sys::signal::SigevNotify;
     /// # use std::{thread, time};
@@ -425,10 +492,10 @@ impl<'a> AioCb<'a> {
     /// # fn main() {
     /// const INITIAL: &[u8] = b"abcdef123456";
     /// const LEN: usize = 4;
-    /// let rbuf = BytesMut::from(vec![0; LEN]);
+    /// let rbuf = Box::new(vec![0; LEN]);
     /// let mut f = tempfile().unwrap();
     /// f.write_all(INITIAL).unwrap();
-    /// let mut aiocb = AioCb::from_bytes_mut( f.as_raw_fd(),
+    /// let mut aiocb = AioCb::from_boxed_mut_slice( f.as_raw_fd(),
     ///     2,   //offset
     ///     rbuf,
     ///     0,   //priority
@@ -439,33 +506,33 @@ impl<'a> AioCb<'a> {
     ///     thread::sleep(time::Duration::from_millis(10));
     /// }
     /// assert_eq!(aiocb.aio_return().unwrap() as usize, LEN);
-    /// let buffer = aiocb.into_buffer();
+    /// let mut buffer = aiocb.boxed_mut_slice().unwrap();
     /// const EXPECT: &[u8] = b"cdef";
-    /// assert_eq!(buffer.bytes_mut().unwrap(), EXPECT);
+    /// assert_eq!(buffer.borrow_mut(), EXPECT);
     /// # }
     /// ```
-    pub fn from_bytes_mut(fd: RawFd, offs: off_t, buf: BytesMut,
-                          prio: libc::c_int, sigev_notify: SigevNotify,
-                          opcode: LioOpcode) -> AioCb<'a> {
-        let mut buf2 = if buf.len() < 64 {
-            // Reallocate to force out-of-line allocation
-            let mut ool = BytesMut::with_capacity(64);
-            ool.extend_from_slice(buf.deref());
-            ool
-        } else {
-            buf
-        };
+    ///
+    /// [`from_boxed_slice`]: #method.from_boxed_slice
+    /// [`from_mut_slice`]: #method.from_mut_slice
+    pub fn from_boxed_mut_slice(fd: RawFd, offs: off_t,
+                                mut buf: Box<BorrowMut<[u8]>>,
+                                prio: libc::c_int, sigev_notify: SigevNotify,
+                                opcode: LioOpcode) -> AioCb<'a> {
         let mut a = AioCb::common_init(fd, prio, sigev_notify);
+        {
+            let borrowed : &mut BorrowMut<[u8]> = buf.borrow_mut();
+            let slice : &mut [u8] = borrowed.borrow_mut();
+            a.aio_nbytes = slice.len() as size_t;
+            a.aio_buf = slice.as_mut_ptr() as *mut c_void;
+        }
         a.aio_offset = offs;
-        a.aio_nbytes = buf2.len() as size_t;
-        a.aio_buf = buf2.as_mut_ptr() as *mut c_void;
         a.aio_lio_opcode = opcode as libc::c_int;
 
         AioCb {
             aiocb: a,
             mutable: true,
             in_progress: false,
-            buffer: Buffer::BytesMut(buf2),
+            buffer: Buffer::BoxedMutSlice(buf),
         }
     }
 
@@ -475,7 +542,7 @@ impl<'a> AioCb<'a> {
     /// placement on the heap.  It may be used for both reads and writes.  Due
     /// to its unsafety, this method is not recommended.  It is most useful when
     /// heap allocation is required but for some reason the data cannot be
-    /// converted to a `BytesMut`.
+    /// wrapped in a `struct` that implements `BorrowMut<[u8]>`
     ///
     /// # Parameters
     ///
@@ -519,7 +586,8 @@ impl<'a> AioCb<'a> {
     /// Unlike `from_slice`, this method returns a structure suitable for
     /// placement on the heap.  Due to its unsafety, this method is not
     /// recommended.  It is most useful when heap allocation is required but for
-    /// some reason the data cannot be converted to a `Bytes`.
+    /// some reason the data cannot be wrapped in a `struct` that implements
+    /// `Borrow<[u8]>`
     ///
     /// # Parameters
     ///
@@ -624,19 +692,6 @@ impl<'a> AioCb<'a> {
         }
     }
 
-    /// Consumes the `aiocb` and returns its inner `Buffer`, if any.
-    ///
-    /// This method is especially useful when reading into a `BytesMut`, because
-    /// that type does not support shared ownership.
-    pub fn into_buffer(mut self) -> Buffer<'static> {
-        let buf = self.buffer();
-        match buf {
-            Buffer::BytesMut(x) => Buffer::BytesMut(x),
-            Buffer::Bytes(x) => Buffer::Bytes(x),
-            _ => Buffer::None
-        }
-    }
-
     fn common_init(fd: RawFd, prio: libc::c_int,
                    sigev_notify: SigevNotify) -> libc::aiocb {
         // Use mem::zeroed instead of explicitly zeroing each field, because the
@@ -670,12 +725,10 @@ impl<'a> AioCb<'a> {
     /// result.
     ///
     /// ```
-    /// # extern crate bytes;
     /// # extern crate tempfile;
     /// # extern crate nix;
     /// # use nix::errno::Errno;
     /// # use nix::Error;
-    /// # use bytes::Bytes;
     /// # use nix::sys::aio::*;
     /// # use nix::sys::signal::SigevNotify;
     /// # use std::{thread, time};
@@ -683,11 +736,11 @@ impl<'a> AioCb<'a> {
     /// # use std::os::unix::io::AsRawFd;
     /// # use tempfile::tempfile;
     /// # fn main() {
-    /// let wbuf = Bytes::from(&b"CDEF"[..]);
+    /// let wbuf = b"CDEF";
     /// let mut f = tempfile().unwrap();
-    /// let mut aiocb = AioCb::from_bytes( f.as_raw_fd(),
+    /// let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
     ///     2,   //offset
-    ///     wbuf.clone(),
+    ///     &wbuf[..],
     ///     0,   //priority
     ///     SigevNotify::SigevNone,
     ///     LioOpcode::LIO_NOP);
@@ -871,12 +924,10 @@ impl<'a> AioCb<'a> {
 /// descriptor.
 ///
 /// ```
-/// # extern crate bytes;
 /// # extern crate tempfile;
 /// # extern crate nix;
 /// # use nix::errno::Errno;
 /// # use nix::Error;
-/// # use bytes::Bytes;
 /// # use nix::sys::aio::*;
 /// # use nix::sys::signal::SigevNotify;
 /// # use std::{thread, time};
@@ -884,11 +935,11 @@ impl<'a> AioCb<'a> {
 /// # use std::os::unix::io::AsRawFd;
 /// # use tempfile::tempfile;
 /// # fn main() {
-/// let wbuf = Bytes::from(&b"CDEF"[..]);
+/// let wbuf = b"CDEF";
 /// let mut f = tempfile().unwrap();
-/// let mut aiocb = AioCb::from_bytes( f.as_raw_fd(),
+/// let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
 ///     2,   //offset
-///     wbuf.clone(),
+///     &wbuf[..],
 ///     0,   //priority
 ///     SigevNotify::SigevNone,
 ///     LioOpcode::LIO_NOP);
diff --git a/test/sys/test_aio.rs b/test/sys/test_aio.rs
index f11c7ef939..0f7d71e5c1 100644
--- a/test/sys/test_aio.rs
+++ b/test/sys/test_aio.rs
@@ -323,20 +323,21 @@ fn test_write() {
     assert!(rbuf == EXPECT);
 }
 
-// Tests `AioCb::from_bytes`
+// Tests `AioCb::from_boxed_slice` with `Bytes`
 #[test]
 #[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
 fn test_write_bytes() {
     const INITIAL: &[u8] = b"abcdef123456";
-    let wbuf = Bytes::from(&b"CDEF"[..]);
+    let wbuf = Box::new(Bytes::from(&b"CDEF"[..]));
     let mut rbuf = Vec::new();
     const EXPECT: &[u8] = b"abCDEF123456";
+    let expected_len = wbuf.len();
 
     let mut f = tempfile().unwrap();
     f.write_all(INITIAL).unwrap();
-    let mut aiocb = AioCb::from_bytes( f.as_raw_fd(),
+    let mut aiocb = AioCb::from_boxed_slice( f.as_raw_fd(),
                            2,   //offset
-                           wbuf.clone(),
+                           wbuf,
                            0,   //priority
                            SigevNotify::SigevNone,
                            LioOpcode::LIO_NOP);
@@ -344,7 +345,7 @@ fn test_write_bytes() {
 
     let err = poll_aio(&mut aiocb);
     assert!(err == Ok(()));
-    assert!(aiocb.aio_return().unwrap() as usize == wbuf.len());
+    assert!(aiocb.aio_return().unwrap() as usize == expected_len);
 
     f.seek(SeekFrom::Start(0)).unwrap();
     let len = f.read_to_end(&mut rbuf).unwrap();
@@ -352,46 +353,17 @@ fn test_write_bytes() {
     assert!(rbuf == EXPECT);
 }
 
-// Tests `AioCb::from_bytes_mut`
-#[test]
-#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-fn test_read_bytes_mut_big() {
-    const INITIAL: &[u8] = b"abcdefgh12345678abcdefgh12345678abcdefgh12345678abcdefgh12345678abcdefgh12345678";
-    // rbuf needs to be larger than 32 bytes (64 on 32-bit systems) so
-    // BytesMut::clone is implemented by reference.
-    let rbuf = BytesMut::from(vec![0; 70]);
-    const EXPECT: &[u8] = b"cdefgh12345678abcdefgh12345678abcdefgh12345678abcdefgh12345678abcdefgh";
-    let mut f = tempfile().unwrap();
-    f.write_all(INITIAL).unwrap();
-
-    let mut aiocb = AioCb::from_bytes_mut( f.as_raw_fd(),
-                           2,   //offset
-                           rbuf,
-                           0,   //priority
-                           SigevNotify::SigevNone,
-                           LioOpcode::LIO_NOP);
-    aiocb.read().unwrap();
-
-    let err = poll_aio(&mut aiocb);
-    assert_eq!(err, Ok(()));
-    assert_eq!(aiocb.aio_return().unwrap() as usize, EXPECT.len());
-    let buffer = aiocb.into_buffer();
-    assert_eq!(buffer.bytes_mut().unwrap(), EXPECT);
-}
-
-// Tests reallocation in `AioCb::from_bytes_mut`
+// Tests `AioCb::from_boxed_mut_slice` with `BytesMut`
 #[test]
 #[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
 fn test_read_bytes_mut_small() {
     const INITIAL: &[u8] = b"abcdef";
-    // rbuf needs to be no more than 32 bytes (64 on 32-bit systems) so
-    // BytesMut::clone is implemented inline.
-    let rbuf = BytesMut::from(vec![0; 4]);
+    let rbuf = Box::new(BytesMut::from(vec![0; 4]));
     const EXPECT: &[u8] = b"cdef";
     let mut f = tempfile().unwrap();
     f.write_all(INITIAL).unwrap();
 
-    let mut aiocb = AioCb::from_bytes_mut( f.as_raw_fd(),
+    let mut aiocb = AioCb::from_boxed_mut_slice( f.as_raw_fd(),
                            2,   //offset
                            rbuf,
                            0,   //priority
@@ -402,8 +374,8 @@ fn test_read_bytes_mut_small() {
     let err = poll_aio(&mut aiocb);
     assert_eq!(err, Ok(()));
     assert_eq!(aiocb.aio_return().unwrap() as usize, EXPECT.len());
-    let buffer = aiocb.into_buffer();
-    assert_eq!(buffer.bytes_mut().unwrap(), EXPECT);
+    let buffer = aiocb.boxed_mut_slice().unwrap();
+    assert_eq!(buffer.borrow(), EXPECT);
 }
 
 // Tests `AioCb::from_ptr`