From: Greg Kroah-Hartman Date: Mon, 25 Jul 2016 01:01:13 +0000 (-0700) Subject: 4.4-stable patches X-Git-Tag: v4.6.5~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0ef78fae93ebb25ec8380bcf0f1dd9bd9bd4652d;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: 53c700-fix-bug-on-untagged-commands.patch cifs-dynamic-allocation-of-ntlmssp-blob.patch file-names-with-trailing-period-or-space-need-special-case-conversion.patch fix-reconnect-to-not-defer-smb3-session-reconnect-long-after-socket-reconnect.patch s390-fix-test_fp_ctl-inline-assembly-contraints.patch scsi-fix-race-between-simultaneous-decrements-of-host_failed.patch xen-acpi-allow-xen-acpi-processor-driver-to-load-on-xen-4.7.patch --- diff --git a/queue-4.4/53c700-fix-bug-on-untagged-commands.patch b/queue-4.4/53c700-fix-bug-on-untagged-commands.patch new file mode 100644 index 00000000000..c4f152bc1a4 --- /dev/null +++ b/queue-4.4/53c700-fix-bug-on-untagged-commands.patch @@ -0,0 +1,52 @@ +From 8beb330044d0d1878c7b92290e91c0b889e92633 Mon Sep 17 00:00:00 2001 +From: James Bottomley +Date: Mon, 13 Jun 2016 22:00:07 -0700 +Subject: 53c700: fix BUG on untagged commands + +From: James Bottomley + +commit 8beb330044d0d1878c7b92290e91c0b889e92633 upstream. + +The untagged command case in the 53c700 driver has been broken since +host wide tags were enabled because the replaced scsi_find_tag() +function had a special case for the tag value SCSI_NO_TAG to retrieve +sdev->current_cmnd. The replacement function scsi_host_find_tag() has +no such special case and returns NULL causing untagged commands to +trigger a BUG() in the driver. Inspection shows that the 53c700 is the +only driver using this SCSI_NO_TAG case, so a local fix in the driver +suffices to fix this problem globally. + +Fixes: 64d513ac31b - "scsi: use host wide tags by default" +Reported-by: Helge Deller +Tested-by: Helge Deller +Signed-off-by: James Bottomley +Reviewed-by: Johannes Thumshirn +Reviewed-by: Ewan D. Milne +Acked-by: Christoph Hellwig +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/53c700.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/scsi/53c700.c ++++ b/drivers/scsi/53c700.c +@@ -1122,7 +1122,7 @@ process_script_interrupt(__u32 dsps, __u + } else { + struct scsi_cmnd *SCp; + +- SCp = scsi_host_find_tag(SDp->host, SCSI_NO_TAG); ++ SCp = SDp->current_cmnd; + if(unlikely(SCp == NULL)) { + sdev_printk(KERN_ERR, SDp, + "no saved request for untagged cmd\n"); +@@ -1826,7 +1826,7 @@ NCR_700_queuecommand_lck(struct scsi_cmn + slot->tag, slot); + } else { + slot->tag = SCSI_NO_TAG; +- /* must populate current_cmnd for scsi_host_find_tag to work */ ++ /* save current command for reselection */ + SCp->device->current_cmnd = SCp; + } + /* sanity check: some of the commands generated by the mid-layer diff --git a/queue-4.4/cifs-dynamic-allocation-of-ntlmssp-blob.patch b/queue-4.4/cifs-dynamic-allocation-of-ntlmssp-blob.patch new file mode 100644 index 00000000000..2b33a404fee --- /dev/null +++ b/queue-4.4/cifs-dynamic-allocation-of-ntlmssp-blob.patch @@ -0,0 +1,239 @@ +From b8da344b74c822e966c6d19d6b2321efe82c5d97 Mon Sep 17 00:00:00 2001 +From: Jerome Marchand +Date: Thu, 26 May 2016 11:52:25 +0200 +Subject: cifs: dynamic allocation of ntlmssp blob + +From: Jerome Marchand + +commit b8da344b74c822e966c6d19d6b2321efe82c5d97 upstream. + +In sess_auth_rawntlmssp_authenticate(), the ntlmssp blob is allocated +statically and its size is an "empirical" 5*sizeof(struct +_AUTHENTICATE_MESSAGE) (320B on x86_64). I don't know where this value +comes from or if it was ever appropriate, but it is currently +insufficient: the user and domain name in UTF16 could take 1kB by +themselves. Because of that, build_ntlmssp_auth_blob() might corrupt +memory (out-of-bounds write). The size of ntlmssp_blob in +SMB2_sess_setup() is too small too (sizeof(struct _NEGOTIATE_MESSAGE) ++ 500). + +This patch allocates the blob dynamically in +build_ntlmssp_auth_blob(). + +Signed-off-by: Jerome Marchand +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/ntlmssp.h | 2 - + fs/cifs/sess.c | 76 +++++++++++++++++++++++++++++------------------------- + fs/cifs/smb2pdu.c | 10 +------ + 3 files changed, 45 insertions(+), 43 deletions(-) + +--- a/fs/cifs/ntlmssp.h ++++ b/fs/cifs/ntlmssp.h +@@ -133,6 +133,6 @@ typedef struct _AUTHENTICATE_MESSAGE { + + int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, struct cifs_ses *ses); + void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, struct cifs_ses *ses); +-int build_ntlmssp_auth_blob(unsigned char *pbuffer, u16 *buflen, ++int build_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen, + struct cifs_ses *ses, + const struct nls_table *nls_cp); +--- a/fs/cifs/sess.c ++++ b/fs/cifs/sess.c +@@ -364,19 +364,43 @@ void build_ntlmssp_negotiate_blob(unsign + sec_blob->DomainName.MaximumLength = 0; + } + +-/* We do not malloc the blob, it is passed in pbuffer, because its +- maximum possible size is fixed and small, making this approach cleaner. +- This function returns the length of the data in the blob */ +-int build_ntlmssp_auth_blob(unsigned char *pbuffer, ++static int size_of_ntlmssp_blob(struct cifs_ses *ses) ++{ ++ int sz = sizeof(AUTHENTICATE_MESSAGE) + ses->auth_key.len ++ - CIFS_SESS_KEY_SIZE + CIFS_CPHTXT_SIZE + 2; ++ ++ if (ses->domainName) ++ sz += 2 * strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN); ++ else ++ sz += 2; ++ ++ if (ses->user_name) ++ sz += 2 * strnlen(ses->user_name, CIFS_MAX_USERNAME_LEN); ++ else ++ sz += 2; ++ ++ return sz; ++} ++ ++int build_ntlmssp_auth_blob(unsigned char **pbuffer, + u16 *buflen, + struct cifs_ses *ses, + const struct nls_table *nls_cp) + { + int rc; +- AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer; ++ AUTHENTICATE_MESSAGE *sec_blob; + __u32 flags; + unsigned char *tmp; + ++ rc = setup_ntlmv2_rsp(ses, nls_cp); ++ if (rc) { ++ cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc); ++ *buflen = 0; ++ goto setup_ntlmv2_ret; ++ } ++ *pbuffer = kmalloc(size_of_ntlmssp_blob(ses), GFP_KERNEL); ++ sec_blob = (AUTHENTICATE_MESSAGE *)*pbuffer; ++ + memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); + sec_blob->MessageType = NtLmAuthenticate; + +@@ -391,7 +415,7 @@ int build_ntlmssp_auth_blob(unsigned cha + flags |= NTLMSSP_NEGOTIATE_KEY_XCH; + } + +- tmp = pbuffer + sizeof(AUTHENTICATE_MESSAGE); ++ tmp = *pbuffer + sizeof(AUTHENTICATE_MESSAGE); + sec_blob->NegotiateFlags = cpu_to_le32(flags); + + sec_blob->LmChallengeResponse.BufferOffset = +@@ -399,13 +423,9 @@ int build_ntlmssp_auth_blob(unsigned cha + sec_blob->LmChallengeResponse.Length = 0; + sec_blob->LmChallengeResponse.MaximumLength = 0; + +- sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer); ++ sec_blob->NtChallengeResponse.BufferOffset = ++ cpu_to_le32(tmp - *pbuffer); + if (ses->user_name != NULL) { +- rc = setup_ntlmv2_rsp(ses, nls_cp); +- if (rc) { +- cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc); +- goto setup_ntlmv2_ret; +- } + memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE, + ses->auth_key.len - CIFS_SESS_KEY_SIZE); + tmp += ses->auth_key.len - CIFS_SESS_KEY_SIZE; +@@ -423,7 +443,7 @@ int build_ntlmssp_auth_blob(unsigned cha + } + + if (ses->domainName == NULL) { +- sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); ++ sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - *pbuffer); + sec_blob->DomainName.Length = 0; + sec_blob->DomainName.MaximumLength = 0; + tmp += 2; +@@ -432,14 +452,14 @@ int build_ntlmssp_auth_blob(unsigned cha + len = cifs_strtoUTF16((__le16 *)tmp, ses->domainName, + CIFS_MAX_USERNAME_LEN, nls_cp); + len *= 2; /* unicode is 2 bytes each */ +- sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); ++ sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - *pbuffer); + sec_blob->DomainName.Length = cpu_to_le16(len); + sec_blob->DomainName.MaximumLength = cpu_to_le16(len); + tmp += len; + } + + if (ses->user_name == NULL) { +- sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); ++ sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - *pbuffer); + sec_blob->UserName.Length = 0; + sec_blob->UserName.MaximumLength = 0; + tmp += 2; +@@ -448,13 +468,13 @@ int build_ntlmssp_auth_blob(unsigned cha + len = cifs_strtoUTF16((__le16 *)tmp, ses->user_name, + CIFS_MAX_USERNAME_LEN, nls_cp); + len *= 2; /* unicode is 2 bytes each */ +- sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); ++ sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - *pbuffer); + sec_blob->UserName.Length = cpu_to_le16(len); + sec_blob->UserName.MaximumLength = cpu_to_le16(len); + tmp += len; + } + +- sec_blob->WorkstationName.BufferOffset = cpu_to_le32(tmp - pbuffer); ++ sec_blob->WorkstationName.BufferOffset = cpu_to_le32(tmp - *pbuffer); + sec_blob->WorkstationName.Length = 0; + sec_blob->WorkstationName.MaximumLength = 0; + tmp += 2; +@@ -463,19 +483,19 @@ int build_ntlmssp_auth_blob(unsigned cha + (ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC)) + && !calc_seckey(ses)) { + memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE); +- sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); ++ sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer); + sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE); + sec_blob->SessionKey.MaximumLength = + cpu_to_le16(CIFS_CPHTXT_SIZE); + tmp += CIFS_CPHTXT_SIZE; + } else { +- sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); ++ sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer); + sec_blob->SessionKey.Length = 0; + sec_blob->SessionKey.MaximumLength = 0; + } + ++ *buflen = tmp - *pbuffer; + setup_ntlmv2_ret: +- *buflen = tmp - pbuffer; + return rc; + } + +@@ -1266,7 +1286,7 @@ sess_auth_rawntlmssp_authenticate(struct + struct cifs_ses *ses = sess_data->ses; + __u16 bytes_remaining; + char *bcc_ptr; +- char *ntlmsspblob = NULL; ++ unsigned char *ntlmsspblob = NULL; + u16 blob_len; + + cifs_dbg(FYI, "rawntlmssp session setup authenticate phase\n"); +@@ -1279,19 +1299,7 @@ sess_auth_rawntlmssp_authenticate(struct + /* Build security blob before we assemble the request */ + pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base; + smb_buf = (struct smb_hdr *)pSMB; +- /* +- * 5 is an empirical value, large enough to hold +- * authenticate message plus max 10 of av paris, +- * domain, user, workstation names, flags, etc. +- */ +- ntlmsspblob = kzalloc(5*sizeof(struct _AUTHENTICATE_MESSAGE), +- GFP_KERNEL); +- if (!ntlmsspblob) { +- rc = -ENOMEM; +- goto out; +- } +- +- rc = build_ntlmssp_auth_blob(ntlmsspblob, ++ rc = build_ntlmssp_auth_blob(&ntlmsspblob, + &blob_len, ses, sess_data->nls_cp); + if (rc) + goto out_free_ntlmsspblob; +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -591,7 +591,7 @@ SMB2_sess_setup(const unsigned int xid, + u16 blob_length = 0; + struct key *spnego_key = NULL; + char *security_blob = NULL; +- char *ntlmssp_blob = NULL; ++ unsigned char *ntlmssp_blob = NULL; + bool use_spnego = false; /* else use raw ntlmssp */ + + cifs_dbg(FYI, "Session Setup\n"); +@@ -716,13 +716,7 @@ ssetup_ntlmssp_authenticate: + iov[1].iov_len = blob_length; + } else if (phase == NtLmAuthenticate) { + req->hdr.SessionId = ses->Suid; +- ntlmssp_blob = kzalloc(sizeof(struct _NEGOTIATE_MESSAGE) + 500, +- GFP_KERNEL); +- if (ntlmssp_blob == NULL) { +- rc = -ENOMEM; +- goto ssetup_exit; +- } +- rc = build_ntlmssp_auth_blob(ntlmssp_blob, &blob_length, ses, ++ rc = build_ntlmssp_auth_blob(&ntlmssp_blob, &blob_length, ses, + nls_cp); + if (rc) { + cifs_dbg(FYI, "build_ntlmssp_auth_blob failed %d\n", diff --git a/queue-4.4/file-names-with-trailing-period-or-space-need-special-case-conversion.patch b/queue-4.4/file-names-with-trailing-period-or-space-need-special-case-conversion.patch new file mode 100644 index 00000000000..5feeea716b0 --- /dev/null +++ b/queue-4.4/file-names-with-trailing-period-or-space-need-special-case-conversion.patch @@ -0,0 +1,98 @@ +From 45e8a2583d97ca758a55c608f78c4cef562644d1 Mon Sep 17 00:00:00 2001 +From: Steve French +Date: Wed, 22 Jun 2016 21:07:32 -0500 +Subject: File names with trailing period or space need special case conversion + +From: Steve French + +commit 45e8a2583d97ca758a55c608f78c4cef562644d1 upstream. + +POSIX allows files with trailing spaces or a trailing period but +SMB3 does not, so convert these using the normal Services For Mac +mapping as we do for other reserved characters such as + : < > | ? * +This is similar to what Macs do for the same problem over SMB3. + +Signed-off-by: Steve French +Acked-by: Pavel Shilovsky +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/cifs_unicode.c | 33 +++++++++++++++++++++++++++++---- + fs/cifs/cifs_unicode.h | 2 ++ + 2 files changed, 31 insertions(+), 4 deletions(-) + +--- a/fs/cifs/cifs_unicode.c ++++ b/fs/cifs/cifs_unicode.c +@@ -101,6 +101,12 @@ convert_sfm_char(const __u16 src_char, c + case SFM_SLASH: + *target = '\\'; + break; ++ case SFM_SPACE: ++ *target = ' '; ++ break; ++ case SFM_PERIOD: ++ *target = '.'; ++ break; + default: + return false; + } +@@ -404,7 +410,7 @@ static __le16 convert_to_sfu_char(char s + return dest_char; + } + +-static __le16 convert_to_sfm_char(char src_char) ++static __le16 convert_to_sfm_char(char src_char, bool end_of_string) + { + __le16 dest_char; + +@@ -427,6 +433,18 @@ static __le16 convert_to_sfm_char(char s + case '|': + dest_char = cpu_to_le16(SFM_PIPE); + break; ++ case '.': ++ if (end_of_string) ++ dest_char = cpu_to_le16(SFM_PERIOD); ++ else ++ dest_char = 0; ++ break; ++ case ' ': ++ if (end_of_string) ++ dest_char = cpu_to_le16(SFM_SPACE); ++ else ++ dest_char = 0; ++ break; + default: + dest_char = 0; + } +@@ -469,9 +487,16 @@ cifsConvertToUTF16(__le16 *target, const + /* see if we must remap this char */ + if (map_chars == SFU_MAP_UNI_RSVD) + dst_char = convert_to_sfu_char(src_char); +- else if (map_chars == SFM_MAP_UNI_RSVD) +- dst_char = convert_to_sfm_char(src_char); +- else ++ else if (map_chars == SFM_MAP_UNI_RSVD) { ++ bool end_of_string; ++ ++ if (i == srclen - 1) ++ end_of_string = true; ++ else ++ end_of_string = false; ++ ++ dst_char = convert_to_sfm_char(src_char, end_of_string); ++ } else + dst_char = 0; + /* + * FIXME: We can not handle remapping backslash (UNI_SLASH) +--- a/fs/cifs/cifs_unicode.h ++++ b/fs/cifs/cifs_unicode.h +@@ -64,6 +64,8 @@ + #define SFM_LESSTHAN ((__u16) 0xF023) + #define SFM_PIPE ((__u16) 0xF027) + #define SFM_SLASH ((__u16) 0xF026) ++#define SFM_PERIOD ((__u16) 0xF028) ++#define SFM_SPACE ((__u16) 0xF029) + + /* + * Mapping mechanism to use when one of the seven reserved characters is diff --git a/queue-4.4/fix-reconnect-to-not-defer-smb3-session-reconnect-long-after-socket-reconnect.patch b/queue-4.4/fix-reconnect-to-not-defer-smb3-session-reconnect-long-after-socket-reconnect.patch new file mode 100644 index 00000000000..1fadf866447 --- /dev/null +++ b/queue-4.4/fix-reconnect-to-not-defer-smb3-session-reconnect-long-after-socket-reconnect.patch @@ -0,0 +1,78 @@ +From 4fcd1813e6404dd4420c7d12fb483f9320f0bf93 Mon Sep 17 00:00:00 2001 +From: Steve French +Date: Wed, 22 Jun 2016 20:12:05 -0500 +Subject: Fix reconnect to not defer smb3 session reconnect long after socket reconnect + +From: Steve French + +commit 4fcd1813e6404dd4420c7d12fb483f9320f0bf93 upstream. + +Azure server blocks clients that open a socket and don't do anything on it. +In our reconnect scenarios, we can reconnect the tcp session and +detect the socket is available but we defer the negprot and SMB3 session +setup and tree connect reconnection until the next i/o is requested, but +this looks suspicous to some servers who expect SMB3 negprog and session +setup soon after a socket is created. + +In the echo thread, reconnect SMB3 sessions and tree connections +that are disconnected. A later patch will replay persistent (and +resilient) handle opens. + +Signed-off-by: Steve French +Acked-by: Pavel Shilovsky +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/connect.c | 4 +++- + fs/cifs/smb2pdu.c | 27 +++++++++++++++++++++++++++ + 2 files changed, 30 insertions(+), 1 deletion(-) + +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -425,7 +425,9 @@ cifs_echo_request(struct work_struct *wo + * server->ops->need_neg() == true. Also, no need to ping if + * we got a response recently. + */ +- if (!server->ops->need_neg || server->ops->need_neg(server) || ++ ++ if (server->tcpStatus == CifsNeedReconnect || ++ server->tcpStatus == CifsExiting || server->tcpStatus == CifsNew || + (server->ops->can_echo && !server->ops->can_echo(server)) || + time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ)) + goto requeue_echo; +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -1820,6 +1820,33 @@ SMB2_echo(struct TCP_Server_Info *server + + cifs_dbg(FYI, "In echo request\n"); + ++ if (server->tcpStatus == CifsNeedNegotiate) { ++ struct list_head *tmp, *tmp2; ++ struct cifs_ses *ses; ++ struct cifs_tcon *tcon; ++ ++ cifs_dbg(FYI, "Need negotiate, reconnecting tcons\n"); ++ spin_lock(&cifs_tcp_ses_lock); ++ list_for_each(tmp, &server->smb_ses_list) { ++ ses = list_entry(tmp, struct cifs_ses, smb_ses_list); ++ list_for_each(tmp2, &ses->tcon_list) { ++ tcon = list_entry(tmp2, struct cifs_tcon, ++ tcon_list); ++ /* add check for persistent handle reconnect */ ++ if (tcon && tcon->need_reconnect) { ++ spin_unlock(&cifs_tcp_ses_lock); ++ rc = smb2_reconnect(SMB2_ECHO, tcon); ++ spin_lock(&cifs_tcp_ses_lock); ++ } ++ } ++ } ++ spin_unlock(&cifs_tcp_ses_lock); ++ } ++ ++ /* if no session, renegotiate failed above */ ++ if (server->tcpStatus == CifsNeedNegotiate) ++ return -EIO; ++ + rc = small_smb2_init(SMB2_ECHO, NULL, (void **)&req); + if (rc) + return rc; diff --git a/queue-4.4/s390-fix-test_fp_ctl-inline-assembly-contraints.patch b/queue-4.4/s390-fix-test_fp_ctl-inline-assembly-contraints.patch new file mode 100644 index 00000000000..def4e0b7832 --- /dev/null +++ b/queue-4.4/s390-fix-test_fp_ctl-inline-assembly-contraints.patch @@ -0,0 +1,39 @@ +From bcf4dd5f9ee096bd1510f838dd4750c35df4e38b Mon Sep 17 00:00:00 2001 +From: Martin Schwidefsky +Date: Mon, 27 Jun 2016 17:06:45 +0200 +Subject: s390: fix test_fp_ctl inline assembly contraints + +From: Martin Schwidefsky + +commit bcf4dd5f9ee096bd1510f838dd4750c35df4e38b upstream. + +The test_fp_ctl function is used to test if a given value is a valid +floating-point control. The inline assembly in test_fp_ctl uses an +incorrect constraint for the 'orig_fpc' variable. If the compiler +chooses the same register for 'fpc' and 'orig_fpc' the test_fp_ctl() +function always returns true. This allows user space to trigger +kernel oopses with invalid floating-point control values on the +signal stack. + +This problem has been introduced with git commit 4725c86055f5bbdcdf +"s390: fix save and restore of the floating-point-control register" + +Reviewed-by: Heiko Carstens +Signed-off-by: Martin Schwidefsky +Signed-off-by: Greg Kroah-Hartman + +--- + arch/s390/include/asm/fpu/api.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/s390/include/asm/fpu/api.h ++++ b/arch/s390/include/asm/fpu/api.h +@@ -22,7 +22,7 @@ static inline int test_fp_ctl(u32 fpc) + " la %0,0\n" + "1:\n" + EX_TABLE(0b,1b) +- : "=d" (rc), "=d" (orig_fpc) ++ : "=d" (rc), "=&d" (orig_fpc) + : "d" (fpc), "0" (-EINVAL)); + return rc; + } diff --git a/queue-4.4/scsi-fix-race-between-simultaneous-decrements-of-host_failed.patch b/queue-4.4/scsi-fix-race-between-simultaneous-decrements-of-host_failed.patch new file mode 100644 index 00000000000..6cef63bd60d --- /dev/null +++ b/queue-4.4/scsi-fix-race-between-simultaneous-decrements-of-host_failed.patch @@ -0,0 +1,94 @@ +From 72d8c36ec364c82bf1bf0c64dfa1041cfaf139f7 Mon Sep 17 00:00:00 2001 +From: Wei Fang +Date: Tue, 7 Jun 2016 14:53:56 +0800 +Subject: scsi: fix race between simultaneous decrements of ->host_failed + +From: Wei Fang + +commit 72d8c36ec364c82bf1bf0c64dfa1041cfaf139f7 upstream. + +sas_ata_strategy_handler() adds the works of the ata error handler to +system_unbound_wq. This workqueue asynchronously runs work items, so the +ata error handler will be performed concurrently on different CPUs. In +this case, ->host_failed will be decreased simultaneously in +scsi_eh_finish_cmd() on different CPUs, and become abnormal. + +It will lead to permanently inequality between ->host_failed and +->host_busy, and scsi error handler thread won't start running. IO +errors after that won't be handled. + +Since all scmds must have been handled in the strategy handler, just +remove the decrement in scsi_eh_finish_cmd() and zero ->host_busy after +the strategy handler to fix this race. + +Fixes: 50824d6c5657 ("[SCSI] libsas: async ata-eh") +Signed-off-by: Wei Fang +Reviewed-by: James Bottomley +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman + +--- + Documentation/scsi/scsi_eh.txt | 8 ++++++-- + drivers/ata/libata-eh.c | 2 +- + drivers/scsi/scsi_error.c | 4 +++- + 3 files changed, 10 insertions(+), 4 deletions(-) + +--- a/Documentation/scsi/scsi_eh.txt ++++ b/Documentation/scsi/scsi_eh.txt +@@ -263,19 +263,23 @@ scmd->allowed. + + 3. scmd recovered + ACTION: scsi_eh_finish_cmd() is invoked to EH-finish scmd +- - shost->host_failed-- + - clear scmd->eh_eflags + - scsi_setup_cmd_retry() + - move from local eh_work_q to local eh_done_q + LOCKING: none ++ CONCURRENCY: at most one thread per separate eh_work_q to ++ keep queue manipulation lockless + + 4. EH completes + ACTION: scsi_eh_flush_done_q() retries scmds or notifies upper +- layer of failure. ++ layer of failure. May be called concurrently but must have ++ a no more than one thread per separate eh_work_q to ++ manipulate the queue locklessly + - scmd is removed from eh_done_q and scmd->eh_entry is cleared + - if retry is necessary, scmd is requeued using + scsi_queue_insert() + - otherwise, scsi_finish_command() is invoked for scmd ++ - zero shost->host_failed + LOCKING: queue or finish function performs appropriate locking + + +--- a/drivers/ata/libata-eh.c ++++ b/drivers/ata/libata-eh.c +@@ -606,7 +606,7 @@ void ata_scsi_error(struct Scsi_Host *ho + ata_scsi_port_error_handler(host, ap); + + /* finish or retry handled scmd's and clean up */ +- WARN_ON(host->host_failed || !list_empty(&eh_work_q)); ++ WARN_ON(!list_empty(&eh_work_q)); + + DPRINTK("EXIT\n"); + } +--- a/drivers/scsi/scsi_error.c ++++ b/drivers/scsi/scsi_error.c +@@ -1127,7 +1127,6 @@ static int scsi_eh_action(struct scsi_cm + */ + void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q) + { +- scmd->device->host->host_failed--; + scmd->eh_eflags = 0; + list_move_tail(&scmd->eh_entry, done_q); + } +@@ -2226,6 +2225,9 @@ int scsi_error_handler(void *data) + else + scsi_unjam_host(shost); + ++ /* All scmds have been handled */ ++ shost->host_failed = 0; ++ + /* + * Note - if the above fails completely, the action is to take + * individual devices offline and flush the queue of any diff --git a/queue-4.4/series b/queue-4.4/series index a99f35ea0e2..a6a1f464543 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -132,3 +132,10 @@ arm-dts-armada-38x-fix-mbus_id-for-crypto-sram-on-armada-385-linksys.patch arm-mvebu-fix-hw-i-o-coherency-related-deadlocks.patch ovl-copy-up-underlying-inode-s-i_mode-to-overlay-inode.patch ovl-verify-upper-dentry-in-ovl_remove_and_whiteout.patch +scsi-fix-race-between-simultaneous-decrements-of-host_failed.patch +s390-fix-test_fp_ctl-inline-assembly-contraints.patch +53c700-fix-bug-on-untagged-commands.patch +fix-reconnect-to-not-defer-smb3-session-reconnect-long-after-socket-reconnect.patch +cifs-dynamic-allocation-of-ntlmssp-blob.patch +file-names-with-trailing-period-or-space-need-special-case-conversion.patch +xen-acpi-allow-xen-acpi-processor-driver-to-load-on-xen-4.7.patch diff --git a/queue-4.4/xen-acpi-allow-xen-acpi-processor-driver-to-load-on-xen-4.7.patch b/queue-4.4/xen-acpi-allow-xen-acpi-processor-driver-to-load-on-xen-4.7.patch new file mode 100644 index 00000000000..18b9125cce6 --- /dev/null +++ b/queue-4.4/xen-acpi-allow-xen-acpi-processor-driver-to-load-on-xen-4.7.patch @@ -0,0 +1,81 @@ +From 6f2d9d99213514360034c6d52d2c3919290b3504 Mon Sep 17 00:00:00 2001 +From: Jan Beulich +Date: Fri, 8 Jul 2016 06:15:07 -0600 +Subject: xen/acpi: allow xen-acpi-processor driver to load on Xen 4.7 + +From: Jan Beulich + +commit 6f2d9d99213514360034c6d52d2c3919290b3504 upstream. + +As of Xen 4.7 PV CPUID doesn't expose either of CPUID[1].ECX[7] and +CPUID[0x80000007].EDX[7] anymore, causing the driver to fail to load on +both Intel and AMD systems. Doing any kind of hardware capability +checks in the driver as a prerequisite was wrong anyway: With the +hypervisor being in charge, all such checking should be done by it. If +ACPI data gets uploaded despite some missing capability, the hypervisor +is free to ignore part or all of that data. + +Ditch the entire check_prereq() function, and do the only valid check +(xen_initial_domain()) in the caller in its place. + +Signed-off-by: Jan Beulich +Signed-off-by: David Vrabel +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/xen/xen-acpi-processor.c | 35 +++-------------------------------- + 1 file changed, 3 insertions(+), 32 deletions(-) + +--- a/drivers/xen/xen-acpi-processor.c ++++ b/drivers/xen/xen-acpi-processor.c +@@ -423,36 +423,7 @@ upload: + + return 0; + } +-static int __init check_prereq(void) +-{ +- struct cpuinfo_x86 *c = &cpu_data(0); +- +- if (!xen_initial_domain()) +- return -ENODEV; +- +- if (!acpi_gbl_FADT.smi_command) +- return -ENODEV; + +- if (c->x86_vendor == X86_VENDOR_INTEL) { +- if (!cpu_has(c, X86_FEATURE_EST)) +- return -ENODEV; +- +- return 0; +- } +- if (c->x86_vendor == X86_VENDOR_AMD) { +- /* Copied from powernow-k8.h, can't include ../cpufreq/powernow +- * as we get compile warnings for the static functions. +- */ +-#define CPUID_FREQ_VOLT_CAPABILITIES 0x80000007 +-#define USE_HW_PSTATE 0x00000080 +- u32 eax, ebx, ecx, edx; +- cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx); +- if ((edx & USE_HW_PSTATE) != USE_HW_PSTATE) +- return -ENODEV; +- return 0; +- } +- return -ENODEV; +-} + /* acpi_perf_data is a pointer to percpu data. */ + static struct acpi_processor_performance __percpu *acpi_perf_data; + +@@ -509,10 +480,10 @@ struct notifier_block xen_acpi_processor + static int __init xen_acpi_processor_init(void) + { + unsigned int i; +- int rc = check_prereq(); ++ int rc; + +- if (rc) +- return rc; ++ if (!xen_initial_domain()) ++ return -ENODEV; + + nr_acpi_bits = get_max_acpi_id() + 1; + acpi_ids_done = kcalloc(BITS_TO_LONGS(nr_acpi_bits), sizeof(unsigned long), GFP_KERNEL);