diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-11-11 12:19:01 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-11-11 12:19:01 -0500 |
commit | c5e4ca6da93f69939542385ca23d7ccebddc3f7d (patch) | |
tree | da01507b6d050f5ac9face51a7be904ed5cc18dd /fs | |
parent | ef091b3cef2d699568b51559ae8340b996f43230 (diff) | |
parent | e519e7774784f3fa7728657d780863805ed1c983 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull VFS fixes from Al Viro:
"Christoph's and Jan's aio fixes, fixup for generic_file_splice_read
(removal of pointless detritus that actually breaks it when used for
gfs2 ->splice_read()) and fixup for generic_file_read_iter()
interaction with ITER_PIPE destinations."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
splice: remove detritus from generic_file_splice_read()
mm/filemap: don't allow partially uptodate page for pipes
aio: fix freeze protection of aio writes
fs: remove aio_run_iocb
fs: remove the never implemented aio_fsync file operation
aio: hold an extra file reference over AIO read/write operations
Diffstat (limited to 'fs')
-rw-r--r-- | fs/aio.c | 207 | ||||
-rw-r--r-- | fs/ntfs/dir.c | 2 | ||||
-rw-r--r-- | fs/splice.c | 5 |
3 files changed, 109 insertions, 105 deletions
@@ -1078,6 +1078,17 @@ static void aio_complete(struct kiocb *kiocb, long res, long res2) | |||
1078 | unsigned tail, pos, head; | 1078 | unsigned tail, pos, head; |
1079 | unsigned long flags; | 1079 | unsigned long flags; |
1080 | 1080 | ||
1081 | if (kiocb->ki_flags & IOCB_WRITE) { | ||
1082 | struct file *file = kiocb->ki_filp; | ||
1083 | |||
1084 | /* | ||
1085 | * Tell lockdep we inherited freeze protection from submission | ||
1086 | * thread. | ||
1087 | */ | ||
1088 | __sb_writers_acquired(file_inode(file)->i_sb, SB_FREEZE_WRITE); | ||
1089 | file_end_write(file); | ||
1090 | } | ||
1091 | |||
1081 | /* | 1092 | /* |
1082 | * Special case handling for sync iocbs: | 1093 | * Special case handling for sync iocbs: |
1083 | * - events go directly into the iocb for fast handling | 1094 | * - events go directly into the iocb for fast handling |
@@ -1392,122 +1403,106 @@ SYSCALL_DEFINE1(io_destroy, aio_context_t, ctx) | |||
1392 | return -EINVAL; | 1403 | return -EINVAL; |
1393 | } | 1404 | } |
1394 | 1405 | ||
1395 | typedef ssize_t (rw_iter_op)(struct kiocb *, struct iov_iter *); | 1406 | static int aio_setup_rw(int rw, struct iocb *iocb, struct iovec **iovec, |
1396 | 1407 | bool vectored, bool compat, struct iov_iter *iter) | |
1397 | static int aio_setup_vectored_rw(int rw, char __user *buf, size_t len, | ||
1398 | struct iovec **iovec, | ||
1399 | bool compat, | ||
1400 | struct iov_iter *iter) | ||
1401 | { | 1408 | { |
1409 | void __user *buf = (void __user *)(uintptr_t)iocb->aio_buf; | ||
1410 | size_t len = iocb->aio_nbytes; | ||
1411 | |||
1412 | if (!vectored) { | ||
1413 | ssize_t ret = import_single_range(rw, buf, len, *iovec, iter); | ||
1414 | *iovec = NULL; | ||
1415 | return ret; | ||
1416 | } | ||
1402 | #ifdef CONFIG_COMPAT | 1417 | #ifdef CONFIG_COMPAT |
1403 | if (compat) | 1418 | if (compat) |
1404 | return compat_import_iovec(rw, | 1419 | return compat_import_iovec(rw, buf, len, UIO_FASTIOV, iovec, |
1405 | (struct compat_iovec __user *)buf, | 1420 | iter); |
1406 | len, UIO_FASTIOV, iovec, iter); | ||
1407 | #endif | 1421 | #endif |
1408 | return import_iovec(rw, (struct iovec __user *)buf, | 1422 | return import_iovec(rw, buf, len, UIO_FASTIOV, iovec, iter); |
1409 | len, UIO_FASTIOV, iovec, iter); | ||
1410 | } | 1423 | } |
1411 | 1424 | ||
1412 | /* | 1425 | static inline ssize_t aio_ret(struct kiocb *req, ssize_t ret) |
1413 | * aio_run_iocb: | 1426 | { |
1414 | * Performs the initial checks and io submission. | 1427 | switch (ret) { |
1415 | */ | 1428 | case -EIOCBQUEUED: |
1416 | static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode, | 1429 | return ret; |
1417 | char __user *buf, size_t len, bool compat) | 1430 | case -ERESTARTSYS: |
1431 | case -ERESTARTNOINTR: | ||
1432 | case -ERESTARTNOHAND: | ||
1433 | case -ERESTART_RESTARTBLOCK: | ||
1434 | /* | ||
1435 | * There's no easy way to restart the syscall since other AIO's | ||
1436 | * may be already running. Just fail this IO with EINTR. | ||
1437 | */ | ||
1438 | ret = -EINTR; | ||
1439 | /*FALLTHRU*/ | ||
1440 | default: | ||
1441 | aio_complete(req, ret, 0); | ||
1442 | return 0; | ||
1443 | } | ||
1444 | } | ||
1445 | |||
1446 | static ssize_t aio_read(struct kiocb *req, struct iocb *iocb, bool vectored, | ||
1447 | bool compat) | ||
1418 | { | 1448 | { |
1419 | struct file *file = req->ki_filp; | 1449 | struct file *file = req->ki_filp; |
1420 | ssize_t ret; | ||
1421 | int rw; | ||
1422 | fmode_t mode; | ||
1423 | rw_iter_op *iter_op; | ||
1424 | struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs; | 1450 | struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs; |
1425 | struct iov_iter iter; | 1451 | struct iov_iter iter; |
1452 | ssize_t ret; | ||
1426 | 1453 | ||
1427 | switch (opcode) { | 1454 | if (unlikely(!(file->f_mode & FMODE_READ))) |
1428 | case IOCB_CMD_PREAD: | 1455 | return -EBADF; |
1429 | case IOCB_CMD_PREADV: | 1456 | if (unlikely(!file->f_op->read_iter)) |
1430 | mode = FMODE_READ; | 1457 | return -EINVAL; |
1431 | rw = READ; | ||
1432 | iter_op = file->f_op->read_iter; | ||
1433 | goto rw_common; | ||
1434 | |||
1435 | case IOCB_CMD_PWRITE: | ||
1436 | case IOCB_CMD_PWRITEV: | ||
1437 | mode = FMODE_WRITE; | ||
1438 | rw = WRITE; | ||
1439 | iter_op = file->f_op->write_iter; | ||
1440 | goto rw_common; | ||
1441 | rw_common: | ||
1442 | if (unlikely(!(file->f_mode & mode))) | ||
1443 | return -EBADF; | ||
1444 | |||
1445 | if (!iter_op) | ||
1446 | return -EINVAL; | ||
1447 | |||
1448 | if (opcode == IOCB_CMD_PREADV || opcode == IOCB_CMD_PWRITEV) | ||
1449 | ret = aio_setup_vectored_rw(rw, buf, len, | ||
1450 | &iovec, compat, &iter); | ||
1451 | else { | ||
1452 | ret = import_single_range(rw, buf, len, iovec, &iter); | ||
1453 | iovec = NULL; | ||
1454 | } | ||
1455 | if (!ret) | ||
1456 | ret = rw_verify_area(rw, file, &req->ki_pos, | ||
1457 | iov_iter_count(&iter)); | ||
1458 | if (ret < 0) { | ||
1459 | kfree(iovec); | ||
1460 | return ret; | ||
1461 | } | ||
1462 | |||
1463 | if (rw == WRITE) | ||
1464 | file_start_write(file); | ||
1465 | |||
1466 | ret = iter_op(req, &iter); | ||
1467 | |||
1468 | if (rw == WRITE) | ||
1469 | file_end_write(file); | ||
1470 | kfree(iovec); | ||
1471 | break; | ||
1472 | |||
1473 | case IOCB_CMD_FDSYNC: | ||
1474 | if (!file->f_op->aio_fsync) | ||
1475 | return -EINVAL; | ||
1476 | |||
1477 | ret = file->f_op->aio_fsync(req, 1); | ||
1478 | break; | ||
1479 | 1458 | ||
1480 | case IOCB_CMD_FSYNC: | 1459 | ret = aio_setup_rw(READ, iocb, &iovec, vectored, compat, &iter); |
1481 | if (!file->f_op->aio_fsync) | 1460 | if (ret) |
1482 | return -EINVAL; | 1461 | return ret; |
1462 | ret = rw_verify_area(READ, file, &req->ki_pos, iov_iter_count(&iter)); | ||
1463 | if (!ret) | ||
1464 | ret = aio_ret(req, file->f_op->read_iter(req, &iter)); | ||
1465 | kfree(iovec); | ||
1466 | return ret; | ||
1467 | } | ||
1483 | 1468 | ||
1484 | ret = file->f_op->aio_fsync(req, 0); | 1469 | static ssize_t aio_write(struct kiocb *req, struct iocb *iocb, bool vectored, |
1485 | break; | 1470 | bool compat) |
1471 | { | ||
1472 | struct file *file = req->ki_filp; | ||
1473 | struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs; | ||
1474 | struct iov_iter iter; | ||
1475 | ssize_t ret; | ||
1486 | 1476 | ||
1487 | default: | 1477 | if (unlikely(!(file->f_mode & FMODE_WRITE))) |
1488 | pr_debug("EINVAL: no operation provided\n"); | 1478 | return -EBADF; |
1479 | if (unlikely(!file->f_op->write_iter)) | ||
1489 | return -EINVAL; | 1480 | return -EINVAL; |
1490 | } | ||
1491 | 1481 | ||
1492 | if (ret != -EIOCBQUEUED) { | 1482 | ret = aio_setup_rw(WRITE, iocb, &iovec, vectored, compat, &iter); |
1483 | if (ret) | ||
1484 | return ret; | ||
1485 | ret = rw_verify_area(WRITE, file, &req->ki_pos, iov_iter_count(&iter)); | ||
1486 | if (!ret) { | ||
1487 | req->ki_flags |= IOCB_WRITE; | ||
1488 | file_start_write(file); | ||
1489 | ret = aio_ret(req, file->f_op->write_iter(req, &iter)); | ||
1493 | /* | 1490 | /* |
1494 | * There's no easy way to restart the syscall since other AIO's | 1491 | * We release freeze protection in aio_complete(). Fool lockdep |
1495 | * may be already running. Just fail this IO with EINTR. | 1492 | * by telling it the lock got released so that it doesn't |
1493 | * complain about held lock when we return to userspace. | ||
1496 | */ | 1494 | */ |
1497 | if (unlikely(ret == -ERESTARTSYS || ret == -ERESTARTNOINTR || | 1495 | __sb_writers_release(file_inode(file)->i_sb, SB_FREEZE_WRITE); |
1498 | ret == -ERESTARTNOHAND || | ||
1499 | ret == -ERESTART_RESTARTBLOCK)) | ||
1500 | ret = -EINTR; | ||
1501 | aio_complete(req, ret, 0); | ||
1502 | } | 1496 | } |
1503 | 1497 | kfree(iovec); | |
1504 | return 0; | 1498 | return ret; |
1505 | } | 1499 | } |
1506 | 1500 | ||
1507 | static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, | 1501 | static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, |
1508 | struct iocb *iocb, bool compat) | 1502 | struct iocb *iocb, bool compat) |
1509 | { | 1503 | { |
1510 | struct aio_kiocb *req; | 1504 | struct aio_kiocb *req; |
1505 | struct file *file; | ||
1511 | ssize_t ret; | 1506 | ssize_t ret; |
1512 | 1507 | ||
1513 | /* enforce forwards compatibility on users */ | 1508 | /* enforce forwards compatibility on users */ |
@@ -1530,7 +1525,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, | |||
1530 | if (unlikely(!req)) | 1525 | if (unlikely(!req)) |
1531 | return -EAGAIN; | 1526 | return -EAGAIN; |
1532 | 1527 | ||
1533 | req->common.ki_filp = fget(iocb->aio_fildes); | 1528 | req->common.ki_filp = file = fget(iocb->aio_fildes); |
1534 | if (unlikely(!req->common.ki_filp)) { | 1529 | if (unlikely(!req->common.ki_filp)) { |
1535 | ret = -EBADF; | 1530 | ret = -EBADF; |
1536 | goto out_put_req; | 1531 | goto out_put_req; |
@@ -1565,13 +1560,29 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, | |||
1565 | req->ki_user_iocb = user_iocb; | 1560 | req->ki_user_iocb = user_iocb; |
1566 | req->ki_user_data = iocb->aio_data; | 1561 | req->ki_user_data = iocb->aio_data; |
1567 | 1562 | ||
1568 | ret = aio_run_iocb(&req->common, iocb->aio_lio_opcode, | 1563 | get_file(file); |
1569 | (char __user *)(unsigned long)iocb->aio_buf, | 1564 | switch (iocb->aio_lio_opcode) { |
1570 | iocb->aio_nbytes, | 1565 | case IOCB_CMD_PREAD: |
1571 | compat); | 1566 | ret = aio_read(&req->common, iocb, false, compat); |
1572 | if (ret) | 1567 | break; |
1573 | goto out_put_req; | 1568 | case IOCB_CMD_PWRITE: |
1569 | ret = aio_write(&req->common, iocb, false, compat); | ||
1570 | break; | ||
1571 | case IOCB_CMD_PREADV: | ||
1572 | ret = aio_read(&req->common, iocb, true, compat); | ||
1573 | break; | ||
1574 | case IOCB_CMD_PWRITEV: | ||
1575 | ret = aio_write(&req->common, iocb, true, compat); | ||
1576 | break; | ||
1577 | default: | ||
1578 | pr_debug("invalid aio operation %d\n", iocb->aio_lio_opcode); | ||
1579 | ret = -EINVAL; | ||
1580 | break; | ||
1581 | } | ||
1582 | fput(file); | ||
1574 | 1583 | ||
1584 | if (ret && ret != -EIOCBQUEUED) | ||
1585 | goto out_put_req; | ||
1575 | return 0; | 1586 | return 0; |
1576 | out_put_req: | 1587 | out_put_req: |
1577 | put_reqs_available(ctx, 1); | 1588 | put_reqs_available(ctx, 1); |
diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c index a18613579001..0ee19ecc982d 100644 --- a/fs/ntfs/dir.c +++ b/fs/ntfs/dir.c | |||
@@ -1544,8 +1544,6 @@ const struct file_operations ntfs_dir_ops = { | |||
1544 | .iterate = ntfs_readdir, /* Read directory contents. */ | 1544 | .iterate = ntfs_readdir, /* Read directory contents. */ |
1545 | #ifdef NTFS_RW | 1545 | #ifdef NTFS_RW |
1546 | .fsync = ntfs_dir_fsync, /* Sync a directory to disk. */ | 1546 | .fsync = ntfs_dir_fsync, /* Sync a directory to disk. */ |
1547 | /*.aio_fsync = ,*/ /* Sync all outstanding async | ||
1548 | i/o operations on a kiocb. */ | ||
1549 | #endif /* NTFS_RW */ | 1547 | #endif /* NTFS_RW */ |
1550 | /*.ioctl = ,*/ /* Perform function on the | 1548 | /*.ioctl = ,*/ /* Perform function on the |
1551 | mounted filesystem. */ | 1549 | mounted filesystem. */ |
diff --git a/fs/splice.c b/fs/splice.c index 153d4f3bd441..dcaf185a5731 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -299,13 +299,8 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos, | |||
299 | { | 299 | { |
300 | struct iov_iter to; | 300 | struct iov_iter to; |
301 | struct kiocb kiocb; | 301 | struct kiocb kiocb; |
302 | loff_t isize; | ||
303 | int idx, ret; | 302 | int idx, ret; |
304 | 303 | ||
305 | isize = i_size_read(in->f_mapping->host); | ||
306 | if (unlikely(*ppos >= isize)) | ||
307 | return 0; | ||
308 | |||
309 | iov_iter_pipe(&to, ITER_PIPE | READ, pipe, len); | 304 | iov_iter_pipe(&to, ITER_PIPE | READ, pipe, len); |
310 | idx = to.idx; | 305 | idx = to.idx; |
311 | init_sync_kiocb(&kiocb, in); | 306 | init_sync_kiocb(&kiocb, in); |