aio.c (eb5bc2a213f96bd43b5f00a625acb0c669613645) aio.c (66ee59af630fd8d5f4f56fb28162857e629aa0ab)
1/*
2 * An async IO implementation for Linux
3 * Written by Benjamin LaHaise <bcrl@kvack.org>
4 *
5 * Implements an efficient asynchronous io interface.
6 *
7 * Copyright 2000, 2001, 2002 Red Hat, Inc. All Rights Reserved.
8 *

--- 1271 unchanged lines hidden (view full) ---

1280 long ret;
1281
1282 ret = get_user(ctx, ctxp);
1283 if (unlikely(ret))
1284 goto out;
1285
1286 ret = -EINVAL;
1287 if (unlikely(ctx || nr_events == 0)) {
1/*
2 * An async IO implementation for Linux
3 * Written by Benjamin LaHaise <bcrl@kvack.org>
4 *
5 * Implements an efficient asynchronous io interface.
6 *
7 * Copyright 2000, 2001, 2002 Red Hat, Inc. All Rights Reserved.
8 *

--- 1271 unchanged lines hidden (view full) ---

1280 long ret;
1281
1282 ret = get_user(ctx, ctxp);
1283 if (unlikely(ret))
1284 goto out;
1285
1286 ret = -EINVAL;
1287 if (unlikely(ctx || nr_events == 0)) {
1288 pr_debug("EINVAL: ctx %lu nr_events %u\n",
1288 pr_debug("EINVAL: io_setup: ctx %lu nr_events %u\n",
1289 ctx, nr_events);
1290 goto out;
1291 }
1292
1293 ioctx = ioctx_alloc(nr_events);
1294 ret = PTR_ERR(ioctx);
1295 if (!IS_ERR(ioctx)) {
1296 ret = put_user(ioctx->user_id, ctxp);

--- 31 unchanged lines hidden (view full) ---

1328 * keep using user-space buffers even if user thinks the context
1329 * is destroyed.
1330 */
1331 if (!ret)
1332 wait_for_completion(&requests_done);
1333
1334 return ret;
1335 }
1289 ctx, nr_events);
1290 goto out;
1291 }
1292
1293 ioctx = ioctx_alloc(nr_events);
1294 ret = PTR_ERR(ioctx);
1295 if (!IS_ERR(ioctx)) {
1296 ret = put_user(ioctx->user_id, ctxp);

--- 31 unchanged lines hidden (view full) ---

1328 * keep using user-space buffers even if user thinks the context
1329 * is destroyed.
1330 */
1331 if (!ret)
1332 wait_for_completion(&requests_done);
1333
1334 return ret;
1335 }
1336 pr_debug("EINVAL: invalid context id\n");
1336 pr_debug("EINVAL: io_destroy: invalid context id\n");
1337 return -EINVAL;
1338}
1339
1340typedef ssize_t (aio_rw_op)(struct kiocb *, const struct iovec *,
1341 unsigned long, loff_t);
1342typedef ssize_t (rw_iter_op)(struct kiocb *, struct iov_iter *);
1343
1344static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb,
1345 int rw, char __user *buf,
1346 unsigned long *nr_segs,
1337 return -EINVAL;
1338}
1339
1340typedef ssize_t (aio_rw_op)(struct kiocb *, const struct iovec *,
1341 unsigned long, loff_t);
1342typedef ssize_t (rw_iter_op)(struct kiocb *, struct iov_iter *);
1343
1344static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb,
1345 int rw, char __user *buf,
1346 unsigned long *nr_segs,
1347 size_t *len,
1347 struct iovec **iovec,
1348 bool compat)
1349{
1350 ssize_t ret;
1351
1348 struct iovec **iovec,
1349 bool compat)
1350{
1351 ssize_t ret;
1352
1352 *nr_segs = kiocb->ki_nbytes;
1353 *nr_segs = *len;
1353
1354#ifdef CONFIG_COMPAT
1355 if (compat)
1356 ret = compat_rw_copy_check_uvector(rw,
1357 (struct compat_iovec __user *)buf,
1358 *nr_segs, UIO_FASTIOV, *iovec, iovec);
1359 else
1360#endif
1361 ret = rw_copy_check_uvector(rw,
1362 (struct iovec __user *)buf,
1363 *nr_segs, UIO_FASTIOV, *iovec, iovec);
1364 if (ret < 0)
1365 return ret;
1366
1354
1355#ifdef CONFIG_COMPAT
1356 if (compat)
1357 ret = compat_rw_copy_check_uvector(rw,
1358 (struct compat_iovec __user *)buf,
1359 *nr_segs, UIO_FASTIOV, *iovec, iovec);
1360 else
1361#endif
1362 ret = rw_copy_check_uvector(rw,
1363 (struct iovec __user *)buf,
1364 *nr_segs, UIO_FASTIOV, *iovec, iovec);
1365 if (ret < 0)
1366 return ret;
1367
1367 /* ki_nbytes now reflect bytes instead of segs */
1368 kiocb->ki_nbytes = ret;
1368 /* len now reflect bytes instead of segs */
1369 *len = ret;
1369 return 0;
1370}
1371
1372static ssize_t aio_setup_single_vector(struct kiocb *kiocb,
1373 int rw, char __user *buf,
1374 unsigned long *nr_segs,
1370 return 0;
1371}
1372
1373static ssize_t aio_setup_single_vector(struct kiocb *kiocb,
1374 int rw, char __user *buf,
1375 unsigned long *nr_segs,
1376 size_t len,
1375 struct iovec *iovec)
1376{
1377 struct iovec *iovec)
1378{
1377 if (unlikely(!access_ok(!rw, buf, kiocb->ki_nbytes)))
1379 if (unlikely(!access_ok(!rw, buf, len)))
1378 return -EFAULT;
1379
1380 iovec->iov_base = buf;
1380 return -EFAULT;
1381
1382 iovec->iov_base = buf;
1381 iovec->iov_len = kiocb->ki_nbytes;
1383 iovec->iov_len = len;
1382 *nr_segs = 1;
1383 return 0;
1384}
1385
1386/*
1387 * aio_run_iocb:
1388 * Performs the initial checks and io submission.
1389 */
1390static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode,
1384 *nr_segs = 1;
1385 return 0;
1386}
1387
1388/*
1389 * aio_run_iocb:
1390 * Performs the initial checks and io submission.
1391 */
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{
1393 struct file *file = req->ki_filp;
1394 ssize_t ret;
1395 unsigned long nr_segs;
1396 int rw;
1397 fmode_t mode;
1398 aio_rw_op *rw_op;
1399 rw_iter_op *iter_op;

--- 18 unchanged lines hidden (view full) ---

1418 goto rw_common;
1419rw_common:
1420 if (unlikely(!(file->f_mode & mode)))
1421 return -EBADF;
1422
1423 if (!rw_op && !iter_op)
1424 return -EINVAL;
1425
1394{
1395 struct file *file = req->ki_filp;
1396 ssize_t ret;
1397 unsigned long nr_segs;
1398 int rw;
1399 fmode_t mode;
1400 aio_rw_op *rw_op;
1401 rw_iter_op *iter_op;

--- 18 unchanged lines hidden (view full) ---

1420 goto rw_common;
1421rw_common:
1422 if (unlikely(!(file->f_mode & mode)))
1423 return -EBADF;
1424
1425 if (!rw_op && !iter_op)
1426 return -EINVAL;
1427
1426 ret = (opcode == IOCB_CMD_PREADV ||
1427 opcode == IOCB_CMD_PWRITEV)
1428 ? aio_setup_vectored_rw(req, rw, buf, &nr_segs,
1429 &iovec, compat)
1430 : aio_setup_single_vector(req, rw, buf, &nr_segs,
1431 iovec);
1428 if (opcode == IOCB_CMD_PREADV || opcode == IOCB_CMD_PWRITEV)
1429 ret = aio_setup_vectored_rw(req, rw, buf, &nr_segs,
1430 &len, &iovec, compat);
1431 else
1432 ret = aio_setup_single_vector(req, rw, buf, &nr_segs,
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) {
1435 if (iovec != inline_vecs)
1436 kfree(iovec);
1437 return ret;
1438 }
1439
1436 if (ret < 0) {
1437 if (iovec != inline_vecs)
1438 kfree(iovec);
1439 return ret;
1440 }
1441
1440 req->ki_nbytes = ret;
1442 len = ret;
1441
1442 /* XXX: move/kill - rw_verify_area()? */
1443 /* This matches the pread()/pwrite() logic */
1444 if (req->ki_pos < 0) {
1445 ret = -EINVAL;
1446 break;
1447 }
1448
1449 if (rw == WRITE)
1450 file_start_write(file);
1451
1452 if (iter_op) {
1443
1444 /* XXX: move/kill - rw_verify_area()? */
1445 /* This matches the pread()/pwrite() logic */
1446 if (req->ki_pos < 0) {
1447 ret = -EINVAL;
1448 break;
1449 }
1450
1451 if (rw == WRITE)
1452 file_start_write(file);
1453
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);
1455 } else {
1456 ret = rw_op(req, iovec, nr_segs, req->ki_pos);
1457 }
1458
1459 if (rw == WRITE)
1460 file_end_write(file);
1461 break;

--- 48 unchanged lines hidden (view full) ---

1510 }
1511
1512 /* prevent overflows */
1513 if (unlikely(
1514 (iocb->aio_buf != (unsigned long)iocb->aio_buf) ||
1515 (iocb->aio_nbytes != (size_t)iocb->aio_nbytes) ||
1516 ((ssize_t)iocb->aio_nbytes < 0)
1517 )) {
1456 ret = iter_op(req, &iter);
1457 } else {
1458 ret = rw_op(req, iovec, nr_segs, req->ki_pos);
1459 }
1460
1461 if (rw == WRITE)
1462 file_end_write(file);
1463 break;

