diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-12 17:49:50 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-12 17:49:50 -0400 |
commit | 5166701b368caea89d57b14bf41cf39e819dad51 (patch) | |
tree | c73b9d4860809e3afa9359be9d03ba2d8d98a18e /fs/cifs | |
parent | 0a7418f5f569512e98789c439198eed4b507cce3 (diff) | |
parent | a786c06d9f2719203c00b3d97b21f9a96980d0b5 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs updates from Al Viro:
"The first vfs pile, with deep apologies for being very late in this
window.
Assorted cleanups and fixes, plus a large preparatory part of iov_iter
work. There's a lot more of that, but it'll probably go into the next
merge window - it *does* shape up nicely, removes a lot of
boilerplate, gets rid of locking inconsistencie between aio_write and
splice_write and I hope to get Kent's direct-io rewrite merged into
the same queue, but some of the stuff after this point is having
(mostly trivial) conflicts with the things already merged into
mainline and with some I want more testing.
This one passes LTP and xfstests without regressions, in addition to
usual beating. BTW, readahead02 in ltp syscalls testsuite has started
giving failures since "mm/readahead.c: fix readahead failure for
memoryless NUMA nodes and limit readahead pages" - might be a false
positive, might be a real regression..."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (63 commits)
missing bits of "splice: fix racy pipe->buffers uses"
cifs: fix the race in cifs_writev()
ceph_sync_{,direct_}write: fix an oops on ceph_osdc_new_request() failure
kill generic_file_buffered_write()
ocfs2_file_aio_write(): switch to generic_perform_write()
ceph_aio_write(): switch to generic_perform_write()
xfs_file_buffered_aio_write(): switch to generic_perform_write()
export generic_perform_write(), start getting rid of generic_file_buffer_write()
generic_file_direct_write(): get rid of ppos argument
btrfs_file_aio_write(): get rid of ppos
kill the 5th argument of generic_file_buffered_write()
kill the 4th argument of __generic_file_aio_write()
lustre: don't open-code kernel_recvmsg()
ocfs2: don't open-code kernel_recvmsg()
drbd: don't open-code kernel_recvmsg()
constify blk_rq_map_user_iov() and friends
lustre: switch to kernel_sendmsg()
ocfs2: don't open-code kernel_sendmsg()
take iov_iter stuff to mm/iov_iter.c
process_vm_access: tidy up a bit
...
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/cifsfs.c | 1 | ||||
-rw-r--r-- | fs/cifs/file.c | 128 |
2 files changed, 52 insertions, 77 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 2c70cbe35d39..df9c9141c099 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -850,7 +850,6 @@ const struct inode_operations cifs_file_inode_ops = { | |||
850 | /* revalidate:cifs_revalidate, */ | 850 | /* revalidate:cifs_revalidate, */ |
851 | .setattr = cifs_setattr, | 851 | .setattr = cifs_setattr, |
852 | .getattr = cifs_getattr, /* do we need this anymore? */ | 852 | .getattr = cifs_getattr, /* do we need this anymore? */ |
853 | .rename = cifs_rename, | ||
854 | .permission = cifs_permission, | 853 | .permission = cifs_permission, |
855 | #ifdef CONFIG_CIFS_XATTR | 854 | #ifdef CONFIG_CIFS_XATTR |
856 | .setxattr = cifs_setxattr, | 855 | .setxattr = cifs_setxattr, |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 216d7e99f921..8807442c94dd 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -2579,19 +2579,32 @@ cifs_writev(struct kiocb *iocb, const struct iovec *iov, | |||
2579 | struct cifsInodeInfo *cinode = CIFS_I(inode); | 2579 | struct cifsInodeInfo *cinode = CIFS_I(inode); |
2580 | struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; | 2580 | struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; |
2581 | ssize_t rc = -EACCES; | 2581 | ssize_t rc = -EACCES; |
2582 | loff_t lock_pos = pos; | 2582 | loff_t lock_pos = iocb->ki_pos; |
2583 | 2583 | ||
2584 | if (file->f_flags & O_APPEND) | ||
2585 | lock_pos = i_size_read(inode); | ||
2586 | /* | 2584 | /* |
2587 | * We need to hold the sem to be sure nobody modifies lock list | 2585 | * We need to hold the sem to be sure nobody modifies lock list |
2588 | * with a brlock that prevents writing. | 2586 | * with a brlock that prevents writing. |
2589 | */ | 2587 | */ |
2590 | down_read(&cinode->lock_sem); | 2588 | down_read(&cinode->lock_sem); |
2589 | mutex_lock(&inode->i_mutex); | ||
2590 | if (file->f_flags & O_APPEND) | ||
2591 | lock_pos = i_size_read(inode); | ||
2591 | if (!cifs_find_lock_conflict(cfile, lock_pos, iov_length(iov, nr_segs), | 2592 | if (!cifs_find_lock_conflict(cfile, lock_pos, iov_length(iov, nr_segs), |
2592 | server->vals->exclusive_lock_type, NULL, | 2593 | server->vals->exclusive_lock_type, NULL, |
2593 | CIFS_WRITE_OP)) | 2594 | CIFS_WRITE_OP)) { |
2594 | rc = generic_file_aio_write(iocb, iov, nr_segs, pos); | 2595 | rc = __generic_file_aio_write(iocb, iov, nr_segs); |
2596 | mutex_unlock(&inode->i_mutex); | ||
2597 | |||
2598 | if (rc > 0) { | ||
2599 | ssize_t err; | ||
2600 | |||
2601 | err = generic_write_sync(file, iocb->ki_pos - rc, rc); | ||
2602 | if (rc < 0) | ||
2603 | rc = err; | ||
2604 | } | ||
2605 | } else { | ||
2606 | mutex_unlock(&inode->i_mutex); | ||
2607 | } | ||
2595 | up_read(&cinode->lock_sem); | 2608 | up_read(&cinode->lock_sem); |
2596 | return rc; | 2609 | return rc; |
2597 | } | 2610 | } |
@@ -2727,56 +2740,27 @@ cifs_retry_async_readv(struct cifs_readdata *rdata) | |||
2727 | /** | 2740 | /** |
2728 | * cifs_readdata_to_iov - copy data from pages in response to an iovec | 2741 | * cifs_readdata_to_iov - copy data from pages in response to an iovec |
2729 | * @rdata: the readdata response with list of pages holding data | 2742 | * @rdata: the readdata response with list of pages holding data |
2730 | * @iov: vector in which we should copy the data | 2743 | * @iter: destination for our data |
2731 | * @nr_segs: number of segments in vector | ||
2732 | * @offset: offset into file of the first iovec | ||
2733 | * @copied: used to return the amount of data copied to the iov | ||
2734 | * | 2744 | * |
2735 | * This function copies data from a list of pages in a readdata response into | 2745 | * This function copies data from a list of pages in a readdata response into |
2736 | * an array of iovecs. It will first calculate where the data should go | 2746 | * an array of iovecs. It will first calculate where the data should go |
2737 | * based on the info in the readdata and then copy the data into that spot. | 2747 | * based on the info in the readdata and then copy the data into that spot. |
2738 | */ | 2748 | */ |
2739 | static ssize_t | 2749 | static int |
2740 | cifs_readdata_to_iov(struct cifs_readdata *rdata, const struct iovec *iov, | 2750 | cifs_readdata_to_iov(struct cifs_readdata *rdata, struct iov_iter *iter) |
2741 | unsigned long nr_segs, loff_t offset, ssize_t *copied) | ||
2742 | { | 2751 | { |
2743 | int rc = 0; | 2752 | size_t remaining = rdata->bytes; |
2744 | struct iov_iter ii; | ||
2745 | size_t pos = rdata->offset - offset; | ||
2746 | ssize_t remaining = rdata->bytes; | ||
2747 | unsigned char *pdata; | ||
2748 | unsigned int i; | 2753 | unsigned int i; |
2749 | 2754 | ||
2750 | /* set up iov_iter and advance to the correct offset */ | ||
2751 | iov_iter_init(&ii, iov, nr_segs, iov_length(iov, nr_segs), 0); | ||
2752 | iov_iter_advance(&ii, pos); | ||
2753 | |||
2754 | *copied = 0; | ||
2755 | for (i = 0; i < rdata->nr_pages; i++) { | 2755 | for (i = 0; i < rdata->nr_pages; i++) { |
2756 | ssize_t copy; | ||
2757 | struct page *page = rdata->pages[i]; | 2756 | struct page *page = rdata->pages[i]; |
2758 | 2757 | size_t copy = min(remaining, PAGE_SIZE); | |
2759 | /* copy a whole page or whatever's left */ | 2758 | size_t written = copy_page_to_iter(page, 0, copy, iter); |
2760 | copy = min_t(ssize_t, remaining, PAGE_SIZE); | 2759 | remaining -= written; |
2761 | 2760 | if (written < copy && iov_iter_count(iter) > 0) | |
2762 | /* ...but limit it to whatever space is left in the iov */ | 2761 | break; |
2763 | copy = min_t(ssize_t, copy, iov_iter_count(&ii)); | ||
2764 | |||
2765 | /* go while there's data to be copied and no errors */ | ||
2766 | if (copy && !rc) { | ||
2767 | pdata = kmap(page); | ||
2768 | rc = memcpy_toiovecend(ii.iov, pdata, ii.iov_offset, | ||
2769 | (int)copy); | ||
2770 | kunmap(page); | ||
2771 | if (!rc) { | ||
2772 | *copied += copy; | ||
2773 | remaining -= copy; | ||
2774 | iov_iter_advance(&ii, copy); | ||
2775 | } | ||
2776 | } | ||
2777 | } | 2762 | } |
2778 | 2763 | return remaining ? -EFAULT : 0; | |
2779 | return rc; | ||
2780 | } | 2764 | } |
2781 | 2765 | ||
2782 | static void | 2766 | static void |
@@ -2837,20 +2821,21 @@ cifs_uncached_read_into_pages(struct TCP_Server_Info *server, | |||
2837 | return total_read > 0 ? total_read : result; | 2821 | return total_read > 0 ? total_read : result; |
2838 | } | 2822 | } |
2839 | 2823 | ||
2840 | static ssize_t | 2824 | ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov, |
2841 | cifs_iovec_read(struct file *file, const struct iovec *iov, | 2825 | unsigned long nr_segs, loff_t pos) |
2842 | unsigned long nr_segs, loff_t *poffset) | ||
2843 | { | 2826 | { |
2827 | struct file *file = iocb->ki_filp; | ||
2844 | ssize_t rc; | 2828 | ssize_t rc; |
2845 | size_t len, cur_len; | 2829 | size_t len, cur_len; |
2846 | ssize_t total_read = 0; | 2830 | ssize_t total_read = 0; |
2847 | loff_t offset = *poffset; | 2831 | loff_t offset = pos; |
2848 | unsigned int npages; | 2832 | unsigned int npages; |
2849 | struct cifs_sb_info *cifs_sb; | 2833 | struct cifs_sb_info *cifs_sb; |
2850 | struct cifs_tcon *tcon; | 2834 | struct cifs_tcon *tcon; |
2851 | struct cifsFileInfo *open_file; | 2835 | struct cifsFileInfo *open_file; |
2852 | struct cifs_readdata *rdata, *tmp; | 2836 | struct cifs_readdata *rdata, *tmp; |
2853 | struct list_head rdata_list; | 2837 | struct list_head rdata_list; |
2838 | struct iov_iter to; | ||
2854 | pid_t pid; | 2839 | pid_t pid; |
2855 | 2840 | ||
2856 | if (!nr_segs) | 2841 | if (!nr_segs) |
@@ -2860,6 +2845,8 @@ cifs_iovec_read(struct file *file, const struct iovec *iov, | |||
2860 | if (!len) | 2845 | if (!len) |
2861 | return 0; | 2846 | return 0; |
2862 | 2847 | ||
2848 | iov_iter_init(&to, iov, nr_segs, len, 0); | ||
2849 | |||
2863 | INIT_LIST_HEAD(&rdata_list); | 2850 | INIT_LIST_HEAD(&rdata_list); |
2864 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 2851 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
2865 | open_file = file->private_data; | 2852 | open_file = file->private_data; |
@@ -2917,55 +2904,44 @@ error: | |||
2917 | if (!list_empty(&rdata_list)) | 2904 | if (!list_empty(&rdata_list)) |
2918 | rc = 0; | 2905 | rc = 0; |
2919 | 2906 | ||
2907 | len = iov_iter_count(&to); | ||
2920 | /* the loop below should proceed in the order of increasing offsets */ | 2908 | /* the loop below should proceed in the order of increasing offsets */ |
2921 | restart_loop: | ||
2922 | list_for_each_entry_safe(rdata, tmp, &rdata_list, list) { | 2909 | list_for_each_entry_safe(rdata, tmp, &rdata_list, list) { |
2910 | again: | ||
2923 | if (!rc) { | 2911 | if (!rc) { |
2924 | ssize_t copied; | ||
2925 | |||
2926 | /* FIXME: freezable sleep too? */ | 2912 | /* FIXME: freezable sleep too? */ |
2927 | rc = wait_for_completion_killable(&rdata->done); | 2913 | rc = wait_for_completion_killable(&rdata->done); |
2928 | if (rc) | 2914 | if (rc) |
2929 | rc = -EINTR; | 2915 | rc = -EINTR; |
2930 | else if (rdata->result) | 2916 | else if (rdata->result) { |
2931 | rc = rdata->result; | 2917 | rc = rdata->result; |
2932 | else { | 2918 | /* resend call if it's a retryable error */ |
2933 | rc = cifs_readdata_to_iov(rdata, iov, | 2919 | if (rc == -EAGAIN) { |
2934 | nr_segs, *poffset, | 2920 | rc = cifs_retry_async_readv(rdata); |
2935 | &copied); | 2921 | goto again; |
2936 | total_read += copied; | 2922 | } |
2923 | } else { | ||
2924 | rc = cifs_readdata_to_iov(rdata, &to); | ||
2937 | } | 2925 | } |
2938 | 2926 | ||
2939 | /* resend call if it's a retryable error */ | ||
2940 | if (rc == -EAGAIN) { | ||
2941 | rc = cifs_retry_async_readv(rdata); | ||
2942 | goto restart_loop; | ||
2943 | } | ||
2944 | } | 2927 | } |
2945 | list_del_init(&rdata->list); | 2928 | list_del_init(&rdata->list); |
2946 | kref_put(&rdata->refcount, cifs_uncached_readdata_release); | 2929 | kref_put(&rdata->refcount, cifs_uncached_readdata_release); |
2947 | } | 2930 | } |
2948 | 2931 | ||
2932 | total_read = len - iov_iter_count(&to); | ||
2933 | |||
2949 | cifs_stats_bytes_read(tcon, total_read); | 2934 | cifs_stats_bytes_read(tcon, total_read); |
2950 | *poffset += total_read; | ||
2951 | 2935 | ||
2952 | /* mask nodata case */ | 2936 | /* mask nodata case */ |
2953 | if (rc == -ENODATA) | 2937 | if (rc == -ENODATA) |
2954 | rc = 0; | 2938 | rc = 0; |
2955 | 2939 | ||
2956 | return total_read ? total_read : rc; | 2940 | if (total_read) { |
2957 | } | 2941 | iocb->ki_pos = pos + total_read; |
2958 | 2942 | return total_read; | |
2959 | ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov, | 2943 | } |
2960 | unsigned long nr_segs, loff_t pos) | 2944 | return rc; |
2961 | { | ||
2962 | ssize_t read; | ||
2963 | |||
2964 | read = cifs_iovec_read(iocb->ki_filp, iov, nr_segs, &pos); | ||
2965 | if (read > 0) | ||
2966 | iocb->ki_pos = pos; | ||
2967 | |||
2968 | return read; | ||
2969 | } | 2945 | } |
2970 | 2946 | ||
2971 | ssize_t | 2947 | ssize_t |