eventfd_ctx_put(req->ki_eventfd);
        if (req->ki_dtor)
                req->ki_dtor(req);
-       if (req->ki_iovec != &req->ki_inline_vec)
-               kfree(req->ki_iovec);
        kmem_cache_free(kiocb_cachep, req);
 }
 
 typedef ssize_t (aio_rw_op)(struct kiocb *, const struct iovec *,
                            unsigned long, loff_t);
 
-static ssize_t aio_setup_vectored_rw(int rw, struct kiocb *kiocb, bool compat)
+static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb,
+                                    int rw, char __user *buf,
+                                    unsigned long *nr_segs,
+                                    struct iovec **iovec,
+                                    bool compat)
 {
        ssize_t ret;
 
-       kiocb->ki_nr_segs = kiocb->ki_nbytes;
+       *nr_segs = kiocb->ki_nbytes;
 
 #ifdef CONFIG_COMPAT
        if (compat)
                ret = compat_rw_copy_check_uvector(rw,
-                               (struct compat_iovec __user *)kiocb->ki_buf,
-                               kiocb->ki_nr_segs, 1, &kiocb->ki_inline_vec,
-                               &kiocb->ki_iovec);
+                               (struct compat_iovec __user *)buf,
+                               *nr_segs, 1, *iovec, iovec);
        else
 #endif
                ret = rw_copy_check_uvector(rw,
-                               (struct iovec __user *)kiocb->ki_buf,
-                               kiocb->ki_nr_segs, 1, &kiocb->ki_inline_vec,
-                               &kiocb->ki_iovec);
+                               (struct iovec __user *)buf,
+                               *nr_segs, 1, *iovec, iovec);
        if (ret < 0)
                return ret;
 
        return 0;
 }
 
-static ssize_t aio_setup_single_vector(int rw, struct kiocb *kiocb)
+static ssize_t aio_setup_single_vector(struct kiocb *kiocb,
+                                      int rw, char __user *buf,
+                                      unsigned long *nr_segs,
+                                      struct iovec *iovec)
 {
-       if (unlikely(!access_ok(!rw, kiocb->ki_buf, kiocb->ki_nbytes)))
+       if (unlikely(!access_ok(!rw, buf, kiocb->ki_nbytes)))
                return -EFAULT;
 
-       kiocb->ki_iovec = &kiocb->ki_inline_vec;
-       kiocb->ki_iovec->iov_base = kiocb->ki_buf;
-       kiocb->ki_iovec->iov_len = kiocb->ki_nbytes;
-       kiocb->ki_nr_segs = 1;
+       iovec->iov_base = buf;
+       iovec->iov_len = kiocb->ki_nbytes;
+       *nr_segs = 1;
        return 0;
 }
 
  *     Performs the initial checks and aio retry method
  *     setup for the kiocb at the time of io submission.
  */
-static ssize_t aio_run_iocb(struct kiocb *req, bool compat)
+static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode,
+                           char __user *buf, bool compat)
 {
        struct file *file = req->ki_filp;
        ssize_t ret;
+       unsigned long nr_segs;
        int rw;
        fmode_t mode;
        aio_rw_op *rw_op;
+       struct iovec inline_vec, *iovec = &inline_vec;
 
-       switch (req->ki_opcode) {
+       switch (opcode) {
        case IOCB_CMD_PREAD:
        case IOCB_CMD_PREADV:
                mode    = FMODE_READ;
                if (!rw_op)
                        return -EINVAL;
 
-               ret = (req->ki_opcode == IOCB_CMD_PREADV ||
-                      req->ki_opcode == IOCB_CMD_PWRITEV)
-                       ? aio_setup_vectored_rw(rw, req, compat)
-                       : aio_setup_single_vector(rw, req);
+               ret = (opcode == IOCB_CMD_PREADV ||
+                      opcode == IOCB_CMD_PWRITEV)
+                       ? aio_setup_vectored_rw(req, rw, buf, &nr_segs,
+                                               &iovec, compat)
+                       : aio_setup_single_vector(req, rw, buf, &nr_segs,
+                                                 iovec);
                if (ret)
                        return ret;
 
                ret = rw_verify_area(rw, file, &req->ki_pos, req->ki_nbytes);
-               if (ret < 0)
+               if (ret < 0) {
+                       if (iovec != &inline_vec)
+                               kfree(iovec);
                        return ret;
+               }
 
                req->ki_nbytes = ret;
 
                if (rw == WRITE)
                        file_start_write(file);
 
-               ret = rw_op(req, req->ki_iovec,
-                           req->ki_nr_segs, req->ki_pos);
+               ret = rw_op(req, iovec, nr_segs, req->ki_pos);
 
                if (rw == WRITE)
                        file_end_write(file);
                return -EINVAL;
        }
 
+       if (iovec != &inline_vec)
+               kfree(iovec);
+
        if (ret != -EIOCBQUEUED) {
                /*
                 * There's no easy way to restart the syscall since other AIO's
        req->ki_obj.user = user_iocb;
        req->ki_user_data = iocb->aio_data;
        req->ki_pos = iocb->aio_offset;
-
-       req->ki_buf = (char __user *)(unsigned long)iocb->aio_buf;
        req->ki_nbytes = iocb->aio_nbytes;
-       req->ki_opcode = iocb->aio_lio_opcode;
 
-       ret = aio_run_iocb(req, compat);
+       ret = aio_run_iocb(req, iocb->aio_lio_opcode,
+                          (char __user *)(unsigned long)iocb->aio_buf,
+                          compat);
        if (ret)
                goto out_put_req;