--- 48 unchanged lines hidden (view full) ---

1512 }
1513
1514 /* prevent overflows */
1515 if (unlikely(
1516 (iocb->aio_buf != (unsigned long)iocb->aio_buf) ||
1517 (iocb->aio_nbytes != (size_t)iocb->aio_nbytes) ||
1518 ((ssize_t)iocb->aio_nbytes < 0)
1519 )) {
1518 pr_debug("EINVAL: overflow check\n");
1520 pr_debug("EINVAL: io_submit: overflow check\n");
1519 return -EINVAL;
1520 }
1521
1522 req = aio_get_req(ctx);
1523 if (unlikely(!req))
1524 return -EAGAIN;
1525
1526 req->ki_filp = fget(iocb->aio_fildes);

--- 21 unchanged lines hidden (view full) ---

1548 if (unlikely(ret)) {
1549 pr_debug("EFAULT: aio_key\n");
1550 goto out_put_req;
1551 }
1552
1553 req->ki_obj.user = user_iocb;
1554 req->ki_user_data = iocb->aio_data;
1555 req->ki_pos = iocb->aio_offset;
1521 return -EINVAL;
1522 }
1523
1524 req = aio_get_req(ctx);
1525 if (unlikely(!req))
1526 return -EAGAIN;
1527
1528 req->ki_filp = fget(iocb->aio_fildes);

