diff options
Diffstat (limited to 'fs/cifs/file.c')
| -rw-r--r-- | fs/cifs/file.c | 56 |
1 files changed, 43 insertions, 13 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index e3e3a7550205..659ce1b92c44 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -733,7 +733,8 @@ reopen_success: | |||
| 733 | 733 | ||
| 734 | if (can_flush) { | 734 | if (can_flush) { |
| 735 | rc = filemap_write_and_wait(inode->i_mapping); | 735 | rc = filemap_write_and_wait(inode->i_mapping); |
| 736 | mapping_set_error(inode->i_mapping, rc); | 736 | if (!is_interrupt_error(rc)) |
| 737 | mapping_set_error(inode->i_mapping, rc); | ||
| 737 | 738 | ||
| 738 | if (tcon->unix_ext) | 739 | if (tcon->unix_ext) |
| 739 | rc = cifs_get_inode_info_unix(&inode, full_path, | 740 | rc = cifs_get_inode_info_unix(&inode, full_path, |
| @@ -1132,14 +1133,18 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile) | |||
| 1132 | 1133 | ||
| 1133 | /* | 1134 | /* |
| 1134 | * Accessing maxBuf is racy with cifs_reconnect - need to store value | 1135 | * Accessing maxBuf is racy with cifs_reconnect - need to store value |
| 1135 | * and check it for zero before using. | 1136 | * and check it before using. |
| 1136 | */ | 1137 | */ |
| 1137 | max_buf = tcon->ses->server->maxBuf; | 1138 | max_buf = tcon->ses->server->maxBuf; |
| 1138 | if (!max_buf) { | 1139 | if (max_buf < (sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE))) { |
| 1139 | free_xid(xid); | 1140 | free_xid(xid); |
| 1140 | return -EINVAL; | 1141 | return -EINVAL; |
| 1141 | } | 1142 | } |
| 1142 | 1143 | ||
| 1144 | BUILD_BUG_ON(sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE) > | ||
| 1145 | PAGE_SIZE); | ||
| 1146 | max_buf = min_t(unsigned int, max_buf - sizeof(struct smb_hdr), | ||
| 1147 | PAGE_SIZE); | ||
| 1143 | max_num = (max_buf - sizeof(struct smb_hdr)) / | 1148 | max_num = (max_buf - sizeof(struct smb_hdr)) / |
| 1144 | sizeof(LOCKING_ANDX_RANGE); | 1149 | sizeof(LOCKING_ANDX_RANGE); |
| 1145 | buf = kcalloc(max_num, sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL); | 1150 | buf = kcalloc(max_num, sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL); |
| @@ -1472,12 +1477,16 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, | |||
| 1472 | 1477 | ||
| 1473 | /* | 1478 | /* |
| 1474 | * Accessing maxBuf is racy with cifs_reconnect - need to store value | 1479 | * Accessing maxBuf is racy with cifs_reconnect - need to store value |
| 1475 | * and check it for zero before using. | 1480 | * and check it before using. |
| 1476 | */ | 1481 | */ |
| 1477 | max_buf = tcon->ses->server->maxBuf; | 1482 | max_buf = tcon->ses->server->maxBuf; |
| 1478 | if (!max_buf) | 1483 | if (max_buf < (sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE))) |
| 1479 | return -EINVAL; | 1484 | return -EINVAL; |
| 1480 | 1485 | ||
| 1486 | BUILD_BUG_ON(sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE) > | ||
| 1487 | PAGE_SIZE); | ||
| 1488 | max_buf = min_t(unsigned int, max_buf - sizeof(struct smb_hdr), | ||
| 1489 | PAGE_SIZE); | ||
| 1481 | max_num = (max_buf - sizeof(struct smb_hdr)) / | 1490 | max_num = (max_buf - sizeof(struct smb_hdr)) / |
| 1482 | sizeof(LOCKING_ANDX_RANGE); | 1491 | sizeof(LOCKING_ANDX_RANGE); |
| 1483 | buf = kcalloc(max_num, sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL); | 1492 | buf = kcalloc(max_num, sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL); |
| @@ -2110,6 +2119,7 @@ static int cifs_writepages(struct address_space *mapping, | |||
| 2110 | pgoff_t end, index; | 2119 | pgoff_t end, index; |
| 2111 | struct cifs_writedata *wdata; | 2120 | struct cifs_writedata *wdata; |
| 2112 | int rc = 0; | 2121 | int rc = 0; |
| 2122 | int saved_rc = 0; | ||
| 2113 | unsigned int xid; | 2123 | unsigned int xid; |
| 2114 | 2124 | ||
| 2115 | /* | 2125 | /* |
| @@ -2138,8 +2148,10 @@ retry: | |||
| 2138 | 2148 | ||
| 2139 | rc = server->ops->wait_mtu_credits(server, cifs_sb->wsize, | 2149 | rc = server->ops->wait_mtu_credits(server, cifs_sb->wsize, |
| 2140 | &wsize, &credits); | 2150 | &wsize, &credits); |
| 2141 | if (rc) | 2151 | if (rc != 0) { |
| 2152 | done = true; | ||
| 2142 | break; | 2153 | break; |
| 2154 | } | ||
| 2143 | 2155 | ||
| 2144 | tofind = min((wsize / PAGE_SIZE) - 1, end - index) + 1; | 2156 | tofind = min((wsize / PAGE_SIZE) - 1, end - index) + 1; |
| 2145 | 2157 | ||
| @@ -2147,6 +2159,7 @@ retry: | |||
| 2147 | &found_pages); | 2159 | &found_pages); |
| 2148 | if (!wdata) { | 2160 | if (!wdata) { |
| 2149 | rc = -ENOMEM; | 2161 | rc = -ENOMEM; |
| 2162 | done = true; | ||
| 2150 | add_credits_and_wake_if(server, credits, 0); | 2163 | add_credits_and_wake_if(server, credits, 0); |
| 2151 | break; | 2164 | break; |
| 2152 | } | 2165 | } |
| @@ -2175,7 +2188,7 @@ retry: | |||
| 2175 | if (rc != 0) { | 2188 | if (rc != 0) { |
| 2176 | add_credits_and_wake_if(server, wdata->credits, 0); | 2189 | add_credits_and_wake_if(server, wdata->credits, 0); |
| 2177 | for (i = 0; i < nr_pages; ++i) { | 2190 | for (i = 0; i < nr_pages; ++i) { |
| 2178 | if (rc == -EAGAIN) | 2191 | if (is_retryable_error(rc)) |
| 2179 | redirty_page_for_writepage(wbc, | 2192 | redirty_page_for_writepage(wbc, |
| 2180 | wdata->pages[i]); | 2193 | wdata->pages[i]); |
| 2181 | else | 2194 | else |
| @@ -2183,7 +2196,7 @@ retry: | |||
| 2183 | end_page_writeback(wdata->pages[i]); | 2196 | end_page_writeback(wdata->pages[i]); |
| 2184 | put_page(wdata->pages[i]); | 2197 | put_page(wdata->pages[i]); |
| 2185 | } | 2198 | } |
| 2186 | if (rc != -EAGAIN) | 2199 | if (!is_retryable_error(rc)) |
| 2187 | mapping_set_error(mapping, rc); | 2200 | mapping_set_error(mapping, rc); |
| 2188 | } | 2201 | } |
| 2189 | kref_put(&wdata->refcount, cifs_writedata_release); | 2202 | kref_put(&wdata->refcount, cifs_writedata_release); |
| @@ -2193,6 +2206,15 @@ retry: | |||
| 2193 | continue; | 2206 | continue; |
| 2194 | } | 2207 | } |
| 2195 | 2208 | ||
| 2209 | /* Return immediately if we received a signal during writing */ | ||
| 2210 | if (is_interrupt_error(rc)) { | ||
| 2211 | done = true; | ||
| 2212 | break; | ||
| 2213 | } | ||
| 2214 | |||
| 2215 | if (rc != 0 && saved_rc == 0) | ||
| 2216 | saved_rc = rc; | ||
| 2217 | |||
| 2196 | wbc->nr_to_write -= nr_pages; | 2218 | wbc->nr_to_write -= nr_pages; |
| 2197 | if (wbc->nr_to_write <= 0) | 2219 | if (wbc->nr_to_write <= 0) |
| 2198 | done = true; | 2220 | done = true; |
| @@ -2210,6 +2232,9 @@ retry: | |||
| 2210 | goto retry; | 2232 | goto retry; |
| 2211 | } | 2233 | } |
| 2212 | 2234 | ||
| 2235 | if (saved_rc != 0) | ||
| 2236 | rc = saved_rc; | ||
| 2237 | |||
| 2213 | if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) | 2238 | if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) |
| 2214 | mapping->writeback_index = index; | 2239 | mapping->writeback_index = index; |
| 2215 | 2240 | ||
| @@ -2242,8 +2267,8 @@ cifs_writepage_locked(struct page *page, struct writeback_control *wbc) | |||
| 2242 | set_page_writeback(page); | 2267 | set_page_writeback(page); |
| 2243 | retry_write: | 2268 | retry_write: |
| 2244 | rc = cifs_partialpagewrite(page, 0, PAGE_SIZE); | 2269 | rc = cifs_partialpagewrite(page, 0, PAGE_SIZE); |
| 2245 | if (rc == -EAGAIN) { | 2270 | if (is_retryable_error(rc)) { |
| 2246 | if (wbc->sync_mode == WB_SYNC_ALL) | 2271 | if (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN) |
| 2247 | goto retry_write; | 2272 | goto retry_write; |
| 2248 | redirty_page_for_writepage(wbc, page); | 2273 | redirty_page_for_writepage(wbc, page); |
| 2249 | } else if (rc != 0) { | 2274 | } else if (rc != 0) { |
| @@ -2671,6 +2696,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, | |||
| 2671 | 2696 | ||
| 2672 | rc = cifs_write_allocate_pages(wdata->pages, nr_pages); | 2697 | rc = cifs_write_allocate_pages(wdata->pages, nr_pages); |
| 2673 | if (rc) { | 2698 | if (rc) { |
| 2699 | kvfree(wdata->pages); | ||
| 2674 | kfree(wdata); | 2700 | kfree(wdata); |
| 2675 | add_credits_and_wake_if(server, credits, 0); | 2701 | add_credits_and_wake_if(server, credits, 0); |
| 2676 | break; | 2702 | break; |
| @@ -2682,6 +2708,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, | |||
| 2682 | if (rc) { | 2708 | if (rc) { |
| 2683 | for (i = 0; i < nr_pages; i++) | 2709 | for (i = 0; i < nr_pages; i++) |
| 2684 | put_page(wdata->pages[i]); | 2710 | put_page(wdata->pages[i]); |
| 2711 | kvfree(wdata->pages); | ||
| 2685 | kfree(wdata); | 2712 | kfree(wdata); |
| 2686 | add_credits_and_wake_if(server, credits, 0); | 2713 | add_credits_and_wake_if(server, credits, 0); |
| 2687 | break; | 2714 | break; |
| @@ -3361,8 +3388,12 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, | |||
| 3361 | } | 3388 | } |
| 3362 | 3389 | ||
| 3363 | rc = cifs_read_allocate_pages(rdata, npages); | 3390 | rc = cifs_read_allocate_pages(rdata, npages); |
| 3364 | if (rc) | 3391 | if (rc) { |
| 3365 | goto error; | 3392 | kvfree(rdata->pages); |
| 3393 | kfree(rdata); | ||
| 3394 | add_credits_and_wake_if(server, credits, 0); | ||
| 3395 | break; | ||
| 3396 | } | ||
| 3366 | 3397 | ||
| 3367 | rdata->tailsz = PAGE_SIZE; | 3398 | rdata->tailsz = PAGE_SIZE; |
| 3368 | } | 3399 | } |
| @@ -3382,7 +3413,6 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, | |||
| 3382 | if (!rdata->cfile->invalidHandle || | 3413 | if (!rdata->cfile->invalidHandle || |
| 3383 | !(rc = cifs_reopen_file(rdata->cfile, true))) | 3414 | !(rc = cifs_reopen_file(rdata->cfile, true))) |
| 3384 | rc = server->ops->async_readv(rdata); | 3415 | rc = server->ops->async_readv(rdata); |
| 3385 | error: | ||
| 3386 | if (rc) { | 3416 | if (rc) { |
| 3387 | add_credits_and_wake_if(server, rdata->credits, 0); | 3417 | add_credits_and_wake_if(server, rdata->credits, 0); |
| 3388 | kref_put(&rdata->refcount, | 3418 | kref_put(&rdata->refcount, |
