diff options
Diffstat (limited to 'fs/aio.c')
-rw-r--r-- | fs/aio.c | 34 |
1 files changed, 18 insertions, 16 deletions
@@ -1344,12 +1344,13 @@ typedef ssize_t (rw_iter_op)(struct kiocb *, struct iov_iter *); | |||
1344 | static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb, | 1344 | static 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 | ||
1372 | static ssize_t aio_setup_single_vector(struct kiocb *kiocb, | 1373 | static 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 | */ |
1390 | static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode, | 1392 | static 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; |