aboutsummaryrefslogtreecommitdiffstats
path: root/fs/aio.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/aio.c')
-rw-r--r--fs/aio.c34
1 files changed, 18 insertions, 16 deletions
diff --git a/fs/aio.c b/fs/aio.c
index 118a2e0088d8..667054c7c067 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1344,12 +1344,13 @@ typedef ssize_t (rw_iter_op)(struct kiocb *, struct iov_iter *);
1344static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb, 1344static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb,
1345 int rw, char __user *buf, 1345 int rw, char __user *buf,
1346 unsigned long *nr_segs, 1346 unsigned long *nr_segs,
1347 size_t *len,
1347 struct iovec **iovec, 1348 struct iovec **iovec,
1348 bool compat) 1349 bool compat)
1349{ 1350{
1350 ssize_t ret; 1351 ssize_t ret;
1351 1352
1352 *nr_segs = kiocb->ki_nbytes; 1353 *nr_segs = *len;
1353 1354
1354#ifdef CONFIG_COMPAT 1355#ifdef CONFIG_COMPAT
1355 if (compat) 1356 if (compat)
@@ -1364,21 +1365,22 @@ static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb,
1364 if (ret < 0) 1365 if (ret < 0)
1365 return ret; 1366 return ret;
1366 1367
1367 /* ki_nbytes now reflect bytes instead of segs */ 1368 /* len now reflect bytes instead of segs */
1368 kiocb->ki_nbytes = ret; 1369 *len = ret;
1369 return 0; 1370 return 0;
1370} 1371}
1371 1372
1372static ssize_t aio_setup_single_vector(struct kiocb *kiocb, 1373static ssize_t aio_setup_single_vector(struct kiocb *kiocb,
1373 int rw, char __user *buf, 1374 int rw, char __user *buf,
1374 unsigned long *nr_segs, 1375 unsigned long *nr_segs,
1376 size_t len,
1375 struct iovec *iovec) 1377 struct iovec *iovec)
1376{ 1378{
1377 if (unlikely(!access_ok(!rw, buf, kiocb->ki_nbytes))) 1379 if (unlikely(!access_ok(!rw, buf, len)))
1378 return -EFAULT; 1380 return -EFAULT;
1379 1381
1380 iovec->iov_base = buf; 1382 iovec->iov_base = buf;
1381 iovec->iov_len = kiocb->ki_nbytes; 1383 iovec->iov_len = len;
1382 *nr_segs = 1; 1384 *nr_segs = 1;
1383 return 0; 1385 return 0;
1384} 1386}
@@ -1388,7 +1390,7 @@ static ssize_t aio_setup_single_vector(struct kiocb *kiocb,
1388 * Performs the initial checks and io submission. 1390 * Performs the initial checks and io submission.
1389 */ 1391 */
1390static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode, 1392static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode,
1391 char __user *buf, bool compat) 1393 char __user *buf, size_t len, bool compat)
1392{ 1394{
1393 struct file *file = req->ki_filp; 1395 struct file *file = req->ki_filp;
1394 ssize_t ret; 1396 ssize_t ret;
@@ -1423,21 +1425,21 @@ rw_common:
1423 if (!rw_op && !iter_op) 1425 if (!rw_op && !iter_op)
1424 return -EINVAL; 1426 return -EINVAL;
1425 1427
1426 ret = (opcode == IOCB_CMD_PREADV || 1428 if (opcode == IOCB_CMD_PREADV || opcode == IOCB_CMD_PWRITEV)
1427 opcode == IOCB_CMD_PWRITEV) 1429 ret = aio_setup_vectored_rw(req, rw, buf, &nr_segs,
1428 ? aio_setup_vectored_rw(req, rw, buf, &nr_segs, 1430 &len, &iovec, compat);
1429 &iovec, compat) 1431 else
1430 : aio_setup_single_vector(req, rw, buf, &nr_segs, 1432 ret = aio_setup_single_vector(req, rw, buf, &nr_segs,
1431 iovec); 1433 len, iovec);
1432 if (!ret) 1434 if (!ret)
1433 ret = rw_verify_area(rw, file, &req->ki_pos, req->ki_nbytes); 1435 ret = rw_verify_area(rw, file, &req->ki_pos, len);
1434 if (ret < 0) { 1436 if (ret < 0) {
1435 if (iovec != inline_vecs) 1437 if (iovec != inline_vecs)
1436 kfree(iovec); 1438 kfree(iovec);
1437 return ret; 1439 return ret;
1438 } 1440 }
1439 1441
1440 req->ki_nbytes = ret; 1442 len = ret;
1441 1443
1442 /* XXX: move/kill - rw_verify_area()? */ 1444 /* XXX: move/kill - rw_verify_area()? */
1443 /* This matches the pread()/pwrite() logic */ 1445 /* This matches the pread()/pwrite() logic */
@@ -1450,7 +1452,7 @@ rw_common:
1450 file_start_write(file); 1452 file_start_write(file);
1451 1453
1452 if (iter_op) { 1454 if (iter_op) {
1453 iov_iter_init(&iter, rw, iovec, nr_segs, req->ki_nbytes); 1455 iov_iter_init(&iter, rw, iovec, nr_segs, len);
1454 ret = iter_op(req, &iter); 1456 ret = iter_op(req, &iter);
1455 } else { 1457 } else {
1456 ret = rw_op(req, iovec, nr_segs, req->ki_pos); 1458 ret = rw_op(req, iovec, nr_segs, req->ki_pos);
@@ -1553,10 +1555,10 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
1553 req->ki_obj.user = user_iocb; 1555 req->ki_obj.user = user_iocb;
1554 req->ki_user_data = iocb->aio_data; 1556 req->ki_user_data = iocb->aio_data;
1555 req->ki_pos = iocb->aio_offset; 1557 req->ki_pos = iocb->aio_offset;
1556 req->ki_nbytes = iocb->aio_nbytes;
1557 1558
1558 ret = aio_run_iocb(req, iocb->aio_lio_opcode, 1559 ret = aio_run_iocb(req, iocb->aio_lio_opcode,
1559 (char __user *)(unsigned long)iocb->aio_buf, 1560 (char __user *)(unsigned long)iocb->aio_buf,
1561 iocb->aio_nbytes,
1560 compat); 1562 compat);
1561 if (ret) 1563 if (ret)
1562 goto out_put_req; 1564 goto out_put_req;