diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-03-02 18:20:00 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-03-02 18:20:00 -0500 |
| commit | 94e877d0fb43bec0540d6a37d49cb4f7f05a5348 (patch) | |
| tree | dc301912dff9c390cba59df00cb76b62ac862d6a | |
| parent | 69fd110eb650ea7baa82158f3b89a7d86da1d056 (diff) | |
| parent | 653a7746fa2f5369985f5368ffc162b6510db6c8 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs pile two from Al Viro:
- orangefs fix
- series of fs/namei.c cleanups from me
- VFS stuff coming from overlayfs tree
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
orangefs: Use RCU for destroy_inode
vfs: use helper for calling f_op->fsync()
mm: use helper for calling f_op->mmap()
vfs: use helpers for calling f_op->{read,write}_iter()
vfs: pass type instead of fn to do_{loop,iter}_readv_writev()
vfs: extract common parts of {compat_,}do_readv_writev()
vfs: wrap write f_ops with file_{start,end}_write()
vfs: deny copy_file_range() for non regular files
vfs: deny fallocate() on directory
vfs: create vfs helper vfs_tmpfile()
namei.c: split unlazy_walk()
namei.c: fold the check for DCACHE_OP_REVALIDATE into d_revalidate()
lookup_fast(): clean up the logics around the fallback to non-rcu mode
namei: fold unlazy_link() into its sole caller
| -rw-r--r-- | drivers/block/loop.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem_dmabuf.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/vgem/vgem_drv.c | 2 | ||||
| -rw-r--r-- | fs/aio.c | 4 | ||||
| -rw-r--r-- | fs/coda/file.c | 2 | ||||
| -rw-r--r-- | fs/namei.c | 251 | ||||
| -rw-r--r-- | fs/open.c | 14 | ||||
| -rw-r--r-- | fs/orangefs/super.c | 9 | ||||
| -rw-r--r-- | fs/read_write.c | 130 | ||||
| -rw-r--r-- | fs/splice.c | 2 | ||||
| -rw-r--r-- | fs/sync.c | 2 | ||||
| -rw-r--r-- | include/linux/fs.h | 52 | ||||
| -rw-r--r-- | ipc/shm.c | 4 | ||||
| -rw-r--r-- | mm/mmap.c | 2 | ||||
| -rw-r--r-- | mm/nommu.c | 4 |
15 files changed, 261 insertions, 223 deletions
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 4b52a1690329..eeb1db73f44e 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
| @@ -501,9 +501,9 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd, | |||
| 501 | cmd->iocb.ki_flags = IOCB_DIRECT; | 501 | cmd->iocb.ki_flags = IOCB_DIRECT; |
| 502 | 502 | ||
| 503 | if (rw == WRITE) | 503 | if (rw == WRITE) |
| 504 | ret = file->f_op->write_iter(&cmd->iocb, &iter); | 504 | ret = call_write_iter(file, &cmd->iocb, &iter); |
| 505 | else | 505 | else |
| 506 | ret = file->f_op->read_iter(&cmd->iocb, &iter); | 506 | ret = call_read_iter(file, &cmd->iocb, &iter); |
| 507 | 507 | ||
| 508 | if (ret != -EIOCBQUEUED) | 508 | if (ret != -EIOCBQUEUED) |
| 509 | cmd->iocb.ki_complete(&cmd->iocb, ret, 0); | 509 | cmd->iocb.ki_complete(&cmd->iocb, ret, 0); |
diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c index d037adcda6f2..29bb8011dbc4 100644 --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c | |||
| @@ -141,7 +141,7 @@ static int i915_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct * | |||
| 141 | if (!obj->base.filp) | 141 | if (!obj->base.filp) |
| 142 | return -ENODEV; | 142 | return -ENODEV; |
| 143 | 143 | ||
| 144 | ret = obj->base.filp->f_op->mmap(obj->base.filp, vma); | 144 | ret = call_mmap(obj->base.filp, vma); |
| 145 | if (ret) | 145 | if (ret) |
| 146 | return ret; | 146 | return ret; |
| 147 | 147 | ||
diff --git a/drivers/gpu/drm/vgem/vgem_drv.c b/drivers/gpu/drm/vgem/vgem_drv.c index 7ccbb03e98de..a1f42d125e6e 100644 --- a/drivers/gpu/drm/vgem/vgem_drv.c +++ b/drivers/gpu/drm/vgem/vgem_drv.c | |||
| @@ -288,7 +288,7 @@ static int vgem_prime_mmap(struct drm_gem_object *obj, | |||
| 288 | if (!obj->filp) | 288 | if (!obj->filp) |
| 289 | return -ENODEV; | 289 | return -ENODEV; |
| 290 | 290 | ||
| 291 | ret = obj->filp->f_op->mmap(obj->filp, vma); | 291 | ret = call_mmap(obj->filp, vma); |
| 292 | if (ret) | 292 | if (ret) |
| 293 | return ret; | 293 | return ret; |
| 294 | 294 | ||
| @@ -1495,7 +1495,7 @@ static ssize_t aio_read(struct kiocb *req, struct iocb *iocb, bool vectored, | |||
| 1495 | return ret; | 1495 | return ret; |
| 1496 | ret = rw_verify_area(READ, file, &req->ki_pos, iov_iter_count(&iter)); | 1496 | ret = rw_verify_area(READ, file, &req->ki_pos, iov_iter_count(&iter)); |
| 1497 | if (!ret) | 1497 | if (!ret) |
| 1498 | ret = aio_ret(req, file->f_op->read_iter(req, &iter)); | 1498 | ret = aio_ret(req, call_read_iter(file, req, &iter)); |
| 1499 | kfree(iovec); | 1499 | kfree(iovec); |
| 1500 | return ret; | 1500 | return ret; |
| 1501 | } | 1501 | } |
| @@ -1520,7 +1520,7 @@ static ssize_t aio_write(struct kiocb *req, struct iocb *iocb, bool vectored, | |||
| 1520 | if (!ret) { | 1520 | if (!ret) { |
| 1521 | req->ki_flags |= IOCB_WRITE; | 1521 | req->ki_flags |= IOCB_WRITE; |
| 1522 | file_start_write(file); | 1522 | file_start_write(file); |
| 1523 | ret = aio_ret(req, file->f_op->write_iter(req, &iter)); | 1523 | ret = aio_ret(req, call_write_iter(file, req, &iter)); |
| 1524 | /* | 1524 | /* |
| 1525 | * We release freeze protection in aio_complete(). Fool lockdep | 1525 | * We release freeze protection in aio_complete(). Fool lockdep |
| 1526 | * by telling it the lock got released so that it doesn't | 1526 | * by telling it the lock got released so that it doesn't |
diff --git a/fs/coda/file.c b/fs/coda/file.c index 6e0154eb6fcc..9d956cd6d46f 100644 --- a/fs/coda/file.c +++ b/fs/coda/file.c | |||
| @@ -96,7 +96,7 @@ coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma) | |||
| 96 | cfi->cfi_mapcount++; | 96 | cfi->cfi_mapcount++; |
| 97 | spin_unlock(&cii->c_lock); | 97 | spin_unlock(&cii->c_lock); |
| 98 | 98 | ||
| 99 | return host_file->f_op->mmap(host_file, vma); | 99 | return call_mmap(host_file, vma); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | int coda_open(struct inode *coda_inode, struct file *coda_file) | 102 | int coda_open(struct inode *coda_inode, struct file *coda_file) |
diff --git a/fs/namei.c b/fs/namei.c index da689c9c005e..d41fab78798b 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -672,17 +672,15 @@ static bool legitimize_links(struct nameidata *nd) | |||
| 672 | /** | 672 | /** |
| 673 | * unlazy_walk - try to switch to ref-walk mode. | 673 | * unlazy_walk - try to switch to ref-walk mode. |
| 674 | * @nd: nameidata pathwalk data | 674 | * @nd: nameidata pathwalk data |
| 675 | * @dentry: child of nd->path.dentry or NULL | ||
| 676 | * @seq: seq number to check dentry against | ||
| 677 | * Returns: 0 on success, -ECHILD on failure | 675 | * Returns: 0 on success, -ECHILD on failure |
| 678 | * | 676 | * |
| 679 | * unlazy_walk attempts to legitimize the current nd->path, nd->root and dentry | 677 | * unlazy_walk attempts to legitimize the current nd->path and nd->root |
| 680 | * for ref-walk mode. @dentry must be a path found by a do_lookup call on | 678 | * for ref-walk mode. |
| 681 | * @nd or NULL. Must be called from rcu-walk context. | 679 | * Must be called from rcu-walk context. |
| 682 | * Nothing should touch nameidata between unlazy_walk() failure and | 680 | * Nothing should touch nameidata between unlazy_walk() failure and |
| 683 | * terminate_walk(). | 681 | * terminate_walk(). |
| 684 | */ | 682 | */ |
| 685 | static int unlazy_walk(struct nameidata *nd, struct dentry *dentry, unsigned seq) | 683 | static int unlazy_walk(struct nameidata *nd) |
| 686 | { | 684 | { |
| 687 | struct dentry *parent = nd->path.dentry; | 685 | struct dentry *parent = nd->path.dentry; |
| 688 | 686 | ||
| @@ -691,33 +689,66 @@ static int unlazy_walk(struct nameidata *nd, struct dentry *dentry, unsigned seq | |||
| 691 | nd->flags &= ~LOOKUP_RCU; | 689 | nd->flags &= ~LOOKUP_RCU; |
| 692 | if (unlikely(!legitimize_links(nd))) | 690 | if (unlikely(!legitimize_links(nd))) |
| 693 | goto out2; | 691 | goto out2; |
| 692 | if (unlikely(!legitimize_path(nd, &nd->path, nd->seq))) | ||
| 693 | goto out1; | ||
| 694 | if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT)) { | ||
| 695 | if (unlikely(!legitimize_path(nd, &nd->root, nd->root_seq))) | ||
| 696 | goto out; | ||
| 697 | } | ||
| 698 | rcu_read_unlock(); | ||
| 699 | BUG_ON(nd->inode != parent->d_inode); | ||
| 700 | return 0; | ||
| 701 | |||
| 702 | out2: | ||
| 703 | nd->path.mnt = NULL; | ||
| 704 | nd->path.dentry = NULL; | ||
| 705 | out1: | ||
| 706 | if (!(nd->flags & LOOKUP_ROOT)) | ||
| 707 | nd->root.mnt = NULL; | ||
| 708 | out: | ||
| 709 | rcu_read_unlock(); | ||
| 710 | return -ECHILD; | ||
| 711 | } | ||
| 712 | |||
| 713 | /** | ||
| 714 | * unlazy_child - try to switch to ref-walk mode. | ||
| 715 | * @nd: nameidata pathwalk data | ||
| 716 | * @dentry: child of nd->path.dentry | ||
| 717 | * @seq: seq number to check dentry against | ||
| 718 | * Returns: 0 on success, -ECHILD on failure | ||
| 719 | * | ||
| 720 | * unlazy_child attempts to legitimize the current nd->path, nd->root and dentry | ||
| 721 | * for ref-walk mode. @dentry must be a path found by a do_lookup call on | ||
| 722 | * @nd. Must be called from rcu-walk context. | ||
| 723 | * Nothing should touch nameidata between unlazy_child() failure and | ||
| 724 | * terminate_walk(). | ||
| 725 | */ | ||
| 726 | static int unlazy_child(struct nameidata *nd, struct dentry *dentry, unsigned seq) | ||
| 727 | { | ||
| 728 | BUG_ON(!(nd->flags & LOOKUP_RCU)); | ||
| 729 | |||
| 730 | nd->flags &= ~LOOKUP_RCU; | ||
| 731 | if (unlikely(!legitimize_links(nd))) | ||
| 732 | goto out2; | ||
| 694 | if (unlikely(!legitimize_mnt(nd->path.mnt, nd->m_seq))) | 733 | if (unlikely(!legitimize_mnt(nd->path.mnt, nd->m_seq))) |
| 695 | goto out2; | 734 | goto out2; |
| 696 | if (unlikely(!lockref_get_not_dead(&parent->d_lockref))) | 735 | if (unlikely(!lockref_get_not_dead(&nd->path.dentry->d_lockref))) |
| 697 | goto out1; | 736 | goto out1; |
| 698 | 737 | ||
| 699 | /* | 738 | /* |
| 700 | * For a negative lookup, the lookup sequence point is the parents | 739 | * We need to move both the parent and the dentry from the RCU domain |
| 701 | * sequence point, and it only needs to revalidate the parent dentry. | 740 | * to be properly refcounted. And the sequence number in the dentry |
| 702 | * | 741 | * validates *both* dentry counters, since we checked the sequence |
| 703 | * For a positive lookup, we need to move both the parent and the | 742 | * number of the parent after we got the child sequence number. So we |
| 704 | * dentry from the RCU domain to be properly refcounted. And the | 743 | * know the parent must still be valid if the child sequence number is |
| 705 | * sequence number in the dentry validates *both* dentry counters, | ||
| 706 | * since we checked the sequence number of the parent after we got | ||
| 707 | * the child sequence number. So we know the parent must still | ||
| 708 | * be valid if the child sequence number is still valid. | ||
| 709 | */ | 744 | */ |
| 710 | if (!dentry) { | 745 | if (unlikely(!lockref_get_not_dead(&dentry->d_lockref))) |
| 711 | if (read_seqcount_retry(&parent->d_seq, nd->seq)) | 746 | goto out; |
| 712 | goto out; | 747 | if (unlikely(read_seqcount_retry(&dentry->d_seq, seq))) { |
| 713 | BUG_ON(nd->inode != parent->d_inode); | 748 | rcu_read_unlock(); |
| 714 | } else { | 749 | dput(dentry); |
| 715 | if (!lockref_get_not_dead(&dentry->d_lockref)) | 750 | goto drop_root_mnt; |
| 716 | goto out; | ||
| 717 | if (read_seqcount_retry(&dentry->d_seq, seq)) | ||
| 718 | goto drop_dentry; | ||
| 719 | } | 751 | } |
| 720 | |||
| 721 | /* | 752 | /* |
| 722 | * Sequence counts matched. Now make sure that the root is | 753 | * Sequence counts matched. Now make sure that the root is |
| 723 | * still valid and get it if required. | 754 | * still valid and get it if required. |
| @@ -733,10 +764,6 @@ static int unlazy_walk(struct nameidata *nd, struct dentry *dentry, unsigned seq | |||
| 733 | rcu_read_unlock(); | 764 | rcu_read_unlock(); |
| 734 | return 0; | 765 | return 0; |
| 735 | 766 | ||
| 736 | drop_dentry: | ||
| 737 | rcu_read_unlock(); | ||
| 738 | dput(dentry); | ||
| 739 | goto drop_root_mnt; | ||
| 740 | out2: | 767 | out2: |
| 741 | nd->path.mnt = NULL; | 768 | nd->path.mnt = NULL; |
| 742 | out1: | 769 | out1: |
| @@ -749,27 +776,12 @@ drop_root_mnt: | |||
| 749 | return -ECHILD; | 776 | return -ECHILD; |
| 750 | } | 777 | } |
| 751 | 778 | ||
| 752 | static int unlazy_link(struct nameidata *nd, struct path *link, unsigned seq) | ||
| 753 | { | ||
| 754 | if (unlikely(!legitimize_path(nd, link, seq))) { | ||
| 755 | drop_links(nd); | ||
| 756 | nd->depth = 0; | ||
| 757 | nd->flags &= ~LOOKUP_RCU; | ||
| 758 | nd->path.mnt = NULL; | ||
| 759 | nd->path.dentry = NULL; | ||
| 760 | if (!(nd->flags & LOOKUP_ROOT)) | ||
| 761 | nd->root.mnt = NULL; | ||
| 762 | rcu_read_unlock(); | ||
| 763 | } else if (likely(unlazy_walk(nd, NULL, 0)) == 0) { | ||
| 764 | return 0; | ||
| 765 | } | ||
| 766 | path_put(link); | ||
| 767 | return -ECHILD; | ||
| 768 | } | ||
| 769 | |||
| 770 | static inline int d_revalidate(struct dentry *dentry, unsigned int flags) | 779 | static inline int d_revalidate(struct dentry *dentry, unsigned int flags) |
| 771 | { | 780 | { |
| 772 | return dentry->d_op->d_revalidate(dentry, flags); | 781 | if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) |
| 782 | return dentry->d_op->d_revalidate(dentry, flags); | ||
| 783 | else | ||
| 784 | return 1; | ||
| 773 | } | 785 | } |
| 774 | 786 | ||
| 775 | /** | 787 | /** |
| @@ -790,7 +802,7 @@ static int complete_walk(struct nameidata *nd) | |||
| 790 | if (nd->flags & LOOKUP_RCU) { | 802 | if (nd->flags & LOOKUP_RCU) { |
| 791 | if (!(nd->flags & LOOKUP_ROOT)) | 803 | if (!(nd->flags & LOOKUP_ROOT)) |
| 792 | nd->root.mnt = NULL; | 804 | nd->root.mnt = NULL; |
| 793 | if (unlikely(unlazy_walk(nd, NULL, 0))) | 805 | if (unlikely(unlazy_walk(nd))) |
| 794 | return -ECHILD; | 806 | return -ECHILD; |
| 795 | } | 807 | } |
| 796 | 808 | ||
| @@ -1016,7 +1028,7 @@ const char *get_link(struct nameidata *nd) | |||
| 1016 | touch_atime(&last->link); | 1028 | touch_atime(&last->link); |
| 1017 | cond_resched(); | 1029 | cond_resched(); |
| 1018 | } else if (atime_needs_update_rcu(&last->link, inode)) { | 1030 | } else if (atime_needs_update_rcu(&last->link, inode)) { |
| 1019 | if (unlikely(unlazy_walk(nd, NULL, 0))) | 1031 | if (unlikely(unlazy_walk(nd))) |
| 1020 | return ERR_PTR(-ECHILD); | 1032 | return ERR_PTR(-ECHILD); |
| 1021 | touch_atime(&last->link); | 1033 | touch_atime(&last->link); |
| 1022 | } | 1034 | } |
| @@ -1035,7 +1047,7 @@ const char *get_link(struct nameidata *nd) | |||
| 1035 | if (nd->flags & LOOKUP_RCU) { | 1047 | if (nd->flags & LOOKUP_RCU) { |
| 1036 | res = get(NULL, inode, &last->done); | 1048 | res = get(NULL, inode, &last->done); |
| 1037 | if (res == ERR_PTR(-ECHILD)) { | 1049 | if (res == ERR_PTR(-ECHILD)) { |
| 1038 | if (unlikely(unlazy_walk(nd, NULL, 0))) | 1050 | if (unlikely(unlazy_walk(nd))) |
| 1039 | return ERR_PTR(-ECHILD); | 1051 | return ERR_PTR(-ECHILD); |
| 1040 | res = get(dentry, inode, &last->done); | 1052 | res = get(dentry, inode, &last->done); |
| 1041 | } | 1053 | } |
| @@ -1469,19 +1481,14 @@ static struct dentry *lookup_dcache(const struct qstr *name, | |||
| 1469 | struct dentry *dir, | 1481 | struct dentry *dir, |
| 1470 | unsigned int flags) | 1482 | unsigned int flags) |
| 1471 | { | 1483 | { |
| 1472 | struct dentry *dentry; | 1484 | struct dentry *dentry = d_lookup(dir, name); |
| 1473 | int error; | ||
| 1474 | |||
| 1475 | dentry = d_lookup(dir, name); | ||
| 1476 | if (dentry) { | 1485 | if (dentry) { |
| 1477 | if (dentry->d_flags & DCACHE_OP_REVALIDATE) { | 1486 | int error = d_revalidate(dentry, flags); |
| 1478 | error = d_revalidate(dentry, flags); | 1487 | if (unlikely(error <= 0)) { |
| 1479 | if (unlikely(error <= 0)) { | 1488 | if (!error) |
| 1480 | if (!error) | 1489 | d_invalidate(dentry); |
| 1481 | d_invalidate(dentry); | 1490 | dput(dentry); |
| 1482 | dput(dentry); | 1491 | return ERR_PTR(error); |
| 1483 | return ERR_PTR(error); | ||
| 1484 | } | ||
| 1485 | } | 1492 | } |
| 1486 | } | 1493 | } |
| 1487 | return dentry; | 1494 | return dentry; |
| @@ -1546,7 +1553,7 @@ static int lookup_fast(struct nameidata *nd, | |||
| 1546 | bool negative; | 1553 | bool negative; |
| 1547 | dentry = __d_lookup_rcu(parent, &nd->last, &seq); | 1554 | dentry = __d_lookup_rcu(parent, &nd->last, &seq); |
| 1548 | if (unlikely(!dentry)) { | 1555 | if (unlikely(!dentry)) { |
| 1549 | if (unlazy_walk(nd, NULL, 0)) | 1556 | if (unlazy_walk(nd)) |
| 1550 | return -ECHILD; | 1557 | return -ECHILD; |
| 1551 | return 0; | 1558 | return 0; |
| 1552 | } | 1559 | } |
| @@ -1571,14 +1578,8 @@ static int lookup_fast(struct nameidata *nd, | |||
| 1571 | return -ECHILD; | 1578 | return -ECHILD; |
| 1572 | 1579 | ||
| 1573 | *seqp = seq; | 1580 | *seqp = seq; |
| 1574 | if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) | 1581 | status = d_revalidate(dentry, nd->flags); |
| 1575 | status = d_revalidate(dentry, nd->flags); | 1582 | if (likely(status > 0)) { |
| 1576 | if (unlikely(status <= 0)) { | ||
| 1577 | if (unlazy_walk(nd, dentry, seq)) | ||
| 1578 | return -ECHILD; | ||
| 1579 | if (status == -ECHILD) | ||
| 1580 | status = d_revalidate(dentry, nd->flags); | ||
| 1581 | } else { | ||
| 1582 | /* | 1583 | /* |
| 1583 | * Note: do negative dentry check after revalidation in | 1584 | * Note: do negative dentry check after revalidation in |
| 1584 | * case that drops it. | 1585 | * case that drops it. |
| @@ -1589,15 +1590,17 @@ static int lookup_fast(struct nameidata *nd, | |||
| 1589 | path->dentry = dentry; | 1590 | path->dentry = dentry; |
| 1590 | if (likely(__follow_mount_rcu(nd, path, inode, seqp))) | 1591 | if (likely(__follow_mount_rcu(nd, path, inode, seqp))) |
| 1591 | return 1; | 1592 | return 1; |
| 1592 | if (unlazy_walk(nd, dentry, seq)) | ||
| 1593 | return -ECHILD; | ||
| 1594 | } | 1593 | } |
| 1594 | if (unlazy_child(nd, dentry, seq)) | ||
| 1595 | return -ECHILD; | ||
| 1596 | if (unlikely(status == -ECHILD)) | ||
| 1597 | /* we'd been told to redo it in non-rcu mode */ | ||
| 1598 | status = d_revalidate(dentry, nd->flags); | ||
| 1595 | } else { | 1599 | } else { |
| 1596 | dentry = __d_lookup(parent, &nd->last); | 1600 | dentry = __d_lookup(parent, &nd->last); |
| 1597 | if (unlikely(!dentry)) | 1601 | if (unlikely(!dentry)) |
| 1598 | return 0; | 1602 | return 0; |
| 1599 | if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) | 1603 | status = d_revalidate(dentry, nd->flags); |
| 1600 | status = d_revalidate(dentry, nd->flags); | ||
| 1601 | } | 1604 | } |
| 1602 | if (unlikely(status <= 0)) { | 1605 | if (unlikely(status <= 0)) { |
| 1603 | if (!status) | 1606 | if (!status) |
| @@ -1636,8 +1639,7 @@ again: | |||
| 1636 | if (IS_ERR(dentry)) | 1639 | if (IS_ERR(dentry)) |
| 1637 | goto out; | 1640 | goto out; |
| 1638 | if (unlikely(!d_in_lookup(dentry))) { | 1641 | if (unlikely(!d_in_lookup(dentry))) { |
| 1639 | if ((dentry->d_flags & DCACHE_OP_REVALIDATE) && | 1642 | if (!(flags & LOOKUP_NO_REVAL)) { |
| 1640 | !(flags & LOOKUP_NO_REVAL)) { | ||
| 1641 | int error = d_revalidate(dentry, flags); | 1643 | int error = d_revalidate(dentry, flags); |
| 1642 | if (unlikely(error <= 0)) { | 1644 | if (unlikely(error <= 0)) { |
| 1643 | if (!error) { | 1645 | if (!error) { |
| @@ -1668,7 +1670,7 @@ static inline int may_lookup(struct nameidata *nd) | |||
| 1668 | int err = inode_permission(nd->inode, MAY_EXEC|MAY_NOT_BLOCK); | 1670 | int err = inode_permission(nd->inode, MAY_EXEC|MAY_NOT_BLOCK); |
| 1669 | if (err != -ECHILD) | 1671 | if (err != -ECHILD) |
| 1670 | return err; | 1672 | return err; |
| 1671 | if (unlazy_walk(nd, NULL, 0)) | 1673 | if (unlazy_walk(nd)) |
| 1672 | return -ECHILD; | 1674 | return -ECHILD; |
| 1673 | } | 1675 | } |
| 1674 | return inode_permission(nd->inode, MAY_EXEC); | 1676 | return inode_permission(nd->inode, MAY_EXEC); |
| @@ -1703,9 +1705,17 @@ static int pick_link(struct nameidata *nd, struct path *link, | |||
| 1703 | error = nd_alloc_stack(nd); | 1705 | error = nd_alloc_stack(nd); |
| 1704 | if (unlikely(error)) { | 1706 | if (unlikely(error)) { |
| 1705 | if (error == -ECHILD) { | 1707 | if (error == -ECHILD) { |
| 1706 | if (unlikely(unlazy_link(nd, link, seq))) | 1708 | if (unlikely(!legitimize_path(nd, link, seq))) { |
| 1707 | return -ECHILD; | 1709 | drop_links(nd); |
| 1708 | error = nd_alloc_stack(nd); | 1710 | nd->depth = 0; |
| 1711 | nd->flags &= ~LOOKUP_RCU; | ||
| 1712 | nd->path.mnt = NULL; | ||
| 1713 | nd->path.dentry = NULL; | ||
| 1714 | if (!(nd->flags & LOOKUP_ROOT)) | ||
| 1715 | nd->root.mnt = NULL; | ||
| 1716 | rcu_read_unlock(); | ||
| 1717 | } else if (likely(unlazy_walk(nd)) == 0) | ||
| 1718 | error = nd_alloc_stack(nd); | ||
| 1709 | } | 1719 | } |
| 1710 | if (error) { | 1720 | if (error) { |
| 1711 | path_put(link); | 1721 | path_put(link); |
| @@ -2122,7 +2132,7 @@ OK: | |||
| 2122 | } | 2132 | } |
| 2123 | if (unlikely(!d_can_lookup(nd->path.dentry))) { | 2133 | if (unlikely(!d_can_lookup(nd->path.dentry))) { |
| 2124 | if (nd->flags & LOOKUP_RCU) { | 2134 | if (nd->flags & LOOKUP_RCU) { |
| 2125 | if (unlazy_walk(nd, NULL, 0)) | 2135 | if (unlazy_walk(nd)) |
| 2126 | return -ECHILD; | 2136 | return -ECHILD; |
| 2127 | } | 2137 | } |
| 2128 | return -ENOTDIR; | 2138 | return -ENOTDIR; |
| @@ -2579,7 +2589,7 @@ mountpoint_last(struct nameidata *nd) | |||
| 2579 | 2589 | ||
| 2580 | /* If we're in rcuwalk, drop out of it to handle last component */ | 2590 | /* If we're in rcuwalk, drop out of it to handle last component */ |
| 2581 | if (nd->flags & LOOKUP_RCU) { | 2591 | if (nd->flags & LOOKUP_RCU) { |
| 2582 | if (unlazy_walk(nd, NULL, 0)) | 2592 | if (unlazy_walk(nd)) |
| 2583 | return -ECHILD; | 2593 | return -ECHILD; |
| 2584 | } | 2594 | } |
| 2585 | 2595 | ||
| @@ -3072,9 +3082,6 @@ static int lookup_open(struct nameidata *nd, struct path *path, | |||
| 3072 | if (d_in_lookup(dentry)) | 3082 | if (d_in_lookup(dentry)) |
| 3073 | break; | 3083 | break; |
| 3074 | 3084 | ||
| 3075 | if (!(dentry->d_flags & DCACHE_OP_REVALIDATE)) | ||
| 3076 | break; | ||
| 3077 | |||
| 3078 | error = d_revalidate(dentry, nd->flags); | 3085 | error = d_revalidate(dentry, nd->flags); |
| 3079 | if (likely(error > 0)) | 3086 | if (likely(error > 0)) |
| 3080 | break; | 3087 | break; |
| @@ -3356,13 +3363,50 @@ out: | |||
| 3356 | return error; | 3363 | return error; |
| 3357 | } | 3364 | } |
| 3358 | 3365 | ||
| 3366 | struct dentry *vfs_tmpfile(struct dentry *dentry, umode_t mode, int open_flag) | ||
| 3367 | { | ||
| 3368 | static const struct qstr name = QSTR_INIT("/", 1); | ||
| 3369 | struct dentry *child = NULL; | ||
| 3370 | struct inode *dir = dentry->d_inode; | ||
| 3371 | struct inode *inode; | ||
| 3372 | int error; | ||
| 3373 | |||
| 3374 | /* we want directory to be writable */ | ||
| 3375 | error = inode_permission(dir, MAY_WRITE | MAY_EXEC); | ||
| 3376 | if (error) | ||
| 3377 | goto out_err; | ||
| 3378 | error = -EOPNOTSUPP; | ||
| 3379 | if (!dir->i_op->tmpfile) | ||
| 3380 | goto out_err; | ||
| 3381 | error = -ENOMEM; | ||
| 3382 | child = d_alloc(dentry, &name); | ||
| 3383 | if (unlikely(!child)) | ||
| 3384 | goto out_err; | ||
| 3385 | error = dir->i_op->tmpfile(dir, child, mode); | ||
| 3386 | if (error) | ||
| 3387 | goto out_err; | ||
| 3388 | error = -ENOENT; | ||
| 3389 | inode = child->d_inode; | ||
| 3390 | if (unlikely(!inode)) | ||
| 3391 | goto out_err; | ||
| 3392 | if (!(open_flag & O_EXCL)) { | ||
| 3393 | spin_lock(&inode->i_lock); | ||
| 3394 | inode->i_state |= I_LINKABLE; | ||
| 3395 | spin_unlock(&inode->i_lock); | ||
| 3396 | } | ||
| 3397 | return child; | ||
| 3398 | |||
| 3399 | out_err: | ||
| 3400 | dput(child); | ||
| 3401 | return ERR_PTR(error); | ||
| 3402 | } | ||
| 3403 | EXPORT_SYMBOL(vfs_tmpfile); | ||
| 3404 | |||
| 3359 | static int do_tmpfile(struct nameidata *nd, unsigned flags, | 3405 | static int do_tmpfile(struct nameidata *nd, unsigned flags, |
| 3360 | const struct open_flags *op, | 3406 | const struct open_flags *op, |
| 3361 | struct file *file, int *opened) | 3407 | struct file *file, int *opened) |
| 3362 | { | 3408 | { |
| 3363 | static const struct qstr name = QSTR_INIT("/", 1); | ||
| 3364 | struct dentry *child; | 3409 | struct dentry *child; |
| 3365 | struct inode *dir; | ||
| 3366 | struct path path; | 3410 | struct path path; |
| 3367 | int error = path_lookupat(nd, flags | LOOKUP_DIRECTORY, &path); | 3411 | int error = path_lookupat(nd, flags | LOOKUP_DIRECTORY, &path); |
| 3368 | if (unlikely(error)) | 3412 | if (unlikely(error)) |
| @@ -3370,25 +3414,12 @@ static int do_tmpfile(struct nameidata *nd, unsigned flags, | |||
| 3370 | error = mnt_want_write(path.mnt); | 3414 | error = mnt_want_write(path.mnt); |
| 3371 | if (unlikely(error)) | 3415 | if (unlikely(error)) |
| 3372 | goto out; | 3416 | goto out; |
| 3373 | dir = path.dentry->d_inode; | 3417 | child = vfs_tmpfile(path.dentry, op->mode, op->open_flag); |
| 3374 | /* we want directory to be writable */ | 3418 | error = PTR_ERR(child); |
| 3375 | error = inode_permission(dir, MAY_WRITE | MAY_EXEC); | 3419 | if (unlikely(IS_ERR(child))) |
| 3376 | if (error) | ||
| 3377 | goto out2; | 3420 | goto out2; |
| 3378 | if (!dir->i_op->tmpfile) { | ||
| 3379 | error = -EOPNOTSUPP; | ||
| 3380 | goto out2; | ||
| 3381 | } | ||
| 3382 | child = d_alloc(path.dentry, &name); | ||
| 3383 | if (unlikely(!child)) { | ||
| 3384 | error = -ENOMEM; | ||
| 3385 | goto out2; | ||
| 3386 | } | ||
| 3387 | dput(path.dentry); | 3421 | dput(path.dentry); |
| 3388 | path.dentry = child; | 3422 | path.dentry = child; |
| 3389 | error = dir->i_op->tmpfile(dir, child, op->mode); | ||
| 3390 | if (error) | ||
| 3391 | goto out2; | ||
| 3392 | audit_inode(nd->name, child, 0); | 3423 | audit_inode(nd->name, child, 0); |
| 3393 | /* Don't check for other permissions, the inode was just created */ | 3424 | /* Don't check for other permissions, the inode was just created */ |
| 3394 | error = may_open(&path, 0, op->open_flag); | 3425 | error = may_open(&path, 0, op->open_flag); |
| @@ -3399,14 +3430,8 @@ static int do_tmpfile(struct nameidata *nd, unsigned flags, | |||
| 3399 | if (error) | 3430 | if (error) |
| 3400 | goto out2; | 3431 | goto out2; |
| 3401 | error = open_check_o_direct(file); | 3432 | error = open_check_o_direct(file); |
| 3402 | if (error) { | 3433 | if (error) |
| 3403 | fput(file); | 3434 | fput(file); |
| 3404 | } else if (!(op->open_flag & O_EXCL)) { | ||
| 3405 | struct inode *inode = file_inode(file); | ||
| 3406 | spin_lock(&inode->i_lock); | ||
| 3407 | inode->i_state |= I_LINKABLE; | ||
| 3408 | spin_unlock(&inode->i_lock); | ||
| 3409 | } | ||
| 3410 | out2: | 3435 | out2: |
| 3411 | mnt_drop_write(path.mnt); | 3436 | mnt_drop_write(path.mnt); |
| 3412 | out: | 3437 | out: |
| @@ -301,12 +301,10 @@ int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len) | |||
| 301 | if (S_ISFIFO(inode->i_mode)) | 301 | if (S_ISFIFO(inode->i_mode)) |
| 302 | return -ESPIPE; | 302 | return -ESPIPE; |
| 303 | 303 | ||
| 304 | /* | 304 | if (S_ISDIR(inode->i_mode)) |
| 305 | * Let individual file system decide if it supports preallocation | 305 | return -EISDIR; |
| 306 | * for directories or not. | 306 | |
| 307 | */ | 307 | if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode)) |
| 308 | if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode) && | ||
| 309 | !S_ISBLK(inode->i_mode)) | ||
| 310 | return -ENODEV; | 308 | return -ENODEV; |
| 311 | 309 | ||
| 312 | /* Check for wrap through zero too */ | 310 | /* Check for wrap through zero too */ |
| @@ -316,7 +314,7 @@ int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len) | |||
| 316 | if (!file->f_op->fallocate) | 314 | if (!file->f_op->fallocate) |
| 317 | return -EOPNOTSUPP; | 315 | return -EOPNOTSUPP; |
| 318 | 316 | ||
| 319 | sb_start_write(inode->i_sb); | 317 | file_start_write(file); |
| 320 | ret = file->f_op->fallocate(file, mode, offset, len); | 318 | ret = file->f_op->fallocate(file, mode, offset, len); |
| 321 | 319 | ||
| 322 | /* | 320 | /* |
| @@ -329,7 +327,7 @@ int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len) | |||
| 329 | if (ret == 0) | 327 | if (ret == 0) |
| 330 | fsnotify_modify(file); | 328 | fsnotify_modify(file); |
| 331 | 329 | ||
| 332 | sb_end_write(inode->i_sb); | 330 | file_end_write(file); |
| 333 | return ret; | 331 | return ret; |
| 334 | } | 332 | } |
| 335 | EXPORT_SYMBOL_GPL(vfs_fallocate); | 333 | EXPORT_SYMBOL_GPL(vfs_fallocate); |
diff --git a/fs/orangefs/super.c b/fs/orangefs/super.c index c48859f16e7b..67c24351a67f 100644 --- a/fs/orangefs/super.c +++ b/fs/orangefs/super.c | |||
| @@ -115,6 +115,13 @@ static struct inode *orangefs_alloc_inode(struct super_block *sb) | |||
| 115 | return &orangefs_inode->vfs_inode; | 115 | return &orangefs_inode->vfs_inode; |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | static void orangefs_i_callback(struct rcu_head *head) | ||
| 119 | { | ||
| 120 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
| 121 | struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); | ||
| 122 | kmem_cache_free(orangefs_inode_cache, orangefs_inode); | ||
| 123 | } | ||
| 124 | |||
| 118 | static void orangefs_destroy_inode(struct inode *inode) | 125 | static void orangefs_destroy_inode(struct inode *inode) |
| 119 | { | 126 | { |
| 120 | struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); | 127 | struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); |
| @@ -123,7 +130,7 @@ static void orangefs_destroy_inode(struct inode *inode) | |||
| 123 | "%s: deallocated %p destroying inode %pU\n", | 130 | "%s: deallocated %p destroying inode %pU\n", |
| 124 | __func__, orangefs_inode, get_khandle_from_ino(inode)); | 131 | __func__, orangefs_inode, get_khandle_from_ino(inode)); |
| 125 | 132 | ||
| 126 | kmem_cache_free(orangefs_inode_cache, orangefs_inode); | 133 | call_rcu(&inode->i_rcu, orangefs_i_callback); |
| 127 | } | 134 | } |
| 128 | 135 | ||
| 129 | /* | 136 | /* |
diff --git a/fs/read_write.c b/fs/read_write.c index 5816d4c4cab0..f2ed9fdc98fd 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
| @@ -23,9 +23,6 @@ | |||
| 23 | #include <linux/uaccess.h> | 23 | #include <linux/uaccess.h> |
| 24 | #include <asm/unistd.h> | 24 | #include <asm/unistd.h> |
| 25 | 25 | ||
| 26 | typedef ssize_t (*io_fn_t)(struct file *, char __user *, size_t, loff_t *); | ||
| 27 | typedef ssize_t (*iter_fn_t)(struct kiocb *, struct iov_iter *); | ||
| 28 | |||
| 29 | const struct file_operations generic_ro_fops = { | 26 | const struct file_operations generic_ro_fops = { |
| 30 | .llseek = generic_file_llseek, | 27 | .llseek = generic_file_llseek, |
| 31 | .read_iter = generic_file_read_iter, | 28 | .read_iter = generic_file_read_iter, |
| @@ -370,7 +367,7 @@ ssize_t vfs_iter_read(struct file *file, struct iov_iter *iter, loff_t *ppos) | |||
| 370 | kiocb.ki_pos = *ppos; | 367 | kiocb.ki_pos = *ppos; |
| 371 | 368 | ||
| 372 | iter->type |= READ; | 369 | iter->type |= READ; |
| 373 | ret = file->f_op->read_iter(&kiocb, iter); | 370 | ret = call_read_iter(file, &kiocb, iter); |
| 374 | BUG_ON(ret == -EIOCBQUEUED); | 371 | BUG_ON(ret == -EIOCBQUEUED); |
| 375 | if (ret > 0) | 372 | if (ret > 0) |
| 376 | *ppos = kiocb.ki_pos; | 373 | *ppos = kiocb.ki_pos; |
| @@ -390,7 +387,7 @@ ssize_t vfs_iter_write(struct file *file, struct iov_iter *iter, loff_t *ppos) | |||
| 390 | kiocb.ki_pos = *ppos; | 387 | kiocb.ki_pos = *ppos; |
| 391 | 388 | ||
| 392 | iter->type |= WRITE; | 389 | iter->type |= WRITE; |
| 393 | ret = file->f_op->write_iter(&kiocb, iter); | 390 | ret = call_write_iter(file, &kiocb, iter); |
| 394 | BUG_ON(ret == -EIOCBQUEUED); | 391 | BUG_ON(ret == -EIOCBQUEUED); |
| 395 | if (ret > 0) | 392 | if (ret > 0) |
| 396 | *ppos = kiocb.ki_pos; | 393 | *ppos = kiocb.ki_pos; |
| @@ -439,7 +436,7 @@ static ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, lo | |||
| 439 | kiocb.ki_pos = *ppos; | 436 | kiocb.ki_pos = *ppos; |
| 440 | iov_iter_init(&iter, READ, &iov, 1, len); | 437 | iov_iter_init(&iter, READ, &iov, 1, len); |
| 441 | 438 | ||
| 442 | ret = filp->f_op->read_iter(&kiocb, &iter); | 439 | ret = call_read_iter(filp, &kiocb, &iter); |
| 443 | BUG_ON(ret == -EIOCBQUEUED); | 440 | BUG_ON(ret == -EIOCBQUEUED); |
| 444 | *ppos = kiocb.ki_pos; | 441 | *ppos = kiocb.ki_pos; |
| 445 | return ret; | 442 | return ret; |
| @@ -496,7 +493,7 @@ static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t | |||
| 496 | kiocb.ki_pos = *ppos; | 493 | kiocb.ki_pos = *ppos; |
| 497 | iov_iter_init(&iter, WRITE, &iov, 1, len); | 494 | iov_iter_init(&iter, WRITE, &iov, 1, len); |
| 498 | 495 | ||
| 499 | ret = filp->f_op->write_iter(&kiocb, &iter); | 496 | ret = call_write_iter(filp, &kiocb, &iter); |
| 500 | BUG_ON(ret == -EIOCBQUEUED); | 497 | BUG_ON(ret == -EIOCBQUEUED); |
| 501 | if (ret > 0) | 498 | if (ret > 0) |
| 502 | *ppos = kiocb.ki_pos; | 499 | *ppos = kiocb.ki_pos; |
| @@ -675,7 +672,7 @@ unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to) | |||
| 675 | EXPORT_SYMBOL(iov_shorten); | 672 | EXPORT_SYMBOL(iov_shorten); |
| 676 | 673 | ||
| 677 | static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter, | 674 | static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter, |
| 678 | loff_t *ppos, iter_fn_t fn, int flags) | 675 | loff_t *ppos, int type, int flags) |
| 679 | { | 676 | { |
| 680 | struct kiocb kiocb; | 677 | struct kiocb kiocb; |
| 681 | ssize_t ret; | 678 | ssize_t ret; |
| @@ -692,7 +689,10 @@ static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter, | |||
| 692 | kiocb.ki_flags |= (IOCB_DSYNC | IOCB_SYNC); | 689 | kiocb.ki_flags |= (IOCB_DSYNC | IOCB_SYNC); |
| 693 | kiocb.ki_pos = *ppos; | 690 | kiocb.ki_pos = *ppos; |
| 694 | 691 | ||
| 695 | ret = fn(&kiocb, iter); | 692 | if (type == READ) |
| 693 | ret = call_read_iter(filp, &kiocb, iter); | ||
| 694 | else | ||
| 695 | ret = call_write_iter(filp, &kiocb, iter); | ||
| 696 | BUG_ON(ret == -EIOCBQUEUED); | 696 | BUG_ON(ret == -EIOCBQUEUED); |
| 697 | *ppos = kiocb.ki_pos; | 697 | *ppos = kiocb.ki_pos; |
| 698 | return ret; | 698 | return ret; |
| @@ -700,7 +700,7 @@ static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter, | |||
| 700 | 700 | ||
| 701 | /* Do it by hand, with file-ops */ | 701 | /* Do it by hand, with file-ops */ |
| 702 | static ssize_t do_loop_readv_writev(struct file *filp, struct iov_iter *iter, | 702 | static ssize_t do_loop_readv_writev(struct file *filp, struct iov_iter *iter, |
| 703 | loff_t *ppos, io_fn_t fn, int flags) | 703 | loff_t *ppos, int type, int flags) |
| 704 | { | 704 | { |
| 705 | ssize_t ret = 0; | 705 | ssize_t ret = 0; |
| 706 | 706 | ||
| @@ -711,7 +711,13 @@ static ssize_t do_loop_readv_writev(struct file *filp, struct iov_iter *iter, | |||
| 711 | struct iovec iovec = iov_iter_iovec(iter); | 711 | struct iovec iovec = iov_iter_iovec(iter); |
| 712 | ssize_t nr; | 712 | ssize_t nr; |
| 713 | 713 | ||
| 714 | nr = fn(filp, iovec.iov_base, iovec.iov_len, ppos); | 714 | if (type == READ) { |
| 715 | nr = filp->f_op->read(filp, iovec.iov_base, | ||
| 716 | iovec.iov_len, ppos); | ||
| 717 | } else { | ||
| 718 | nr = filp->f_op->write(filp, iovec.iov_base, | ||
| 719 | iovec.iov_len, ppos); | ||
| 720 | } | ||
| 715 | 721 | ||
| 716 | if (nr < 0) { | 722 | if (nr < 0) { |
| 717 | if (!ret) | 723 | if (!ret) |
| @@ -834,50 +840,32 @@ out: | |||
| 834 | return ret; | 840 | return ret; |
| 835 | } | 841 | } |
| 836 | 842 | ||
| 837 | static ssize_t do_readv_writev(int type, struct file *file, | 843 | static ssize_t __do_readv_writev(int type, struct file *file, |
| 838 | const struct iovec __user * uvector, | 844 | struct iov_iter *iter, loff_t *pos, int flags) |
| 839 | unsigned long nr_segs, loff_t *pos, | ||
| 840 | int flags) | ||
| 841 | { | 845 | { |
| 842 | size_t tot_len; | 846 | size_t tot_len; |
| 843 | struct iovec iovstack[UIO_FASTIOV]; | 847 | ssize_t ret = 0; |
| 844 | struct iovec *iov = iovstack; | ||
| 845 | struct iov_iter iter; | ||
| 846 | ssize_t ret; | ||
| 847 | io_fn_t fn; | ||
| 848 | iter_fn_t iter_fn; | ||
| 849 | |||
| 850 | ret = import_iovec(type, uvector, nr_segs, | ||
| 851 | ARRAY_SIZE(iovstack), &iov, &iter); | ||
| 852 | if (ret < 0) | ||
| 853 | return ret; | ||
| 854 | 848 | ||
| 855 | tot_len = iov_iter_count(&iter); | 849 | tot_len = iov_iter_count(iter); |
| 856 | if (!tot_len) | 850 | if (!tot_len) |
| 857 | goto out; | 851 | goto out; |
| 858 | ret = rw_verify_area(type, file, pos, tot_len); | 852 | ret = rw_verify_area(type, file, pos, tot_len); |
| 859 | if (ret < 0) | 853 | if (ret < 0) |
| 860 | goto out; | 854 | goto out; |
| 861 | 855 | ||
| 862 | if (type == READ) { | 856 | if (type != READ) |
| 863 | fn = file->f_op->read; | ||
| 864 | iter_fn = file->f_op->read_iter; | ||
| 865 | } else { | ||
| 866 | fn = (io_fn_t)file->f_op->write; | ||
| 867 | iter_fn = file->f_op->write_iter; | ||
| 868 | file_start_write(file); | 857 | file_start_write(file); |
| 869 | } | ||
| 870 | 858 | ||
| 871 | if (iter_fn) | 859 | if ((type == READ && file->f_op->read_iter) || |
| 872 | ret = do_iter_readv_writev(file, &iter, pos, iter_fn, flags); | 860 | (type == WRITE && file->f_op->write_iter)) |
| 861 | ret = do_iter_readv_writev(file, iter, pos, type, flags); | ||
| 873 | else | 862 | else |
| 874 | ret = do_loop_readv_writev(file, &iter, pos, fn, flags); | 863 | ret = do_loop_readv_writev(file, iter, pos, type, flags); |
| 875 | 864 | ||
| 876 | if (type != READ) | 865 | if (type != READ) |
| 877 | file_end_write(file); | 866 | file_end_write(file); |
| 878 | 867 | ||
| 879 | out: | 868 | out: |
| 880 | kfree(iov); | ||
| 881 | if ((ret + (type == READ)) > 0) { | 869 | if ((ret + (type == READ)) > 0) { |
| 882 | if (type == READ) | 870 | if (type == READ) |
| 883 | fsnotify_access(file); | 871 | fsnotify_access(file); |
| @@ -887,6 +875,27 @@ out: | |||
| 887 | return ret; | 875 | return ret; |
| 888 | } | 876 | } |
| 889 | 877 | ||
| 878 | static ssize_t do_readv_writev(int type, struct file *file, | ||
| 879 | const struct iovec __user *uvector, | ||
| 880 | unsigned long nr_segs, loff_t *pos, | ||
| 881 | int flags) | ||
| 882 | { | ||
| 883 | struct iovec iovstack[UIO_FASTIOV]; | ||
| 884 | struct iovec *iov = iovstack; | ||
| 885 | struct iov_iter iter; | ||
| 886 | ssize_t ret; | ||
| 887 | |||
| 888 | ret = import_iovec(type, uvector, nr_segs, | ||
| 889 | ARRAY_SIZE(iovstack), &iov, &iter); | ||
| 890 | if (ret < 0) | ||
| 891 | return ret; | ||
| 892 | |||
| 893 | ret = __do_readv_writev(type, file, &iter, pos, flags); | ||
| 894 | kfree(iov); | ||
| 895 | |||
| 896 | return ret; | ||
| 897 | } | ||
| 898 | |||
| 890 | ssize_t vfs_readv(struct file *file, const struct iovec __user *vec, | 899 | ssize_t vfs_readv(struct file *file, const struct iovec __user *vec, |
| 891 | unsigned long vlen, loff_t *pos, int flags) | 900 | unsigned long vlen, loff_t *pos, int flags) |
| 892 | { | 901 | { |
| @@ -1064,51 +1073,19 @@ static ssize_t compat_do_readv_writev(int type, struct file *file, | |||
| 1064 | unsigned long nr_segs, loff_t *pos, | 1073 | unsigned long nr_segs, loff_t *pos, |
| 1065 | int flags) | 1074 | int flags) |
| 1066 | { | 1075 | { |
| 1067 | compat_ssize_t tot_len; | ||
| 1068 | struct iovec iovstack[UIO_FASTIOV]; | 1076 | struct iovec iovstack[UIO_FASTIOV]; |
| 1069 | struct iovec *iov = iovstack; | 1077 | struct iovec *iov = iovstack; |
| 1070 | struct iov_iter iter; | 1078 | struct iov_iter iter; |
| 1071 | ssize_t ret; | 1079 | ssize_t ret; |
| 1072 | io_fn_t fn; | ||
| 1073 | iter_fn_t iter_fn; | ||
| 1074 | 1080 | ||
| 1075 | ret = compat_import_iovec(type, uvector, nr_segs, | 1081 | ret = compat_import_iovec(type, uvector, nr_segs, |
| 1076 | UIO_FASTIOV, &iov, &iter); | 1082 | UIO_FASTIOV, &iov, &iter); |
| 1077 | if (ret < 0) | 1083 | if (ret < 0) |
| 1078 | return ret; | 1084 | return ret; |
| 1079 | 1085 | ||
| 1080 | tot_len = iov_iter_count(&iter); | 1086 | ret = __do_readv_writev(type, file, &iter, pos, flags); |
| 1081 | if (!tot_len) | ||
| 1082 | goto out; | ||
| 1083 | ret = rw_verify_area(type, file, pos, tot_len); | ||
| 1084 | if (ret < 0) | ||
| 1085 | goto out; | ||
| 1086 | |||
| 1087 | if (type == READ) { | ||
| 1088 | fn = file->f_op->read; | ||
| 1089 | iter_fn = file->f_op->read_iter; | ||
| 1090 | } else { | ||
| 1091 | fn = (io_fn_t)file->f_op->write; | ||
| 1092 | iter_fn = file->f_op->write_iter; | ||
| 1093 | file_start_write(file); | ||
| 1094 | } | ||
| 1095 | |||
| 1096 | if (iter_fn) | ||
| 1097 | ret = do_iter_readv_writev(file, &iter, pos, iter_fn, flags); | ||
| 1098 | else | ||
| 1099 | ret = do_loop_readv_writev(file, &iter, pos, fn, flags); | ||
| 1100 | |||
| 1101 | if (type != READ) | ||
| 1102 | file_end_write(file); | ||
| 1103 | |||
| 1104 | out: | ||
| 1105 | kfree(iov); | 1087 | kfree(iov); |
| 1106 | if ((ret + (type == READ)) > 0) { | 1088 | |
| 1107 | if (type == READ) | ||
| 1108 | fsnotify_access(file); | ||
| 1109 | else | ||
| 1110 | fsnotify_modify(file); | ||
| 1111 | } | ||
| 1112 | return ret; | 1089 | return ret; |
| 1113 | } | 1090 | } |
| 1114 | 1091 | ||
| @@ -1518,6 +1495,11 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in, | |||
| 1518 | if (flags != 0) | 1495 | if (flags != 0) |
| 1519 | return -EINVAL; | 1496 | return -EINVAL; |
| 1520 | 1497 | ||
| 1498 | if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode)) | ||
| 1499 | return -EISDIR; | ||
| 1500 | if (!S_ISREG(inode_in->i_mode) || !S_ISREG(inode_out->i_mode)) | ||
| 1501 | return -EINVAL; | ||
| 1502 | |||
| 1521 | ret = rw_verify_area(READ, file_in, &pos_in, len); | 1503 | ret = rw_verify_area(READ, file_in, &pos_in, len); |
| 1522 | if (unlikely(ret)) | 1504 | if (unlikely(ret)) |
| 1523 | return ret; | 1505 | return ret; |
| @@ -1538,7 +1520,7 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in, | |||
| 1538 | if (len == 0) | 1520 | if (len == 0) |
| 1539 | return 0; | 1521 | return 0; |
| 1540 | 1522 | ||
| 1541 | sb_start_write(inode_out->i_sb); | 1523 | file_start_write(file_out); |
| 1542 | 1524 | ||
| 1543 | /* | 1525 | /* |
| 1544 | * Try cloning first, this is supported by more file systems, and | 1526 | * Try cloning first, this is supported by more file systems, and |
| @@ -1574,7 +1556,7 @@ done: | |||
| 1574 | inc_syscr(current); | 1556 | inc_syscr(current); |
| 1575 | inc_syscw(current); | 1557 | inc_syscw(current); |
| 1576 | 1558 | ||
| 1577 | sb_end_write(inode_out->i_sb); | 1559 | file_end_write(file_out); |
| 1578 | 1560 | ||
| 1579 | return ret; | 1561 | return ret; |
| 1580 | } | 1562 | } |
diff --git a/fs/splice.c b/fs/splice.c index 4ef78aa8ef61..eaafa3d8869a 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
| @@ -307,7 +307,7 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos, | |||
| 307 | idx = to.idx; | 307 | idx = to.idx; |
| 308 | init_sync_kiocb(&kiocb, in); | 308 | init_sync_kiocb(&kiocb, in); |
| 309 | kiocb.ki_pos = *ppos; | 309 | kiocb.ki_pos = *ppos; |
| 310 | ret = in->f_op->read_iter(&kiocb, &to); | 310 | ret = call_read_iter(in, &kiocb, &to); |
| 311 | if (ret > 0) { | 311 | if (ret > 0) { |
| 312 | *ppos = kiocb.ki_pos; | 312 | *ppos = kiocb.ki_pos; |
| 313 | file_accessed(in); | 313 | file_accessed(in); |
| @@ -192,7 +192,7 @@ int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync) | |||
| 192 | spin_unlock(&inode->i_lock); | 192 | spin_unlock(&inode->i_lock); |
| 193 | mark_inode_dirty_sync(inode); | 193 | mark_inode_dirty_sync(inode); |
| 194 | } | 194 | } |
| 195 | return file->f_op->fsync(file, start, end, datasync); | 195 | return call_fsync(file, start, end, datasync); |
| 196 | } | 196 | } |
| 197 | EXPORT_SYMBOL(vfs_fsync_range); | 197 | EXPORT_SYMBOL(vfs_fsync_range); |
| 198 | 198 | ||
diff --git a/include/linux/fs.h b/include/linux/fs.h index c64f2cb7d364..52350947c670 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -1567,6 +1567,9 @@ extern int vfs_unlink(struct inode *, struct dentry *, struct inode **); | |||
| 1567 | extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, struct inode **, unsigned int); | 1567 | extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, struct inode **, unsigned int); |
| 1568 | extern int vfs_whiteout(struct inode *, struct dentry *); | 1568 | extern int vfs_whiteout(struct inode *, struct dentry *); |
| 1569 | 1569 | ||
| 1570 | extern struct dentry *vfs_tmpfile(struct dentry *dentry, umode_t mode, | ||
| 1571 | int open_flag); | ||
| 1572 | |||
| 1570 | /* | 1573 | /* |
| 1571 | * VFS file helper functions. | 1574 | * VFS file helper functions. |
| 1572 | */ | 1575 | */ |
| @@ -1718,6 +1721,29 @@ struct inode_operations { | |||
| 1718 | int (*set_acl)(struct inode *, struct posix_acl *, int); | 1721 | int (*set_acl)(struct inode *, struct posix_acl *, int); |
| 1719 | } ____cacheline_aligned; | 1722 | } ____cacheline_aligned; |
| 1720 | 1723 | ||
| 1724 | static inline ssize_t call_read_iter(struct file *file, struct kiocb *kio, | ||
| 1725 | struct iov_iter *iter) | ||
| 1726 | { | ||
| 1727 | return file->f_op->read_iter(kio, iter); | ||
| 1728 | } | ||
| 1729 | |||
| 1730 | static inline ssize_t call_write_iter(struct file *file, struct kiocb *kio, | ||
| 1731 | struct iov_iter *iter) | ||
| 1732 | { | ||
| 1733 | return file->f_op->write_iter(kio, iter); | ||
| 1734 | } | ||
| 1735 | |||
| 1736 | static inline int call_mmap(struct file *file, struct vm_area_struct *vma) | ||
| 1737 | { | ||
| 1738 | return file->f_op->mmap(file, vma); | ||
| 1739 | } | ||
| 1740 | |||
| 1741 | static inline int call_fsync(struct file *file, loff_t start, loff_t end, | ||
| 1742 | int datasync) | ||
| 1743 | { | ||
| 1744 | return file->f_op->fsync(file, start, end, datasync); | ||
| 1745 | } | ||
| 1746 | |||
| 1721 | ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, | 1747 | ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, |
| 1722 | unsigned long nr_segs, unsigned long fast_segs, | 1748 | unsigned long nr_segs, unsigned long fast_segs, |
| 1723 | struct iovec *fast_pointer, | 1749 | struct iovec *fast_pointer, |
| @@ -1744,19 +1770,6 @@ extern int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff, | |||
| 1744 | extern int vfs_dedupe_file_range(struct file *file, | 1770 | extern int vfs_dedupe_file_range(struct file *file, |
| 1745 | struct file_dedupe_range *same); | 1771 | struct file_dedupe_range *same); |
| 1746 | 1772 | ||
| 1747 | static inline int do_clone_file_range(struct file *file_in, loff_t pos_in, | ||
| 1748 | struct file *file_out, loff_t pos_out, | ||
| 1749 | u64 len) | ||
| 1750 | { | ||
| 1751 | int ret; | ||
| 1752 | |||
| 1753 | sb_start_write(file_inode(file_out)->i_sb); | ||
| 1754 | ret = vfs_clone_file_range(file_in, pos_in, file_out, pos_out, len); | ||
| 1755 | sb_end_write(file_inode(file_out)->i_sb); | ||
| 1756 | |||
| 1757 | return ret; | ||
| 1758 | } | ||
| 1759 | |||
| 1760 | struct super_operations { | 1773 | struct super_operations { |
| 1761 | struct inode *(*alloc_inode)(struct super_block *sb); | 1774 | struct inode *(*alloc_inode)(struct super_block *sb); |
| 1762 | void (*destroy_inode)(struct inode *); | 1775 | void (*destroy_inode)(struct inode *); |
| @@ -2568,6 +2581,19 @@ static inline void file_end_write(struct file *file) | |||
| 2568 | __sb_end_write(file_inode(file)->i_sb, SB_FREEZE_WRITE); | 2581 | __sb_end_write(file_inode(file)->i_sb, SB_FREEZE_WRITE); |
| 2569 | } | 2582 | } |
| 2570 | 2583 | ||
| 2584 | static inline int do_clone_file_range(struct file *file_in, loff_t pos_in, | ||
| 2585 | struct file *file_out, loff_t pos_out, | ||
| 2586 | u64 len) | ||
| 2587 | { | ||
| 2588 | int ret; | ||
| 2589 | |||
| 2590 | file_start_write(file_out); | ||
| 2591 | ret = vfs_clone_file_range(file_in, pos_in, file_out, pos_out, len); | ||
| 2592 | file_end_write(file_out); | ||
| 2593 | |||
| 2594 | return ret; | ||
| 2595 | } | ||
| 2596 | |||
| 2571 | /* | 2597 | /* |
| 2572 | * get_write_access() gets write permission for a file. | 2598 | * get_write_access() gets write permission for a file. |
| 2573 | * put_write_access() releases this write permission. | 2599 | * put_write_access() releases this write permission. |
| @@ -423,7 +423,7 @@ static int shm_mmap(struct file *file, struct vm_area_struct *vma) | |||
| 423 | if (ret) | 423 | if (ret) |
| 424 | return ret; | 424 | return ret; |
| 425 | 425 | ||
| 426 | ret = sfd->file->f_op->mmap(sfd->file, vma); | 426 | ret = call_mmap(sfd->file, vma); |
| 427 | if (ret) { | 427 | if (ret) { |
| 428 | shm_close(vma); | 428 | shm_close(vma); |
| 429 | return ret; | 429 | return ret; |
| @@ -452,7 +452,7 @@ static int shm_fsync(struct file *file, loff_t start, loff_t end, int datasync) | |||
| 452 | 452 | ||
| 453 | if (!sfd->file->f_op->fsync) | 453 | if (!sfd->file->f_op->fsync) |
| 454 | return -EINVAL; | 454 | return -EINVAL; |
| 455 | return sfd->file->f_op->fsync(sfd->file, start, end, datasync); | 455 | return call_fsync(sfd->file, start, end, datasync); |
| 456 | } | 456 | } |
| 457 | 457 | ||
| 458 | static long shm_fallocate(struct file *file, int mode, loff_t offset, | 458 | static long shm_fallocate(struct file *file, int mode, loff_t offset, |
| @@ -1672,7 +1672,7 @@ unsigned long mmap_region(struct file *file, unsigned long addr, | |||
| 1672 | * new file must not have been exposed to user-space, yet. | 1672 | * new file must not have been exposed to user-space, yet. |
| 1673 | */ | 1673 | */ |
| 1674 | vma->vm_file = get_file(file); | 1674 | vma->vm_file = get_file(file); |
| 1675 | error = file->f_op->mmap(file, vma); | 1675 | error = call_mmap(file, vma); |
| 1676 | if (error) | 1676 | if (error) |
| 1677 | goto unmap_and_free_vma; | 1677 | goto unmap_and_free_vma; |
| 1678 | 1678 | ||
diff --git a/mm/nommu.c b/mm/nommu.c index fe9f4fa4a7a7..5bbef9cb89eb 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
| @@ -1084,7 +1084,7 @@ static int do_mmap_shared_file(struct vm_area_struct *vma) | |||
| 1084 | { | 1084 | { |
| 1085 | int ret; | 1085 | int ret; |
| 1086 | 1086 | ||
| 1087 | ret = vma->vm_file->f_op->mmap(vma->vm_file, vma); | 1087 | ret = call_mmap(vma->vm_file, vma); |
| 1088 | if (ret == 0) { | 1088 | if (ret == 0) { |
| 1089 | vma->vm_region->vm_top = vma->vm_region->vm_end; | 1089 | vma->vm_region->vm_top = vma->vm_region->vm_end; |
| 1090 | return 0; | 1090 | return 0; |
| @@ -1115,7 +1115,7 @@ static int do_mmap_private(struct vm_area_struct *vma, | |||
| 1115 | * - VM_MAYSHARE will be set if it may attempt to share | 1115 | * - VM_MAYSHARE will be set if it may attempt to share |
| 1116 | */ | 1116 | */ |
| 1117 | if (capabilities & NOMMU_MAP_DIRECT) { | 1117 | if (capabilities & NOMMU_MAP_DIRECT) { |
| 1118 | ret = vma->vm_file->f_op->mmap(vma->vm_file, vma); | 1118 | ret = call_mmap(vma->vm_file, vma); |
| 1119 | if (ret == 0) { | 1119 | if (ret == 0) { |
| 1120 | /* shouldn't return success if we're not sharing */ | 1120 | /* shouldn't return success if we're not sharing */ |
| 1121 | BUG_ON(!(vma->vm_flags & VM_MAYSHARE)); | 1121 | BUG_ON(!(vma->vm_flags & VM_MAYSHARE)); |
