diff options
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r-- | fs/cifs/file.c | 45 |
1 files changed, 35 insertions, 10 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index e3e3a7550205..2c7689f3998d 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) { |