diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2015-03-20 20:17:32 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2015-04-11 22:26:45 -0400 |
commit | 4c185ce06dca14f5cea192f5a2c981ef50663f2b (patch) | |
tree | 1a6d775a568d477089b85690160f11b07a812180 | |
parent | ac15ac0669d5f5ce7fddec0d9cf3721c42d77a2c (diff) |
aio: lift iov_iter_init() into aio_setup_..._rw()
the only non-trivial detail is that we do it before rw_verify_area(),
so we'd better cap the length ourselves in aio_setup_single_rw()
case (for vectored case rw_copy_check_uvector() will do that for us).
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/aio.c | 17 |
1 files changed, 11 insertions, 6 deletions
@@ -1357,7 +1357,8 @@ static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb, | |||
1357 | unsigned long *nr_segs, | 1357 | unsigned long *nr_segs, |
1358 | size_t *len, | 1358 | size_t *len, |
1359 | struct iovec **iovec, | 1359 | struct iovec **iovec, |
1360 | bool compat) | 1360 | bool compat, |
1361 | struct iov_iter *iter) | ||
1361 | { | 1362 | { |
1362 | ssize_t ret; | 1363 | ssize_t ret; |
1363 | 1364 | ||
@@ -1378,6 +1379,7 @@ static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb, | |||
1378 | 1379 | ||
1379 | /* len now reflect bytes instead of segs */ | 1380 | /* len now reflect bytes instead of segs */ |
1380 | *len = ret; | 1381 | *len = ret; |
1382 | iov_iter_init(iter, rw, *iovec, *nr_segs, *len); | ||
1381 | return 0; | 1383 | return 0; |
1382 | } | 1384 | } |
1383 | 1385 | ||
@@ -1385,14 +1387,18 @@ static ssize_t aio_setup_single_vector(struct kiocb *kiocb, | |||
1385 | int rw, char __user *buf, | 1387 | int rw, char __user *buf, |
1386 | unsigned long *nr_segs, | 1388 | unsigned long *nr_segs, |
1387 | size_t len, | 1389 | size_t len, |
1388 | struct iovec *iovec) | 1390 | struct iovec *iovec, |
1391 | struct iov_iter *iter) | ||
1389 | { | 1392 | { |
1393 | if (len > MAX_RW_COUNT) | ||
1394 | len = MAX_RW_COUNT; | ||
1390 | if (unlikely(!access_ok(!rw, buf, len))) | 1395 | if (unlikely(!access_ok(!rw, buf, len))) |
1391 | return -EFAULT; | 1396 | return -EFAULT; |
1392 | 1397 | ||
1393 | iovec->iov_base = buf; | 1398 | iovec->iov_base = buf; |
1394 | iovec->iov_len = len; | 1399 | iovec->iov_len = len; |
1395 | *nr_segs = 1; | 1400 | *nr_segs = 1; |
1401 | iov_iter_init(iter, rw, iovec, *nr_segs, len); | ||
1396 | return 0; | 1402 | return 0; |
1397 | } | 1403 | } |
1398 | 1404 | ||
@@ -1438,10 +1444,10 @@ rw_common: | |||
1438 | 1444 | ||
1439 | if (opcode == IOCB_CMD_PREADV || opcode == IOCB_CMD_PWRITEV) | 1445 | if (opcode == IOCB_CMD_PREADV || opcode == IOCB_CMD_PWRITEV) |
1440 | ret = aio_setup_vectored_rw(req, rw, buf, &nr_segs, | 1446 | ret = aio_setup_vectored_rw(req, rw, buf, &nr_segs, |
1441 | &len, &iovec, compat); | 1447 | &len, &iovec, compat, &iter); |
1442 | else | 1448 | else |
1443 | ret = aio_setup_single_vector(req, rw, buf, &nr_segs, | 1449 | ret = aio_setup_single_vector(req, rw, buf, &nr_segs, |
1444 | len, iovec); | 1450 | len, iovec, &iter); |
1445 | if (!ret) | 1451 | if (!ret) |
1446 | ret = rw_verify_area(rw, file, &req->ki_pos, len); | 1452 | ret = rw_verify_area(rw, file, &req->ki_pos, len); |
1447 | if (ret < 0) { | 1453 | if (ret < 0) { |
@@ -1463,10 +1469,9 @@ rw_common: | |||
1463 | file_start_write(file); | 1469 | file_start_write(file); |
1464 | 1470 | ||
1465 | if (iter_op) { | 1471 | if (iter_op) { |
1466 | iov_iter_init(&iter, rw, iovec, nr_segs, len); | ||
1467 | ret = iter_op(req, &iter); | 1472 | ret = iter_op(req, &iter); |
1468 | } else { | 1473 | } else { |
1469 | ret = rw_op(req, iovec, nr_segs, req->ki_pos); | 1474 | ret = rw_op(req, iter.iov, iter.nr_segs, req->ki_pos); |
1470 | } | 1475 | } |
1471 | 1476 | ||
1472 | if (rw == WRITE) | 1477 | if (rw == WRITE) |