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-rc3-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb3 fixes from Steve French:
"A set of small smb3 fixes, some fixing various crediting issues
discovered during xfstest runs, five for stable"

* tag '5.0-rc3-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6:
cifs: print CIFSMaxBufSize as part of /proc/fs/cifs/DebugData
smb3: add credits we receive from oplock/break PDUs
CIFS: Fix mounts if the client is low on credits
CIFS: Do not assume one credit for async responses
CIFS: Fix credit calculations in compound mid callback
CIFS: Fix credit calculation for encrypted reads with errors
CIFS: Fix credits calculations for reads with errors
CIFS: Do not reconnect TCP session in add_credits()
smb3: Cleanup license mess
CIFS: Fix possible hang during async MTU reads and writes
cifs: fix memory leak of an allocated cifs_ntsd structure

+136 -67
+1
fs/cifs/cifs_debug.c
··· 252 252 seq_printf(m, ",ACL"); 253 253 #endif 254 254 seq_putc(m, '\n'); 255 + seq_printf(m, "CIFSMaxBufSize: %d\n", CIFSMaxBufSize); 255 256 seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid); 256 257 seq_printf(m, "Servers:"); 257 258
+23 -12
fs/cifs/cifssmb.c
··· 1549 1549 } 1550 1550 1551 1551 static int 1552 - cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) 1552 + __cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid, 1553 + bool malformed) 1553 1554 { 1554 1555 int length; 1555 - struct cifs_readdata *rdata = mid->callback_data; 1556 1556 1557 1557 length = cifs_discard_remaining_data(server); 1558 - dequeue_mid(mid, rdata->result); 1558 + dequeue_mid(mid, malformed); 1559 1559 mid->resp_buf = server->smallbuf; 1560 1560 server->smallbuf = NULL; 1561 1561 return length; 1562 + } 1563 + 1564 + static int 1565 + cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) 1566 + { 1567 + struct cifs_readdata *rdata = mid->callback_data; 1568 + 1569 + return __cifs_readv_discard(server, mid, rdata->result); 1562 1570 } 1563 1571 1564 1572 int ··· 1610 1602 return -1; 1611 1603 } 1612 1604 1605 + /* set up first two iov for signature check and to get credits */ 1606 + rdata->iov[0].iov_base = buf; 1607 + rdata->iov[0].iov_len = 4; 1608 + rdata->iov[1].iov_base = buf + 4; 1609 + rdata->iov[1].iov_len = server->total_read - 4; 1610 + cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n", 1611 + rdata->iov[0].iov_base, rdata->iov[0].iov_len); 1612 + cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n", 1613 + rdata->iov[1].iov_base, rdata->iov[1].iov_len); 1614 + 1613 1615 /* Was the SMB read successful? */ 1614 1616 rdata->result = server->ops->map_error(buf, false); 1615 1617 if (rdata->result != 0) { 1616 1618 cifs_dbg(FYI, "%s: server returned error %d\n", 1617 1619 __func__, rdata->result); 1618 - return cifs_readv_discard(server, mid); 1620 + /* normal error on read response */ 1621 + return __cifs_readv_discard(server, mid, false); 1619 1622 } 1620 1623 1621 1624 /* Is there enough to get to the rest of the READ_RSP header? */ ··· 1669 1650 return length; 1670 1651 server->total_read += length; 1671 1652 } 1672 - 1673 - /* set up first iov for signature check */ 1674 - rdata->iov[0].iov_base = buf; 1675 - rdata->iov[0].iov_len = 4; 1676 - rdata->iov[1].iov_base = buf + 4; 1677 - rdata->iov[1].iov_len = server->total_read - 4; 1678 - cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n", 1679 - rdata->iov[0].iov_base, server->total_read); 1680 1653 1681 1654 /* how much data is in the response? */ 1682 1655 #ifdef CONFIG_CIFS_SMB_DIRECT
+21
fs/cifs/connect.c
··· 720 720 return false; 721 721 } 722 722 723 + static inline bool 724 + zero_credits(struct TCP_Server_Info *server) 725 + { 726 + int val; 727 + 728 + spin_lock(&server->req_lock); 729 + val = server->credits + server->echo_credits + server->oplock_credits; 730 + if (server->in_flight == 0 && val == 0) { 731 + spin_unlock(&server->req_lock); 732 + return true; 733 + } 734 + spin_unlock(&server->req_lock); 735 + return false; 736 + } 737 + 723 738 static int 724 739 cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg) 725 740 { ··· 746 731 747 732 for (total_read = 0; msg_data_left(smb_msg); total_read += length) { 748 733 try_to_freeze(); 734 + 735 + /* reconnect if no credits and no requests in flight */ 736 + if (zero_credits(server)) { 737 + cifs_reconnect(server); 738 + return -ECONNABORTED; 739 + } 749 740 750 741 if (server_unresponsive(server)) 751 742 return -ECONNABORTED;
+17
fs/cifs/smb2inode.c
··· 293 293 int rc; 294 294 struct smb2_file_all_info *smb2_data; 295 295 __u32 create_options = 0; 296 + struct cifs_fid fid; 297 + bool no_cached_open = tcon->nohandlecache; 296 298 297 299 *adjust_tz = false; 298 300 *symlink = false; ··· 303 301 GFP_KERNEL); 304 302 if (smb2_data == NULL) 305 303 return -ENOMEM; 304 + 305 + /* If it is a root and its handle is cached then use it */ 306 + if (!strlen(full_path) && !no_cached_open) { 307 + rc = open_shroot(xid, tcon, &fid); 308 + if (rc) 309 + goto out; 310 + rc = SMB2_query_info(xid, tcon, fid.persistent_fid, 311 + fid.volatile_fid, smb2_data); 312 + close_shroot(&tcon->crfid); 313 + if (rc) 314 + goto out; 315 + move_smb2_info_to_cifs(data, smb2_data); 316 + goto out; 317 + } 318 + 306 319 if (backup_cred(cifs_sb)) 307 320 create_options |= CREATE_OPEN_BACKUP_INTENT; 308 321
+7
fs/cifs/smb2misc.c
··· 648 648 if (rsp->sync_hdr.Command != SMB2_OPLOCK_BREAK) 649 649 return false; 650 650 651 + if (rsp->sync_hdr.CreditRequest) { 652 + spin_lock(&server->req_lock); 653 + server->credits += le16_to_cpu(rsp->sync_hdr.CreditRequest); 654 + spin_unlock(&server->req_lock); 655 + wake_up(&server->request_q); 656 + } 657 + 651 658 if (rsp->StructureSize != 652 659 smb2_rsp_struct_sizes[SMB2_OPLOCK_BREAK_HE]) { 653 660 if (le16_to_cpu(rsp->StructureSize) == 44)
+47 -21
fs/cifs/smb2ops.c
··· 34 34 #include "cifs_ioctl.h" 35 35 #include "smbdirect.h" 36 36 37 + /* Change credits for different ops and return the total number of credits */ 37 38 static int 38 39 change_conf(struct TCP_Server_Info *server) 39 40 { ··· 42 41 server->oplock_credits = server->echo_credits = 0; 43 42 switch (server->credits) { 44 43 case 0: 45 - return -1; 44 + return 0; 46 45 case 1: 47 46 server->echoes = false; 48 47 server->oplocks = false; 49 - cifs_dbg(VFS, "disabling echoes and oplocks\n"); 50 48 break; 51 49 case 2: 52 50 server->echoes = true; 53 51 server->oplocks = false; 54 52 server->echo_credits = 1; 55 - cifs_dbg(FYI, "disabling oplocks\n"); 56 53 break; 57 54 default: 58 55 server->echoes = true; ··· 63 64 server->echo_credits = 1; 64 65 } 65 66 server->credits -= server->echo_credits + server->oplock_credits; 66 - return 0; 67 + return server->credits + server->echo_credits + server->oplock_credits; 67 68 } 68 69 69 70 static void 70 71 smb2_add_credits(struct TCP_Server_Info *server, const unsigned int add, 71 72 const int optype) 72 73 { 73 - int *val, rc = 0; 74 + int *val, rc = -1; 75 + 74 76 spin_lock(&server->req_lock); 75 77 val = server->ops->get_credits_field(server, optype); 76 78 ··· 101 101 } 102 102 spin_unlock(&server->req_lock); 103 103 wake_up(&server->request_q); 104 - if (rc) 105 - cifs_reconnect(server); 104 + 105 + if (server->tcpStatus == CifsNeedReconnect) 106 + return; 107 + 108 + switch (rc) { 109 + case -1: 110 + /* change_conf hasn't been executed */ 111 + break; 112 + case 0: 113 + cifs_dbg(VFS, "Possible client or server bug - zero credits\n"); 114 + break; 115 + case 1: 116 + cifs_dbg(VFS, "disabling echoes and oplocks\n"); 117 + break; 118 + case 2: 119 + cifs_dbg(FYI, "disabling oplocks\n"); 120 + break; 121 + default: 122 + cifs_dbg(FYI, "add %u credits total=%d\n", add, rc); 123 + } 106 124 } 107 125 108 126 static void ··· 154 136 { 155 137 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)mid->resp_buf; 156 138 157 - return le16_to_cpu(shdr->CreditRequest); 139 + if (mid->mid_state == MID_RESPONSE_RECEIVED 140 + || mid->mid_state == MID_RESPONSE_MALFORMED) 141 + return le16_to_cpu(shdr->CreditRequest); 142 + 143 + return 0; 158 144 } 159 145 160 146 static int ··· 187 165 188 166 scredits = server->credits; 189 167 /* can deadlock with reopen */ 190 - if (scredits == 1) { 168 + if (scredits <= 8) { 191 169 *num = SMB2_MAX_BUFFER_SIZE; 192 170 *credits = 0; 193 171 break; 194 172 } 195 173 196 - /* leave one credit for a possible reopen */ 197 - scredits--; 174 + /* leave some credits for reopen and other ops */ 175 + scredits -= 8; 198 176 *num = min_t(unsigned int, size, 199 177 scredits * SMB2_MAX_BUFFER_SIZE); 200 178 ··· 3211 3189 server->ops->is_status_pending(buf, server, 0)) 3212 3190 return -1; 3213 3191 3214 - rdata->result = server->ops->map_error(buf, false); 3192 + /* set up first two iov to get credits */ 3193 + rdata->iov[0].iov_base = buf; 3194 + rdata->iov[0].iov_len = 4; 3195 + rdata->iov[1].iov_base = buf + 4; 3196 + rdata->iov[1].iov_len = 3197 + min_t(unsigned int, buf_len, server->vals->read_rsp_size) - 4; 3198 + cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n", 3199 + rdata->iov[0].iov_base, rdata->iov[0].iov_len); 3200 + cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n", 3201 + rdata->iov[1].iov_base, rdata->iov[1].iov_len); 3202 + 3203 + rdata->result = server->ops->map_error(buf, true); 3215 3204 if (rdata->result != 0) { 3216 3205 cifs_dbg(FYI, "%s: server returned error %d\n", 3217 3206 __func__, rdata->result); 3218 - dequeue_mid(mid, rdata->result); 3207 + /* normal error on read response */ 3208 + dequeue_mid(mid, false); 3219 3209 return 0; 3220 3210 } 3221 3211 ··· 3299 3265 dequeue_mid(mid, rdata->result); 3300 3266 return 0; 3301 3267 } 3302 - 3303 - /* set up first iov for signature check */ 3304 - rdata->iov[0].iov_base = buf; 3305 - rdata->iov[0].iov_len = 4; 3306 - rdata->iov[1].iov_base = buf + 4; 3307 - rdata->iov[1].iov_len = server->vals->read_rsp_size - 4; 3308 - cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n", 3309 - rdata->iov[0].iov_base, server->vals->read_rsp_size); 3310 3268 3311 3269 length = rdata->copy_into_pages(server, rdata, &iter); 3312 3270
+19 -4
fs/cifs/smb2pdu.c
··· 2816 2816 int resp_buftype = CIFS_NO_BUFFER; 2817 2817 struct cifs_ses *ses = tcon->ses; 2818 2818 int flags = 0; 2819 + bool allocated = false; 2819 2820 2820 2821 cifs_dbg(FYI, "Query Info\n"); 2821 2822 ··· 2856 2855 "Error %d allocating memory for acl\n", 2857 2856 rc); 2858 2857 *dlen = 0; 2858 + rc = -ENOMEM; 2859 2859 goto qinf_exit; 2860 2860 } 2861 + allocated = true; 2861 2862 } 2862 2863 } 2863 2864 2864 2865 rc = smb2_validate_and_copy_iov(le16_to_cpu(rsp->OutputBufferOffset), 2865 2866 le32_to_cpu(rsp->OutputBufferLength), 2866 2867 &rsp_iov, min_len, *data); 2868 + if (rc && allocated) { 2869 + kfree(*data); 2870 + *data = NULL; 2871 + *dlen = 0; 2872 + } 2867 2873 2868 2874 qinf_exit: 2869 2875 SMB2_query_info_free(&rqst); ··· 2924 2916 { 2925 2917 struct TCP_Server_Info *server = mid->callback_data; 2926 2918 struct smb2_echo_rsp *rsp = (struct smb2_echo_rsp *)mid->resp_buf; 2927 - unsigned int credits_received = 1; 2919 + unsigned int credits_received = 0; 2928 2920 2929 - if (mid->mid_state == MID_RESPONSE_RECEIVED) 2921 + if (mid->mid_state == MID_RESPONSE_RECEIVED 2922 + || mid->mid_state == MID_RESPONSE_MALFORMED) 2930 2923 credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest); 2931 2924 2932 2925 DeleteMidQEntry(mid); ··· 3184 3175 struct TCP_Server_Info *server = tcon->ses->server; 3185 3176 struct smb2_sync_hdr *shdr = 3186 3177 (struct smb2_sync_hdr *)rdata->iov[0].iov_base; 3187 - unsigned int credits_received = 1; 3178 + unsigned int credits_received = 0; 3188 3179 struct smb_rqst rqst = { .rq_iov = rdata->iov, 3189 3180 .rq_nvec = 2, 3190 3181 .rq_pages = rdata->pages, ··· 3223 3214 task_io_account_read(rdata->got_bytes); 3224 3215 cifs_stats_bytes_read(tcon, rdata->got_bytes); 3225 3216 break; 3217 + case MID_RESPONSE_MALFORMED: 3218 + credits_received = le16_to_cpu(shdr->CreditRequest); 3219 + /* fall through */ 3226 3220 default: 3227 3221 if (rdata->result != -ENODATA) 3228 3222 rdata->result = -EIO; ··· 3411 3399 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); 3412 3400 unsigned int written; 3413 3401 struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf; 3414 - unsigned int credits_received = 1; 3402 + unsigned int credits_received = 0; 3415 3403 3416 3404 switch (mid->mid_state) { 3417 3405 case MID_RESPONSE_RECEIVED: ··· 3439 3427 case MID_RETRY_NEEDED: 3440 3428 wdata->result = -EAGAIN; 3441 3429 break; 3430 + case MID_RESPONSE_MALFORMED: 3431 + credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest); 3432 + /* fall through */ 3442 3433 default: 3443 3434 wdata->result = -EIO; 3444 3435 break;
-10
fs/cifs/trace.c
··· 3 3 * Copyright (C) 2018, Microsoft Corporation. 4 4 * 5 5 * Author(s): Steve French <stfrench@microsoft.com> 6 - * 7 - * This program is free software; you can redistribute it and/or modify 8 - * it under the terms of the GNU General Public License as published by 9 - * the Free Software Foundation; either version 2 of the License, or 10 - * (at your option) any later version. 11 - * 12 - * This program is distributed in the hope that it will be useful, 13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 15 - * the GNU General Public License for more details. 16 6 */ 17 7 #define CREATE_TRACE_POINTS 18 8 #include "trace.h"
-10
fs/cifs/trace.h
··· 3 3 * Copyright (C) 2018, Microsoft Corporation. 4 4 * 5 5 * Author(s): Steve French <stfrench@microsoft.com> 6 - * 7 - * This program is free software; you can redistribute it and/or modify 8 - * it under the terms of the GNU General Public License as published by 9 - * the Free Software Foundation; either version 2 of the License, or 10 - * (at your option) any later version. 11 - * 12 - * This program is distributed in the hope that it will be useful, 13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 15 - * the GNU General Public License for more details. 16 6 */ 17 7 #undef TRACE_SYSTEM 18 8 #define TRACE_SYSTEM cifs
+1 -10
fs/cifs/transport.c
··· 786 786 cifs_compound_callback(struct mid_q_entry *mid) 787 787 { 788 788 struct TCP_Server_Info *server = mid->server; 789 - unsigned int optype = mid->optype; 790 - unsigned int credits_received = 0; 791 789 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); 790 + add_credits(server, server->ops->get_credits(mid), mid->optype); 800 791 } 801 792 802 793 static void