diff options
author | Pavel Shilovsky <pshilovsky@samba.org> | 2014-06-25 08:19:02 -0400 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2014-08-02 02:23:03 -0400 |
commit | e374d90f8a7693f24635bca9e5d56f3775bb36e2 (patch) | |
tree | 5be53f15accc65ab4ea25ccc8823540ad6c7aa3f /fs | |
parent | 25f402598d2c8f0808d93715ad33e43b265c1604 (diff) |
CIFS: Fix rsize usage for sync read
If a server changes maximum buffer size for read requests (rsize)
on reconnect we can fail on repeating with a big size buffer on
-EAGAIN error in cifs_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')
-rw-r--r-- | fs/cifs/file.c | 26 |
1 files changed, 14 insertions, 12 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index bbc38594b39a..00b2a254ff1c 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -3148,18 +3148,19 @@ cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset) | |||
3148 | 3148 | ||
3149 | for (total_read = 0, cur_offset = read_data; read_size > total_read; | 3149 | for (total_read = 0, cur_offset = read_data; read_size > total_read; |
3150 | total_read += bytes_read, cur_offset += bytes_read) { | 3150 | total_read += bytes_read, cur_offset += bytes_read) { |
3151 | current_read_size = min_t(uint, read_size - total_read, rsize); | 3151 | do { |
3152 | /* | 3152 | current_read_size = min_t(uint, read_size - total_read, |
3153 | * For windows me and 9x we do not want to request more than it | 3153 | rsize); |
3154 | * negotiated since it will refuse the read then. | 3154 | /* |
3155 | */ | 3155 | * For windows me and 9x we do not want to request more |
3156 | if ((tcon->ses) && !(tcon->ses->capabilities & | 3156 | * than it negotiated since it will refuse the read |
3157 | * then. | ||
3158 | */ | ||
3159 | if ((tcon->ses) && !(tcon->ses->capabilities & | ||
3157 | tcon->ses->server->vals->cap_large_files)) { | 3160 | tcon->ses->server->vals->cap_large_files)) { |
3158 | current_read_size = min_t(uint, current_read_size, | 3161 | current_read_size = min_t(uint, |
3159 | CIFSMaxBufSize); | 3162 | current_read_size, CIFSMaxBufSize); |
3160 | } | 3163 | } |
3161 | rc = -EAGAIN; | ||
3162 | while (rc == -EAGAIN) { | ||
3163 | if (open_file->invalidHandle) { | 3164 | if (open_file->invalidHandle) { |
3164 | rc = cifs_reopen_file(open_file, true); | 3165 | rc = cifs_reopen_file(open_file, true); |
3165 | if (rc != 0) | 3166 | if (rc != 0) |
@@ -3172,7 +3173,8 @@ cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset) | |||
3172 | rc = server->ops->sync_read(xid, open_file, &io_parms, | 3173 | rc = server->ops->sync_read(xid, open_file, &io_parms, |
3173 | &bytes_read, &cur_offset, | 3174 | &bytes_read, &cur_offset, |
3174 | &buf_type); | 3175 | &buf_type); |
3175 | } | 3176 | } while (rc == -EAGAIN); |
3177 | |||
3176 | if (rc || (bytes_read == 0)) { | 3178 | if (rc || (bytes_read == 0)) { |
3177 | if (total_read) { | 3179 | if (total_read) { |
3178 | break; | 3180 | break; |