|
| 1 | +cifs: account for primary channel in the interface list |
| 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 fa1d0508bdd4a68c5e40f85f635712af8c12f180 |
| 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/fa1d0508.failed |
| 10 | + |
| 11 | +The refcounting of server interfaces should account |
| 12 | +for the primary channel too. Although this is not |
| 13 | +strictly necessary, doing so will account for the primary |
| 14 | +channel in DebugData. |
| 15 | + |
| 16 | + Cc: stable@vger.kernel.org |
| 17 | + Reviewed-by: Paulo Alcantara (SUSE) <pc@manguebit.com> |
| 18 | + Signed-off-by: Shyam Prasad N <sprasad@microsoft.com> |
| 19 | + Signed-off-by: Steve French <stfrench@microsoft.com> |
| 20 | +(cherry picked from commit fa1d0508bdd4a68c5e40f85f635712af8c12f180) |
| 21 | + Signed-off-by: Jonathan Maple <jmaple@ciq.com> |
| 22 | + |
| 23 | +# Conflicts: |
| 24 | +# fs/cifs/sess.c |
| 25 | +diff --cc fs/cifs/sess.c |
| 26 | +index b9c9236e1312,e716d046fb5f..000000000000 |
| 27 | +--- a/fs/cifs/sess.c |
| 28 | ++++ b/fs/cifs/sess.c |
| 29 | +@@@ -231,25 -298,61 +231,51 @@@ int cifs_try_adding_channels(struct cif |
| 30 | + int |
| 31 | + cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server) |
| 32 | + { |
| 33 | + - unsigned int chan_index; |
| 34 | + - size_t iface_weight = 0, iface_min_speed = 0; |
| 35 | + + unsigned int chan_index = cifs_ses_get_chan_index(ses, server); |
| 36 | + struct cifs_server_iface *iface = NULL; |
| 37 | + struct cifs_server_iface *old_iface = NULL; |
| 38 | +++<<<<<<< HEAD:fs/cifs/sess.c |
| 39 | +++======= |
| 40 | ++ struct cifs_server_iface *last_iface = NULL; |
| 41 | ++ struct sockaddr_storage ss; |
| 42 | +++>>>>>>> fa1d0508bdd4 (cifs: account for primary channel in the interface list):fs/smb/client/sess.c |
| 43 | + int rc = 0; |
| 44 | + |
| 45 | + - spin_lock(&ses->chan_lock); |
| 46 | + - chan_index = cifs_ses_get_chan_index(ses, server); |
| 47 | + - if (chan_index == CIFS_INVAL_CHAN_INDEX) { |
| 48 | + - spin_unlock(&ses->chan_lock); |
| 49 | + + /* primary channel. This can never go away */ |
| 50 | + + if (!chan_index) |
| 51 | + return 0; |
| 52 | + - } |
| 53 | + |
| 54 | + if (ses->chans[chan_index].iface) { |
| 55 | + old_iface = ses->chans[chan_index].iface; |
| 56 | + - if (old_iface->is_active) { |
| 57 | + - spin_unlock(&ses->chan_lock); |
| 58 | + + if (old_iface->is_active) |
| 59 | + return 1; |
| 60 | + - } |
| 61 | + } |
| 62 | + - spin_unlock(&ses->chan_lock); |
| 63 | + |
| 64 | ++ spin_lock(&server->srv_lock); |
| 65 | ++ ss = server->dstaddr; |
| 66 | ++ spin_unlock(&server->srv_lock); |
| 67 | ++ |
| 68 | + spin_lock(&ses->iface_lock); |
| 69 | + - if (!ses->iface_count) { |
| 70 | + - spin_unlock(&ses->iface_lock); |
| 71 | + - cifs_dbg(VFS, "server %s does not advertise interfaces\n", ses->server->hostname); |
| 72 | + - return 0; |
| 73 | + - } |
| 74 | + - |
| 75 | + - last_iface = list_last_entry(&ses->iface_list, struct cifs_server_iface, |
| 76 | + - iface_head); |
| 77 | + - iface_min_speed = last_iface->speed; |
| 78 | + |
| 79 | + /* then look for a new one */ |
| 80 | + list_for_each_entry(iface, &ses->iface_list, iface_head) { |
| 81 | +++<<<<<<< HEAD:fs/cifs/sess.c |
| 82 | +++======= |
| 83 | ++ if (!chan_index) { |
| 84 | ++ /* if we're trying to get the updated iface for primary channel */ |
| 85 | ++ if (!cifs_match_ipaddr((struct sockaddr *) &ss, |
| 86 | ++ (struct sockaddr *) &iface->sockaddr)) |
| 87 | ++ continue; |
| 88 | ++ |
| 89 | ++ kref_get(&iface->refcount); |
| 90 | ++ break; |
| 91 | ++ } |
| 92 | ++ |
| 93 | ++ /* do not mix rdma and non-rdma interfaces */ |
| 94 | ++ if (iface->rdma_capable != server->rdma) |
| 95 | ++ continue; |
| 96 | ++ |
| 97 | +++>>>>>>> fa1d0508bdd4 (cifs: account for primary channel in the interface list):fs/smb/client/sess.c |
| 98 | + if (!iface->is_active || |
| 99 | + (is_ses_using_iface(ses, iface) && |
| 100 | + !iface->rss_capable)) { |
| 101 | +@@@ -265,7 -375,12 +291,16 @@@ |
| 102 | + cifs_dbg(FYI, "unable to find a suitable iface\n"); |
| 103 | + } |
| 104 | + |
| 105 | +++<<<<<<< HEAD:fs/cifs/sess.c |
| 106 | + + ses->chans[chan_index].iface = iface; |
| 107 | +++======= |
| 108 | ++ if (!chan_index && !iface) { |
| 109 | ++ cifs_dbg(FYI, "unable to get the interface matching: %pIS\n", |
| 110 | ++ &ss); |
| 111 | ++ spin_unlock(&ses->iface_lock); |
| 112 | ++ return 0; |
| 113 | ++ } |
| 114 | +++>>>>>>> fa1d0508bdd4 (cifs: account for primary channel in the interface list):fs/smb/client/sess.c |
| 115 | + |
| 116 | + /* now drop the ref to the current iface */ |
| 117 | + if (old_iface && iface) { |
| 118 | +@@@ -276,7 -398,18 +311,13 @@@ |
| 119 | + } else if (old_iface) { |
| 120 | + cifs_dbg(FYI, "releasing ref to iface: %pIS\n", |
| 121 | + &old_iface->sockaddr); |
| 122 | + - |
| 123 | + - old_iface->num_channels--; |
| 124 | + - if (old_iface->weight_fulfilled) |
| 125 | + - old_iface->weight_fulfilled--; |
| 126 | + - |
| 127 | + kref_put(&old_iface->refcount, release_iface); |
| 128 | ++ } else if (!chan_index) { |
| 129 | ++ /* special case: update interface for primary channel */ |
| 130 | ++ cifs_dbg(FYI, "referencing primary channel iface: %pIS\n", |
| 131 | ++ &iface->sockaddr); |
| 132 | ++ iface->num_channels++; |
| 133 | ++ iface->weight_fulfilled++; |
| 134 | + } else { |
| 135 | + WARN_ON(!iface); |
| 136 | + cifs_dbg(FYI, "adding new iface: %pIS\n", &iface->sockaddr); |
| 137 | +* Unmerged path fs/cifs/sess.c |
| 138 | +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c |
| 139 | +index 06fe88efbf89..ca9630b8bae7 100644 |
| 140 | +--- a/fs/cifs/smb2ops.c |
| 141 | ++++ b/fs/cifs/smb2ops.c |
| 142 | +@@ -703,6 +703,7 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon, bool in_ |
| 143 | + unsigned int ret_data_len = 0; |
| 144 | + struct network_interface_info_ioctl_rsp *out_buf = NULL; |
| 145 | + struct cifs_ses *ses = tcon->ses; |
| 146 | ++ struct TCP_Server_Info *pserver; |
| 147 | + |
| 148 | + /* do not query too frequently */ |
| 149 | + if (ses->iface_last_update && |
| 150 | +@@ -727,6 +728,11 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon, bool in_ |
| 151 | + if (rc) |
| 152 | + goto out; |
| 153 | + |
| 154 | ++ /* check if iface is still active */ |
| 155 | ++ pserver = ses->chans[0].server; |
| 156 | ++ if (pserver && !cifs_chan_is_iface_active(ses, pserver)) |
| 157 | ++ cifs_chan_update_iface(ses, pserver); |
| 158 | ++ |
| 159 | + out: |
| 160 | + kfree(out_buf); |
| 161 | + return rc; |
0 commit comments