Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag '5.0-rc1-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French:
"A set of cifs/smb3 fixes, 4 for stable, most from Pavel. His patches
fix an important set of crediting (flow control) problems, and also
two problems in cifs_writepages, ddressing some large i/o and also
compounding issues"

* tag '5.0-rc1-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6:
cifs: update internal module version number
CIFS: Fix error paths in writeback code
CIFS: Move credit processing to mid callbacks for SMB3
CIFS: Fix credits calculation for cancelled requests
cifs: Fix potential OOB access of lock element array
cifs: Limit memory used by lock request calls to a page
cifs: move large array from stack to heap
CIFS: Do not hide EINTR after sending network packets
CIFS: Fix credit computation for compounded requests
CIFS: Do not set credits to 1 if the server didn't grant anything
CIFS: Fix adjustment of credits for MTU requests
cifs: Fix a tiny potential memory leak
cifs: Fix a debug message

+211 -65
+1 -1
fs/cifs/cifsfs.h
··· 150 150 extern const struct export_operations cifs_export_ops; 151 151 #endif /* CONFIG_CIFS_NFSD_EXPORT */ 152 152 153 - #define CIFS_VERSION "2.15" 153 + #define CIFS_VERSION "2.16" 154 154 #endif /* _CIFSFS_H */
+20
fs/cifs/cifsglob.h
··· 1438 1438 int mid_state; /* wish this were enum but can not pass to wait_event */ 1439 1439 unsigned int mid_flags; 1440 1440 __le16 command; /* smb command code */ 1441 + unsigned int optype; /* operation type */ 1441 1442 bool large_buf:1; /* if valid response, is pointer to large buf */ 1442 1443 bool multiRsp:1; /* multiple trans2 responses for one request */ 1443 1444 bool multiEnd:1; /* both received */ ··· 1573 1572 kfree(param[i].node_name); 1574 1573 } 1575 1574 kfree(param); 1575 + } 1576 + 1577 + static inline bool is_interrupt_error(int error) 1578 + { 1579 + switch (error) { 1580 + case -EINTR: 1581 + case -ERESTARTSYS: 1582 + case -ERESTARTNOHAND: 1583 + case -ERESTARTNOINTR: 1584 + return true; 1585 + } 1586 + return false; 1587 + } 1588 + 1589 + static inline bool is_retryable_error(int error) 1590 + { 1591 + if (is_interrupt_error(error) || error == -EAGAIN) 1592 + return true; 1593 + return false; 1576 1594 } 1577 1595 1578 1596 #define MID_FREE 0
+20 -10
fs/cifs/cifssmb.c
··· 128 128 int rc; 129 129 struct dfs_cache_tgt_list tl; 130 130 struct dfs_cache_tgt_iterator *it = NULL; 131 - char tree[MAX_TREE_SIZE + 1]; 131 + char *tree; 132 132 const char *tcp_host; 133 133 size_t tcp_host_len; 134 134 const char *dfs_host; 135 135 size_t dfs_host_len; 136 136 137 + tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL); 138 + if (!tree) 139 + return -ENOMEM; 140 + 137 141 if (tcon->ipc) { 138 - snprintf(tree, sizeof(tree), "\\\\%s\\IPC$", 142 + snprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", 139 143 tcon->ses->server->hostname); 140 - return CIFSTCon(0, tcon->ses, tree, tcon, nlsc); 144 + rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc); 145 + goto out; 141 146 } 142 147 143 - if (!tcon->dfs_path) 144 - return CIFSTCon(0, tcon->ses, tcon->treeName, tcon, nlsc); 148 + if (!tcon->dfs_path) { 149 + rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon, nlsc); 150 + goto out; 151 + } 145 152 146 153 rc = dfs_cache_noreq_find(tcon->dfs_path + 1, NULL, &tl); 147 154 if (rc) 148 - return rc; 155 + goto out; 149 156 150 157 extract_unc_hostname(tcon->ses->server->hostname, &tcp_host, 151 158 &tcp_host_len); ··· 172 165 continue; 173 166 } 174 167 175 - snprintf(tree, sizeof(tree), "\\%s", tgt); 168 + snprintf(tree, MAX_TREE_SIZE, "\\%s", tgt); 176 169 177 170 rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc); 178 171 if (!rc) ··· 189 182 rc = -ENOENT; 190 183 } 191 184 dfs_cache_free_tgts(&tl); 185 + out: 186 + kfree(tree); 192 187 return rc; 193 188 } 194 189 #else ··· 2123 2114 2124 2115 for (j = 0; j < nr_pages; j++) { 2125 2116 unlock_page(wdata2->pages[j]); 2126 - if (rc != 0 && rc != -EAGAIN) { 2117 + if (rc != 0 && !is_retryable_error(rc)) { 2127 2118 SetPageError(wdata2->pages[j]); 2128 2119 end_page_writeback(wdata2->pages[j]); 2129 2120 put_page(wdata2->pages[j]); ··· 2132 2123 2133 2124 if (rc) { 2134 2125 kref_put(&wdata2->refcount, cifs_writedata_release); 2135 - if (rc == -EAGAIN) 2126 + if (is_retryable_error(rc)) 2136 2127 continue; 2137 2128 break; 2138 2129 } ··· 2141 2132 i += nr_pages; 2142 2133 } while (i < wdata->nr_pages); 2143 2134 2144 - mapping_set_error(inode->i_mapping, rc); 2135 + if (rc != 0 && !is_retryable_error(rc)) 2136 + mapping_set_error(inode->i_mapping, rc); 2145 2137 kref_put(&wdata->refcount, cifs_writedata_release); 2146 2138 } 2147 2139
+4 -3
fs/cifs/connect.c
··· 433 433 kfree(server->hostname); 434 434 435 435 server->hostname = extract_hostname(name); 436 - if (!server->hostname) { 437 - cifs_dbg(FYI, "%s: failed to extract hostname from target: %d\n", 438 - __func__, -ENOMEM); 436 + if (IS_ERR(server->hostname)) { 437 + cifs_dbg(FYI, 438 + "%s: failed to extract hostname from target: %ld\n", 439 + __func__, PTR_ERR(server->hostname)); 439 440 } 440 441 } 441 442
+1
fs/cifs/dfs_cache.c
··· 776 776 it->it_name = kstrndup(t->t_name, strlen(t->t_name), 777 777 GFP_KERNEL); 778 778 if (!it->it_name) { 779 + kfree(it); 779 780 rc = -ENOMEM; 780 781 goto err_free_it; 781 782 }
+35 -10
fs/cifs/file.c
··· 733 733 734 734 if (can_flush) { 735 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 739 if (tcon->unix_ext) 739 740 rc = cifs_get_inode_info_unix(&inode, full_path, ··· 1133 1132 1134 1133 /* 1135 1134 * Accessing maxBuf is racy with cifs_reconnect - need to store value 1136 - * and check it for zero before using. 1135 + * and check it before using. 1137 1136 */ 1138 1137 max_buf = tcon->ses->server->maxBuf; 1139 - if (!max_buf) { 1138 + if (max_buf < (sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE))) { 1140 1139 free_xid(xid); 1141 1140 return -EINVAL; 1142 1141 } 1143 1142 1143 + BUILD_BUG_ON(sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE) > 1144 + PAGE_SIZE); 1145 + max_buf = min_t(unsigned int, max_buf - sizeof(struct smb_hdr), 1146 + PAGE_SIZE); 1144 1147 max_num = (max_buf - sizeof(struct smb_hdr)) / 1145 1148 sizeof(LOCKING_ANDX_RANGE); 1146 1149 buf = kcalloc(max_num, sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL); ··· 1477 1472 1478 1473 /* 1479 1474 * Accessing maxBuf is racy with cifs_reconnect - need to store value 1480 - * and check it for zero before using. 1475 + * and check it before using. 1481 1476 */ 1482 1477 max_buf = tcon->ses->server->maxBuf; 1483 - if (!max_buf) 1478 + if (max_buf < (sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE))) 1484 1479 return -EINVAL; 1485 1480 1481 + BUILD_BUG_ON(sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE) > 1482 + PAGE_SIZE); 1483 + max_buf = min_t(unsigned int, max_buf - sizeof(struct smb_hdr), 1484 + PAGE_SIZE); 1486 1485 max_num = (max_buf - sizeof(struct smb_hdr)) / 1487 1486 sizeof(LOCKING_ANDX_RANGE); 1488 1487 buf = kcalloc(max_num, sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL); ··· 2119 2110 pgoff_t end, index; 2120 2111 struct cifs_writedata *wdata; 2121 2112 int rc = 0; 2113 + int saved_rc = 0; 2122 2114 unsigned int xid; 2123 2115 2124 2116 /* ··· 2148 2138 2149 2139 rc = server->ops->wait_mtu_credits(server, cifs_sb->wsize, 2150 2140 &wsize, &credits); 2151 - if (rc) 2141 + if (rc != 0) { 2142 + done = true; 2152 2143 break; 2144 + } 2153 2145 2154 2146 tofind = min((wsize / PAGE_SIZE) - 1, end - index) + 1; 2155 2147 ··· 2159 2147 &found_pages); 2160 2148 if (!wdata) { 2161 2149 rc = -ENOMEM; 2150 + done = true; 2162 2151 add_credits_and_wake_if(server, credits, 0); 2163 2152 break; 2164 2153 } ··· 2188 2175 if (rc != 0) { 2189 2176 add_credits_and_wake_if(server, wdata->credits, 0); 2190 2177 for (i = 0; i < nr_pages; ++i) { 2191 - if (rc == -EAGAIN) 2178 + if (is_retryable_error(rc)) 2192 2179 redirty_page_for_writepage(wbc, 2193 2180 wdata->pages[i]); 2194 2181 else ··· 2196 2183 end_page_writeback(wdata->pages[i]); 2197 2184 put_page(wdata->pages[i]); 2198 2185 } 2199 - if (rc != -EAGAIN) 2186 + if (!is_retryable_error(rc)) 2200 2187 mapping_set_error(mapping, rc); 2201 2188 } 2202 2189 kref_put(&wdata->refcount, cifs_writedata_release); ··· 2205 2192 index = saved_index; 2206 2193 continue; 2207 2194 } 2195 + 2196 + /* Return immediately if we received a signal during writing */ 2197 + if (is_interrupt_error(rc)) { 2198 + done = true; 2199 + break; 2200 + } 2201 + 2202 + if (rc != 0 && saved_rc == 0) 2203 + saved_rc = rc; 2208 2204 2209 2205 wbc->nr_to_write -= nr_pages; 2210 2206 if (wbc->nr_to_write <= 0) ··· 2231 2209 index = 0; 2232 2210 goto retry; 2233 2211 } 2212 + 2213 + if (saved_rc != 0) 2214 + rc = saved_rc; 2234 2215 2235 2216 if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) 2236 2217 mapping->writeback_index = index; ··· 2267 2242 set_page_writeback(page); 2268 2243 retry_write: 2269 2244 rc = cifs_partialpagewrite(page, 0, PAGE_SIZE); 2270 - if (rc == -EAGAIN) { 2271 - if (wbc->sync_mode == WB_SYNC_ALL) 2245 + if (is_retryable_error(rc)) { 2246 + if (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN) 2272 2247 goto retry_write; 2273 2248 redirty_page_for_writepage(wbc, page); 2274 2249 } else if (rc != 0) {
+10
fs/cifs/inode.c
··· 2257 2257 * the flush returns error? 2258 2258 */ 2259 2259 rc = filemap_write_and_wait(inode->i_mapping); 2260 + if (is_interrupt_error(rc)) { 2261 + rc = -ERESTARTSYS; 2262 + goto out; 2263 + } 2264 + 2260 2265 mapping_set_error(inode->i_mapping, rc); 2261 2266 rc = 0; 2262 2267 ··· 2405 2400 * the flush returns error? 2406 2401 */ 2407 2402 rc = filemap_write_and_wait(inode->i_mapping); 2403 + if (is_interrupt_error(rc)) { 2404 + rc = -ERESTARTSYS; 2405 + goto cifs_setattr_exit; 2406 + } 2407 + 2408 2408 mapping_set_error(inode->i_mapping, rc); 2409 2409 rc = 0; 2410 2410
+6 -2
fs/cifs/smb2file.c
··· 122 122 123 123 /* 124 124 * Accessing maxBuf is racy with cifs_reconnect - need to store value 125 - * and check it for zero before using. 125 + * and check it before using. 126 126 */ 127 127 max_buf = tcon->ses->server->maxBuf; 128 - if (!max_buf) 128 + if (max_buf < sizeof(struct smb2_lock_element)) 129 129 return -EINVAL; 130 130 131 + BUILD_BUG_ON(sizeof(struct smb2_lock_element) > PAGE_SIZE); 132 + max_buf = min_t(unsigned int, max_buf, PAGE_SIZE); 131 133 max_num = max_buf / sizeof(struct smb2_lock_element); 132 134 buf = kcalloc(max_num, sizeof(struct smb2_lock_element), GFP_KERNEL); 133 135 if (!buf) ··· 266 264 return -EINVAL; 267 265 } 268 266 267 + BUILD_BUG_ON(sizeof(struct smb2_lock_element) > PAGE_SIZE); 268 + max_buf = min_t(unsigned int, max_buf, PAGE_SIZE); 269 269 max_num = max_buf / sizeof(struct smb2_lock_element); 270 270 buf = kcalloc(max_num, sizeof(struct smb2_lock_element), GFP_KERNEL); 271 271 if (!buf) {
+22 -9
fs/cifs/smb2pdu.c
··· 162 162 int rc; 163 163 struct dfs_cache_tgt_list tl; 164 164 struct dfs_cache_tgt_iterator *it = NULL; 165 - char tree[MAX_TREE_SIZE + 1]; 165 + char *tree; 166 166 const char *tcp_host; 167 167 size_t tcp_host_len; 168 168 const char *dfs_host; 169 169 size_t dfs_host_len; 170 170 171 + tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL); 172 + if (!tree) 173 + return -ENOMEM; 174 + 171 175 if (tcon->ipc) { 172 - snprintf(tree, sizeof(tree), "\\\\%s\\IPC$", 176 + snprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", 173 177 tcon->ses->server->hostname); 174 - return SMB2_tcon(0, tcon->ses, tree, tcon, nlsc); 178 + rc = SMB2_tcon(0, tcon->ses, tree, tcon, nlsc); 179 + goto out; 175 180 } 176 181 177 - if (!tcon->dfs_path) 178 - return SMB2_tcon(0, tcon->ses, tcon->treeName, tcon, nlsc); 182 + if (!tcon->dfs_path) { 183 + rc = SMB2_tcon(0, tcon->ses, tcon->treeName, tcon, nlsc); 184 + goto out; 185 + } 179 186 180 187 rc = dfs_cache_noreq_find(tcon->dfs_path + 1, NULL, &tl); 181 188 if (rc) 182 - return rc; 189 + goto out; 183 190 184 191 extract_unc_hostname(tcon->ses->server->hostname, &tcp_host, 185 192 &tcp_host_len); ··· 206 199 continue; 207 200 } 208 201 209 - snprintf(tree, sizeof(tree), "\\%s", tgt); 202 + snprintf(tree, MAX_TREE_SIZE, "\\%s", tgt); 210 203 211 204 rc = SMB2_tcon(0, tcon->ses, tree, tcon, nlsc); 212 205 if (!rc) ··· 223 216 rc = -ENOENT; 224 217 } 225 218 dfs_cache_free_tgts(&tl); 219 + out: 220 + kfree(tree); 226 221 return rc; 227 222 } 228 223 #else ··· 3287 3278 if (rdata->credits) { 3288 3279 shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes, 3289 3280 SMB2_MAX_BUFFER_SIZE)); 3290 - shdr->CreditRequest = shdr->CreditCharge; 3281 + shdr->CreditRequest = 3282 + cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 1); 3291 3283 spin_lock(&server->req_lock); 3292 3284 server->credits += rdata->credits - 3293 3285 le16_to_cpu(shdr->CreditCharge); 3294 3286 spin_unlock(&server->req_lock); 3295 3287 wake_up(&server->request_q); 3288 + rdata->credits = le16_to_cpu(shdr->CreditCharge); 3296 3289 flags |= CIFS_HAS_CREDITS; 3297 3290 } 3298 3291 ··· 3566 3555 if (wdata->credits) { 3567 3556 shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->bytes, 3568 3557 SMB2_MAX_BUFFER_SIZE)); 3569 - shdr->CreditRequest = shdr->CreditCharge; 3558 + shdr->CreditRequest = 3559 + cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 1); 3570 3560 spin_lock(&server->req_lock); 3571 3561 server->credits += wdata->credits - 3572 3562 le16_to_cpu(shdr->CreditCharge); 3573 3563 spin_unlock(&server->req_lock); 3574 3564 wake_up(&server->request_q); 3565 + wdata->credits = le16_to_cpu(shdr->CreditCharge); 3575 3566 flags |= CIFS_HAS_CREDITS; 3576 3567 } 3577 3568
+92 -30
fs/cifs/transport.c
··· 387 387 if (rc < 0 && rc != -EINTR) 388 388 cifs_dbg(VFS, "Error %d sending data on socket to server\n", 389 389 rc); 390 - else 390 + else if (rc > 0) 391 391 rc = 0; 392 392 393 393 return rc; ··· 783 783 } 784 784 785 785 static void 786 - cifs_noop_callback(struct mid_q_entry *mid) 786 + cifs_compound_callback(struct mid_q_entry *mid) 787 787 { 788 + struct TCP_Server_Info *server = mid->server; 789 + unsigned int optype = mid->optype; 790 + unsigned int credits_received = 0; 791 + 792 + if (mid->mid_state == MID_RESPONSE_RECEIVED) { 793 + if (mid->resp_buf) 794 + credits_received = server->ops->get_credits(mid); 795 + else 796 + cifs_dbg(FYI, "Bad state for cancelled MID\n"); 797 + } 798 + 799 + add_credits(server, credits_received, optype); 800 + } 801 + 802 + static void 803 + cifs_compound_last_callback(struct mid_q_entry *mid) 804 + { 805 + cifs_compound_callback(mid); 806 + cifs_wake_up_task(mid); 807 + } 808 + 809 + static void 810 + cifs_cancelled_callback(struct mid_q_entry *mid) 811 + { 812 + cifs_compound_callback(mid); 813 + DeleteMidQEntry(mid); 788 814 } 789 815 790 816 int ··· 821 795 int i, j, rc = 0; 822 796 int timeout, optype; 823 797 struct mid_q_entry *midQ[MAX_COMPOUND]; 824 - unsigned int credits = 0; 798 + bool cancelled_mid[MAX_COMPOUND] = {false}; 799 + unsigned int credits[MAX_COMPOUND] = {0}; 825 800 char *buf; 826 801 827 802 timeout = flags & CIFS_TIMEOUT_MASK; ··· 840 813 return -ENOENT; 841 814 842 815 /* 843 - * Ensure that we do not send more than 50 overlapping requests 844 - * to the same server. We may make this configurable later or 845 - * use ses->maxReq. 816 + * Ensure we obtain 1 credit per request in the compound chain. 817 + * It can be optimized further by waiting for all the credits 818 + * at once but this can wait long enough if we don't have enough 819 + * credits due to some heavy operations in progress or the server 820 + * not granting us much, so a fallback to the current approach is 821 + * needed anyway. 846 822 */ 847 - rc = wait_for_free_request(ses->server, timeout, optype); 848 - if (rc) 849 - return rc; 823 + for (i = 0; i < num_rqst; i++) { 824 + rc = wait_for_free_request(ses->server, timeout, optype); 825 + if (rc) { 826 + /* 827 + * We haven't sent an SMB packet to the server yet but 828 + * we already obtained credits for i requests in the 829 + * compound chain - need to return those credits back 830 + * for future use. Note that we need to call add_credits 831 + * multiple times to match the way we obtained credits 832 + * in the first place and to account for in flight 833 + * requests correctly. 834 + */ 835 + for (j = 0; j < i; j++) 836 + add_credits(ses->server, 1, optype); 837 + return rc; 838 + } 839 + credits[i] = 1; 840 + } 850 841 851 842 /* 852 843 * Make sure that we sign in the same order that we send on this socket ··· 880 835 for (j = 0; j < i; j++) 881 836 cifs_delete_mid(midQ[j]); 882 837 mutex_unlock(&ses->server->srv_mutex); 838 + 883 839 /* Update # of requests on wire to server */ 884 - add_credits(ses->server, 1, optype); 840 + for (j = 0; j < num_rqst; j++) 841 + add_credits(ses->server, credits[j], optype); 885 842 return PTR_ERR(midQ[i]); 886 843 } 887 844 888 845 midQ[i]->mid_state = MID_REQUEST_SUBMITTED; 846 + midQ[i]->optype = optype; 889 847 /* 890 - * We don't invoke the callback compounds unless it is the last 891 - * request. 848 + * Invoke callback for every part of the compound chain 849 + * to calculate credits properly. Wake up this thread only when 850 + * the last element is received. 892 851 */ 893 852 if (i < num_rqst - 1) 894 - midQ[i]->callback = cifs_noop_callback; 853 + midQ[i]->callback = cifs_compound_callback; 854 + else 855 + midQ[i]->callback = cifs_compound_last_callback; 895 856 } 896 857 cifs_in_send_inc(ses->server); 897 858 rc = smb_send_rqst(ses->server, num_rqst, rqst, flags); ··· 911 860 912 861 mutex_unlock(&ses->server->srv_mutex); 913 862 914 - if (rc < 0) 863 + if (rc < 0) { 864 + /* Sending failed for some reason - return credits back */ 865 + for (i = 0; i < num_rqst; i++) 866 + add_credits(ses->server, credits[i], optype); 915 867 goto out; 868 + } 869 + 870 + /* 871 + * At this point the request is passed to the network stack - we assume 872 + * that any credits taken from the server structure on the client have 873 + * been spent and we can't return them back. Once we receive responses 874 + * we will collect credits granted by the server in the mid callbacks 875 + * and add those credits to the server structure. 876 + */ 916 877 917 878 /* 918 879 * Compounding is never used during session establish. ··· 938 875 939 876 for (i = 0; i < num_rqst; i++) { 940 877 rc = wait_for_response(ses->server, midQ[i]); 941 - if (rc != 0) { 878 + if (rc != 0) 879 + break; 880 + } 881 + if (rc != 0) { 882 + for (; i < num_rqst; i++) { 942 883 cifs_dbg(VFS, "Cancelling wait for mid %llu cmd: %d\n", 943 884 midQ[i]->mid, le16_to_cpu(midQ[i]->command)); 944 885 send_cancel(ses->server, &rqst[i], midQ[i]); 945 886 spin_lock(&GlobalMid_Lock); 946 887 if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED) { 947 888 midQ[i]->mid_flags |= MID_WAIT_CANCELLED; 948 - midQ[i]->callback = DeleteMidQEntry; 949 - spin_unlock(&GlobalMid_Lock); 950 - add_credits(ses->server, 1, optype); 951 - return rc; 889 + midQ[i]->callback = cifs_cancelled_callback; 890 + cancelled_mid[i] = true; 891 + credits[i] = 0; 952 892 } 953 893 spin_unlock(&GlobalMid_Lock); 954 894 } 955 895 } 956 - 957 - for (i = 0; i < num_rqst; i++) 958 - if (midQ[i]->resp_buf) 959 - credits += ses->server->ops->get_credits(midQ[i]); 960 - if (!credits) 961 - credits = 1; 962 896 963 897 for (i = 0; i < num_rqst; i++) { 964 898 if (rc < 0) ··· 963 903 964 904 rc = cifs_sync_mid_result(midQ[i], ses->server); 965 905 if (rc != 0) { 966 - add_credits(ses->server, credits, optype); 967 - return rc; 906 + /* mark this mid as cancelled to not free it below */ 907 + cancelled_mid[i] = true; 908 + goto out; 968 909 } 969 910 970 911 if (!midQ[i]->resp_buf || ··· 1012 951 * This is prevented above by using a noop callback that will not 1013 952 * wake this thread except for the very last PDU. 1014 953 */ 1015 - for (i = 0; i < num_rqst; i++) 1016 - cifs_delete_mid(midQ[i]); 1017 - add_credits(ses->server, credits, optype); 954 + for (i = 0; i < num_rqst; i++) { 955 + if (!cancelled_mid[i]) 956 + cifs_delete_mid(midQ[i]); 957 + } 1018 958 1019 959 return rc; 1020 960 }