diff options
author | Pavel Shilovsky <pshilovsky@samba.org> | 2014-06-25 02:45:07 -0400 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2014-08-02 02:23:03 -0400 |
commit | 25f402598d2c8f0808d93715ad33e43b265c1604 (patch) | |
tree | 6e1c184cd4078276ff7f6d0a737fa4a7b6696636 /fs/cifs | |
parent | 0ada36b244e8316bb47b46b84b33c5a507bed7a4 (diff) |
CIFS: Fix rsize usage in user read
If a server changes maximum buffer size for read (rsize) requests
on reconnect we can fail on repeating with a big size buffer on
-EAGAIN error in user read. Fix this by checking rsize all the
time before repeating requests.
Reviewed-by: Shirish Pargaonkar <spargaonkar@suse.com>
Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org>
Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/file.c | 45 |
1 files changed, 22 insertions, 23 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 7df4e4658d74..bbc38594b39a 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -2828,26 +2828,6 @@ cifs_uncached_readdata_release(struct kref *refcount) | |||
2828 | cifs_readdata_release(refcount); | 2828 | cifs_readdata_release(refcount); |
2829 | } | 2829 | } |
2830 | 2830 | ||
2831 | static int | ||
2832 | cifs_retry_async_readv(struct cifs_readdata *rdata) | ||
2833 | { | ||
2834 | int rc; | ||
2835 | struct TCP_Server_Info *server; | ||
2836 | |||
2837 | server = tlink_tcon(rdata->cfile->tlink)->ses->server; | ||
2838 | |||
2839 | do { | ||
2840 | if (rdata->cfile->invalidHandle) { | ||
2841 | rc = cifs_reopen_file(rdata->cfile, true); | ||
2842 | if (rc != 0) | ||
2843 | continue; | ||
2844 | } | ||
2845 | rc = server->ops->async_readv(rdata); | ||
2846 | } while (rc == -EAGAIN); | ||
2847 | |||
2848 | return rc; | ||
2849 | } | ||
2850 | |||
2851 | /** | 2831 | /** |
2852 | * cifs_readdata_to_iov - copy data from pages in response to an iovec | 2832 | * cifs_readdata_to_iov - copy data from pages in response to an iovec |
2853 | * @rdata: the readdata response with list of pages holding data | 2833 | * @rdata: the readdata response with list of pages holding data |
@@ -2941,6 +2921,9 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, | |||
2941 | size_t cur_len; | 2921 | size_t cur_len; |
2942 | int rc; | 2922 | int rc; |
2943 | pid_t pid; | 2923 | pid_t pid; |
2924 | struct TCP_Server_Info *server; | ||
2925 | |||
2926 | server = tlink_tcon(open_file->tlink)->ses->server; | ||
2944 | 2927 | ||
2945 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) | 2928 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) |
2946 | pid = open_file->pid; | 2929 | pid = open_file->pid; |
@@ -2971,11 +2954,15 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, | |||
2971 | rdata->pagesz = PAGE_SIZE; | 2954 | rdata->pagesz = PAGE_SIZE; |
2972 | rdata->read_into_pages = cifs_uncached_read_into_pages; | 2955 | rdata->read_into_pages = cifs_uncached_read_into_pages; |
2973 | 2956 | ||
2974 | rc = cifs_retry_async_readv(rdata); | 2957 | if (!rdata->cfile->invalidHandle || |
2958 | !cifs_reopen_file(rdata->cfile, true)) | ||
2959 | rc = server->ops->async_readv(rdata); | ||
2975 | error: | 2960 | error: |
2976 | if (rc) { | 2961 | if (rc) { |
2977 | kref_put(&rdata->refcount, | 2962 | kref_put(&rdata->refcount, |
2978 | cifs_uncached_readdata_release); | 2963 | cifs_uncached_readdata_release); |
2964 | if (rc == -EAGAIN) | ||
2965 | continue; | ||
2979 | break; | 2966 | break; |
2980 | } | 2967 | } |
2981 | 2968 | ||
@@ -3023,8 +3010,8 @@ ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to) | |||
3023 | 3010 | ||
3024 | len = iov_iter_count(to); | 3011 | len = iov_iter_count(to); |
3025 | /* the loop below should proceed in the order of increasing offsets */ | 3012 | /* the loop below should proceed in the order of increasing offsets */ |
3013 | again: | ||
3026 | list_for_each_entry_safe(rdata, tmp, &rdata_list, list) { | 3014 | list_for_each_entry_safe(rdata, tmp, &rdata_list, list) { |
3027 | again: | ||
3028 | if (!rc) { | 3015 | if (!rc) { |
3029 | /* FIXME: freezable sleep too? */ | 3016 | /* FIXME: freezable sleep too? */ |
3030 | rc = wait_for_completion_killable(&rdata->done); | 3017 | rc = wait_for_completion_killable(&rdata->done); |
@@ -3034,7 +3021,19 @@ ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to) | |||
3034 | rc = rdata->result; | 3021 | rc = rdata->result; |
3035 | /* resend call if it's a retryable error */ | 3022 | /* resend call if it's a retryable error */ |
3036 | if (rc == -EAGAIN) { | 3023 | if (rc == -EAGAIN) { |
3037 | rc = cifs_retry_async_readv(rdata); | 3024 | struct list_head tmp_list; |
3025 | |||
3026 | list_del_init(&rdata->list); | ||
3027 | INIT_LIST_HEAD(&tmp_list); | ||
3028 | |||
3029 | rc = cifs_send_async_read(rdata->offset, | ||
3030 | rdata->bytes, rdata->cfile, | ||
3031 | cifs_sb, &tmp_list); | ||
3032 | |||
3033 | list_splice(&tmp_list, &rdata_list); | ||
3034 | |||
3035 | kref_put(&rdata->refcount, | ||
3036 | cifs_uncached_readdata_release); | ||
3038 | goto again; | 3037 | goto again; |
3039 | } | 3038 | } |
3040 | } else { | 3039 | } else { |