|
| 1 | +cifs: cifs_chan_is_iface_active should be called with chan_lock held |
| 2 | + |
| 3 | +jira LE-4669 |
| 4 | +Rebuild_History Non-Buildable kernel-4.18.0-553.82.1.el8_10 |
| 5 | +commit-author Shyam Prasad N <sprasad@microsoft.com> |
| 6 | +commit 7257bcf3bdc785eabc4eef1f329a59815b032508 |
| 7 | +Empty-Commit: Cherry-Pick Conflicts during history rebuild. |
| 8 | +Will be included in final tarball splat. Ref for failed cherry-pick at: |
| 9 | +ciq/ciq_backports/kernel-4.18.0-553.82.1.el8_10/7257bcf3.failed |
| 10 | + |
| 11 | +cifs_chan_is_iface_active checks the channels of a session to see |
| 12 | +if the associated iface is active. This should always happen |
| 13 | +with chan_lock held. However, these two callers of this function |
| 14 | +were missing this locking. |
| 15 | + |
| 16 | +This change makes sure the function calls are protected with |
| 17 | +proper locking. |
| 18 | + |
| 19 | +Fixes: b54034a73baf ("cifs: during reconnect, update interface if necessary") |
| 20 | +Fixes: fa1d0508bdd4 ("cifs: account for primary channel in the interface list") |
| 21 | + Cc: stable@vger.kernel.org |
| 22 | + Signed-off-by: Shyam Prasad N <sprasad@microsoft.com> |
| 23 | + Signed-off-by: Steve French <stfrench@microsoft.com> |
| 24 | +(cherry picked from commit 7257bcf3bdc785eabc4eef1f329a59815b032508) |
| 25 | + Signed-off-by: Jonathan Maple <jmaple@ciq.com> |
| 26 | + |
| 27 | +# Conflicts: |
| 28 | +# fs/cifs/connect.c |
| 29 | +# fs/cifs/smb2ops.c |
| 30 | +diff --cc fs/cifs/connect.c |
| 31 | +index ca2926c7b59e,dc9b95ca71e6..000000000000 |
| 32 | +--- a/fs/cifs/connect.c |
| 33 | ++++ b/fs/cifs/connect.c |
| 34 | +@@@ -207,50 -211,88 +207,60 @@@ static void cifs_mark_tcp_ses_conns_for |
| 35 | + * before reconnecting the tcp session, mark the smb session (uid) and the tid bad so they |
| 36 | + * are not used until reconnected. |
| 37 | + */ |
| 38 | + - cifs_dbg(FYI, "%s: marking necessary sessions and tcons for reconnect\n", __func__); |
| 39 | + + cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n", __func__); |
| 40 | + |
| 41 | + /* If server is a channel, select the primary channel */ |
| 42 | + - pserver = SERVER_IS_CHAN(server) ? server->primary_server : server; |
| 43 | + - |
| 44 | + - /* |
| 45 | + - * if the server has been marked for termination, there is a |
| 46 | + - * chance that the remaining channels all need reconnect. To be |
| 47 | + - * on the safer side, mark the session and trees for reconnect |
| 48 | + - * for this scenario. This might cause a few redundant session |
| 49 | + - * setup and tree connect requests, but it is better than not doing |
| 50 | + - * a tree connect when needed, and all following requests failing |
| 51 | + - */ |
| 52 | + - if (server->terminate) { |
| 53 | + - mark_smb_session = true; |
| 54 | + - server = pserver; |
| 55 | + - } |
| 56 | + + pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server; |
| 57 | + |
| 58 | + spin_lock(&cifs_tcp_ses_lock); |
| 59 | + - list_for_each_entry_safe(ses, nses, &pserver->smb_ses_list, smb_ses_list) { |
| 60 | + + list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) { |
| 61 | + /* check if iface is still active */ |
| 62 | +- if (!cifs_chan_is_iface_active(ses, server)) |
| 63 | +- cifs_chan_update_iface(ses, server); |
| 64 | +- |
| 65 | + spin_lock(&ses->chan_lock); |
| 66 | +++<<<<<<< HEAD:fs/cifs/connect.c |
| 67 | + + if (cifs_chan_needs_reconnect(ses, server)) |
| 68 | + + goto next_session; |
| 69 | +++======= |
| 70 | ++ if (!cifs_chan_is_iface_active(ses, server)) { |
| 71 | ++ spin_unlock(&ses->chan_lock); |
| 72 | ++ cifs_chan_update_iface(ses, server); |
| 73 | ++ spin_lock(&ses->chan_lock); |
| 74 | ++ } |
| 75 | ++ |
| 76 | ++ if (!mark_smb_session && cifs_chan_needs_reconnect(ses, server)) { |
| 77 | ++ spin_unlock(&ses->chan_lock); |
| 78 | ++ continue; |
| 79 | ++ } |
| 80 | +++>>>>>>> 7257bcf3bdc7 (cifs: cifs_chan_is_iface_active should be called with chan_lock held):fs/smb/client/connect.c |
| 81 | + |
| 82 | + - if (mark_smb_session) |
| 83 | + - CIFS_SET_ALL_CHANS_NEED_RECONNECT(ses); |
| 84 | + - else |
| 85 | + - cifs_chan_set_need_reconnect(ses, server); |
| 86 | + - |
| 87 | + - cifs_dbg(FYI, "%s: channel connect bitmap: 0x%lx\n", |
| 88 | + - __func__, ses->chans_need_reconnect); |
| 89 | + + cifs_chan_set_need_reconnect(ses, server); |
| 90 | + |
| 91 | + /* If all channels need reconnect, then tcon needs reconnect */ |
| 92 | + - if (!mark_smb_session && !CIFS_ALL_CHANS_NEED_RECONNECT(ses)) { |
| 93 | + - spin_unlock(&ses->chan_lock); |
| 94 | + - continue; |
| 95 | + - } |
| 96 | + - spin_unlock(&ses->chan_lock); |
| 97 | + + if (!CIFS_ALL_CHANS_NEED_RECONNECT(ses)) |
| 98 | + + goto next_session; |
| 99 | + |
| 100 | + - spin_lock(&ses->ses_lock); |
| 101 | + - ses->ses_status = SES_NEED_RECON; |
| 102 | + - spin_unlock(&ses->ses_lock); |
| 103 | + + num_sessions++; |
| 104 | + |
| 105 | + - list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { |
| 106 | + + list_for_each_entry(tcon, &ses->tcon_list, tcon_list) |
| 107 | + tcon->need_reconnect = true; |
| 108 | + - spin_lock(&tcon->tc_lock); |
| 109 | + - tcon->status = TID_NEED_RECON; |
| 110 | + - spin_unlock(&tcon->tc_lock); |
| 111 | + - |
| 112 | + - cancel_delayed_work(&tcon->query_interfaces); |
| 113 | + - } |
| 114 | + - if (ses->tcon_ipc) { |
| 115 | + + if (ses->tcon_ipc) |
| 116 | + ses->tcon_ipc->need_reconnect = true; |
| 117 | + - spin_lock(&ses->tcon_ipc->tc_lock); |
| 118 | + - ses->tcon_ipc->status = TID_NEED_RECON; |
| 119 | + - spin_unlock(&ses->tcon_ipc->tc_lock); |
| 120 | + - } |
| 121 | + + |
| 122 | + +next_session: |
| 123 | + + spin_unlock(&ses->chan_lock); |
| 124 | + } |
| 125 | + spin_unlock(&cifs_tcp_ses_lock); |
| 126 | + -} |
| 127 | + - |
| 128 | + -static void |
| 129 | + -cifs_abort_connection(struct TCP_Server_Info *server) |
| 130 | + -{ |
| 131 | + - struct mid_q_entry *mid, *nmid; |
| 132 | + - struct list_head retry_list; |
| 133 | + - |
| 134 | + - server->maxBuf = 0; |
| 135 | + - server->max_read = 0; |
| 136 | + |
| 137 | + + if (num_sessions == 0) |
| 138 | + + return; |
| 139 | + + /* |
| 140 | + + * before reconnecting the tcp session, mark the smb session (uid) |
| 141 | + + * and the tid bad so they are not used until reconnected |
| 142 | + + */ |
| 143 | + + cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n", |
| 144 | + + __func__); |
| 145 | + /* do not want to be sending data on a socket we are freeing */ |
| 146 | + cifs_dbg(FYI, "%s: tearing down socket\n", __func__); |
| 147 | + - cifs_server_lock(server); |
| 148 | + + mutex_lock(&server->srv_mutex); |
| 149 | + if (server->ssocket) { |
| 150 | + cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n", server->ssocket->state, |
| 151 | + server->ssocket->flags); |
| 152 | +diff --cc fs/cifs/smb2ops.c |
| 153 | +index 06fe88efbf89,c8722e82274f..000000000000 |
| 154 | +--- a/fs/cifs/smb2ops.c |
| 155 | ++++ b/fs/cifs/smb2ops.c |
| 156 | +@@@ -727,6 -783,16 +727,19 @@@ SMB3_request_interfaces(const unsigned |
| 157 | + if (rc) |
| 158 | + goto out; |
| 159 | + |
| 160 | +++<<<<<<< HEAD:fs/cifs/smb2ops.c |
| 161 | +++======= |
| 162 | ++ /* check if iface is still active */ |
| 163 | ++ spin_lock(&ses->chan_lock); |
| 164 | ++ pserver = ses->chans[0].server; |
| 165 | ++ if (pserver && !cifs_chan_is_iface_active(ses, pserver)) { |
| 166 | ++ spin_unlock(&ses->chan_lock); |
| 167 | ++ cifs_chan_update_iface(ses, pserver); |
| 168 | ++ spin_lock(&ses->chan_lock); |
| 169 | ++ } |
| 170 | ++ spin_unlock(&ses->chan_lock); |
| 171 | ++ |
| 172 | +++>>>>>>> 7257bcf3bdc7 (cifs: cifs_chan_is_iface_active should be called with chan_lock held):fs/smb/client/smb2ops.c |
| 173 | + out: |
| 174 | + kfree(out_buf); |
| 175 | + return rc; |
| 176 | +* Unmerged path fs/cifs/connect.c |
| 177 | +* Unmerged path fs/cifs/smb2ops.c |
0 commit comments