]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/aio.c
Merge remote-tracking branch 'ubifs/linux-next'
[karo-tx-linux.git] / fs / aio.c
index ae401412f8691cd8d8f1669bc7d180dd444e57fb..a5630703eb565f4c0d2062bbe7b3ab1617dc2213 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1199,13 +1199,55 @@ static ssize_t aio_setup_single_vector(struct kiocb *kiocb,
        return 0;
 }
 
+static ssize_t aio_read_iter(struct kiocb *iocb, struct iov_iter *iter)
+{
+       struct file *file = iocb->ki_filp;
+       ssize_t ret;
+
+       if (unlikely(!is_kernel_kiocb(iocb)))
+               return -EINVAL;
+
+       if (unlikely(!(file->f_mode & FMODE_READ)))
+               return -EBADF;
+
+       ret = security_file_permission(file, MAY_READ);
+       if (unlikely(ret))
+               return ret;
+
+       if (!file->f_op->read_iter)
+               return -EINVAL;
+
+       return file->f_op->read_iter(iocb, iter, iocb->ki_pos);
+}
+
+static ssize_t aio_write_iter(struct kiocb *iocb, struct iov_iter *iter)
+{
+       struct file *file = iocb->ki_filp;
+       ssize_t ret;
+
+       if (unlikely(!is_kernel_kiocb(iocb)))
+               return -EINVAL;
+
+       if (unlikely(!(file->f_mode & FMODE_WRITE)))
+               return -EBADF;
+
+       ret = security_file_permission(file, MAY_WRITE);
+       if (unlikely(ret))
+               return ret;
+
+       if (!file->f_op->write_iter)
+               return -EINVAL;
+
+       return file->f_op->write_iter(iocb, iter, iocb->ki_pos);
+}
+
 /*
  * aio_setup_iocb:
  *     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, unsigned opcode,
-                           char __user *buf, bool compat)
+                           void *buf, bool compat)
 {
        struct file *file = req->ki_filp;
        ssize_t ret;
@@ -1220,14 +1262,14 @@ static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode,
        case IOCB_CMD_PREADV:
                mode    = FMODE_READ;
                rw      = READ;
-               rw_op   = file->f_op->aio_read;
+               rw_op   = do_aio_read;
                goto rw_common;
 
        case IOCB_CMD_PWRITE:
        case IOCB_CMD_PWRITEV:
                mode    = FMODE_WRITE;
                rw      = WRITE;
-               rw_op   = file->f_op->aio_write;
+               rw_op   = do_aio_write;
                goto rw_common;
 rw_common:
                if (unlikely(!(file->f_mode & mode)))
@@ -1270,6 +1312,14 @@ rw_common:
                        file_end_write(file);
                break;
 
+       case IOCB_CMD_READ_ITER:
+               ret = aio_read_iter(req, buf);
+               break;
+
+       case IOCB_CMD_WRITE_ITER:
+               ret = aio_write_iter(req, buf);
+               break;
+
        case IOCB_CMD_FDSYNC:
                if (!file->f_op->aio_fsync)
                        return -EINVAL;
@@ -1440,7 +1490,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
        req->ki_nbytes = iocb->aio_nbytes;
 
        ret = aio_run_iocb(req, iocb->aio_lio_opcode,
-                          (char __user *)(unsigned long)iocb->aio_buf,
+                          (void *)(unsigned long)iocb->aio_buf,
                           compat);
        if (ret)
                goto out_put_req;