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 --- |