From 02a7d2e613c60d4fd5896936b634bc839d4ae567 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 28 Jan 2019 11:15:30 +0100 Subject: [PATCH] 4.9-stable patches added patches: cifs-do-not-reconnect-tcp-session-in-add_credits.patch cifs-fix-possible-hang-during-async-mtu-reads-and-writes.patch --- ...reconnect-tcp-session-in-add_credits.patch | 145 ++++++++++++++++++ ...ng-during-async-mtu-reads-and-writes.patch | 55 +++++++ queue-4.9/series | 2 + 3 files changed, 202 insertions(+) create mode 100644 queue-4.9/cifs-do-not-reconnect-tcp-session-in-add_credits.patch create mode 100644 queue-4.9/cifs-fix-possible-hang-during-async-mtu-reads-and-writes.patch diff --git a/queue-4.9/cifs-do-not-reconnect-tcp-session-in-add_credits.patch b/queue-4.9/cifs-do-not-reconnect-tcp-session-in-add_credits.patch new file mode 100644 index 00000000000..cd5bd580fd7 --- /dev/null +++ b/queue-4.9/cifs-do-not-reconnect-tcp-session-in-add_credits.patch @@ -0,0 +1,145 @@ +From ef68e831840c40c7d01b328b3c0f5d8c4796c232 Mon Sep 17 00:00:00 2001 +From: Pavel Shilovsky +Date: Fri, 18 Jan 2019 17:25:36 -0800 +Subject: CIFS: Do not reconnect TCP session in add_credits() + +From: Pavel Shilovsky + +commit ef68e831840c40c7d01b328b3c0f5d8c4796c232 upstream. + +When executing add_credits() we currently call cifs_reconnect() +if the number of credits is zero and there are no requests in +flight. In this case we may call cifs_reconnect() recursively +twice and cause memory corruption given the following sequence +of functions: + +mid1.callback() -> add_credits() -> cifs_reconnect() -> +-> mid2.callback() -> add_credits() -> cifs_reconnect(). + +Fix this by avoiding to call cifs_reconnect() in add_credits() +and checking for zero credits in the demultiplex thread. + +Cc: +Signed-off-by: Pavel Shilovsky +Reviewed-by: Ronnie Sahlberg +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/connect.c | 21 +++++++++++++++++++++ + fs/cifs/smb2ops.c | 32 +++++++++++++++++++++++++------- + 2 files changed, 46 insertions(+), 7 deletions(-) + +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -518,6 +518,21 @@ server_unresponsive(struct TCP_Server_In + return false; + } + ++static inline bool ++zero_credits(struct TCP_Server_Info *server) ++{ ++ int val; ++ ++ spin_lock(&server->req_lock); ++ val = server->credits + server->echo_credits + server->oplock_credits; ++ if (server->in_flight == 0 && val == 0) { ++ spin_unlock(&server->req_lock); ++ return true; ++ } ++ spin_unlock(&server->req_lock); ++ return false; ++} ++ + static int + cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg) + { +@@ -530,6 +545,12 @@ cifs_readv_from_socket(struct TCP_Server + for (total_read = 0; msg_data_left(smb_msg); total_read += length) { + try_to_freeze(); + ++ /* reconnect if no credits and no requests in flight */ ++ if (zero_credits(server)) { ++ cifs_reconnect(server); ++ return -ECONNABORTED; ++ } ++ + if (server_unresponsive(server)) + return -ECONNABORTED; + +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -30,6 +30,7 @@ + #include "smb2glob.h" + #include "cifs_ioctl.h" + ++/* Change credits for different ops and return the total number of credits */ + static int + change_conf(struct TCP_Server_Info *server) + { +@@ -37,17 +38,15 @@ change_conf(struct TCP_Server_Info *serv + server->oplock_credits = server->echo_credits = 0; + switch (server->credits) { + case 0: +- return -1; ++ return 0; + case 1: + server->echoes = false; + server->oplocks = false; +- cifs_dbg(VFS, "disabling echoes and oplocks\n"); + break; + case 2: + server->echoes = true; + server->oplocks = false; + server->echo_credits = 1; +- cifs_dbg(FYI, "disabling oplocks\n"); + break; + default: + server->echoes = true; +@@ -60,14 +59,15 @@ change_conf(struct TCP_Server_Info *serv + server->echo_credits = 1; + } + server->credits -= server->echo_credits + server->oplock_credits; +- return 0; ++ return server->credits + server->echo_credits + server->oplock_credits; + } + + static void + smb2_add_credits(struct TCP_Server_Info *server, const unsigned int add, + const int optype) + { +- int *val, rc = 0; ++ int *val, rc = -1; ++ + spin_lock(&server->req_lock); + val = server->ops->get_credits_field(server, optype); + *val += add; +@@ -91,8 +91,26 @@ smb2_add_credits(struct TCP_Server_Info + } + spin_unlock(&server->req_lock); + wake_up(&server->request_q); +- if (rc) +- cifs_reconnect(server); ++ ++ if (server->tcpStatus == CifsNeedReconnect) ++ return; ++ ++ switch (rc) { ++ case -1: ++ /* change_conf hasn't been executed */ ++ break; ++ case 0: ++ cifs_dbg(VFS, "Possible client or server bug - zero credits\n"); ++ break; ++ case 1: ++ cifs_dbg(VFS, "disabling echoes and oplocks\n"); ++ break; ++ case 2: ++ cifs_dbg(FYI, "disabling oplocks\n"); ++ break; ++ default: ++ cifs_dbg(FYI, "add %u credits total=%d\n", add, rc); ++ } + } + + static void diff --git a/queue-4.9/cifs-fix-possible-hang-during-async-mtu-reads-and-writes.patch b/queue-4.9/cifs-fix-possible-hang-during-async-mtu-reads-and-writes.patch new file mode 100644 index 00000000000..e29b729bbbc --- /dev/null +++ b/queue-4.9/cifs-fix-possible-hang-during-async-mtu-reads-and-writes.patch @@ -0,0 +1,55 @@ +From acc58d0bab55a50e02c25f00bd6a210ee121595f Mon Sep 17 00:00:00 2001 +From: Pavel Shilovsky +Date: Thu, 17 Jan 2019 08:21:24 -0800 +Subject: CIFS: Fix possible hang during async MTU reads and writes + +From: Pavel Shilovsky + +commit acc58d0bab55a50e02c25f00bd6a210ee121595f upstream. + +When doing MTU i/o we need to leave some credits for +possible reopen requests and other operations happening +in parallel. Currently we leave 1 credit which is not +enough even for reopen only: we need at least 2 credits +if durable handle reconnect fails. Also there may be +other operations at the same time including compounding +ones which require 3 credits at a time each. Fix this +by leaving 8 credits which is big enough to cover most +scenarios. + +Was able to reproduce this when server was configured +to give out fewer credits than usual. + +The proper fix would be to reconnect a file handle first +and then obtain credits for an MTU request but this leads +to bigger code changes and should happen in other patches. + +Cc: +Signed-off-by: Pavel Shilovsky +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/smb2ops.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -148,14 +148,14 @@ smb2_wait_mtu_credits(struct TCP_Server_ + + scredits = server->credits; + /* can deadlock with reopen */ +- if (scredits == 1) { ++ if (scredits <= 8) { + *num = SMB2_MAX_BUFFER_SIZE; + *credits = 0; + break; + } + +- /* leave one credit for a possible reopen */ +- scredits--; ++ /* leave some credits for reopen and other ops */ ++ scredits -= 8; + *num = min_t(unsigned int, size, + scredits * SMB2_MAX_BUFFER_SIZE); + diff --git a/queue-4.9/series b/queue-4.9/series index 4fb31e12857..1faee3dd4e6 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -19,3 +19,5 @@ staging-rtl8188eu-add-device-code-for-d-link-dwa-121-rev-b1.patch tty-handle-problem-if-line-discipline-does-not-have-receive_buf.patch uart-fix-crash-in-uart_write-and-uart_put_char.patch tty-n_hdlc-fix-__might_sleep-warning.patch +cifs-fix-possible-hang-during-async-mtu-reads-and-writes.patch +cifs-do-not-reconnect-tcp-session-in-add_credits.patch -- 2.47.2