--- 21 unchanged lines hidden (view full) ---

1550 if (unlikely(ret)) {
1551 pr_debug("EFAULT: aio_key\n");
1552 goto out_put_req;
1553 }
1554
1555 req->ki_obj.user = user_iocb;
1556 req->ki_user_data = iocb->aio_data;
1557 req->ki_pos = iocb->aio_offset;
1556 req->ki_nbytes = iocb->aio_nbytes;
1557
1558 ret = aio_run_iocb(req, iocb->aio_lio_opcode,
1559 (char __user *)(unsigned long)iocb->aio_buf,
1558
1559 ret = aio_run_iocb(req, iocb->aio_lio_opcode,
1560 (char __user *)(unsigned long)iocb->aio_buf,
1561 iocb->aio_nbytes,
1560 compat);
1561 if (ret)
1562 goto out_put_req;
1563
1564 return 0;
1565out_put_req:
1566 put_reqs_available(ctx, 1);
1567 percpu_ref_put(&ctx->reqs);

--- 175 unchanged lines hidden ---
1562 compat);
1563 if (ret)
1564 goto out_put_req;
1565
1566 return 0;
1567out_put_req:
1568 put_reqs_available(ctx, 1);
1569 percpu_ref_put(&ctx->reqs);

--- 175 unchanged lines hidden ---