Skip to content

Commit 1112564

Browse files
committed
cifs: reset iface weights when we cannot find a candidate
jira LE-4669 Rebuild_History Non-Buildable kernel-4.18.0-553.82.1.el8_10 commit-author Shyam Prasad N <sprasad@microsoft.com> commit 9d5eff7 Empty-Commit: Cherry-Pick Conflicts during history rebuild. Will be included in final tarball splat. Ref for failed cherry-pick at: ciq/ciq_backports/kernel-4.18.0-553.82.1.el8_10/9d5eff78.failed We now do a weighted selection of server interfaces when allocating new channels. The weights are decided based on the speed advertised. The fulfilled weight for an interface is a counter that is used to track the interface selection. It should be reset back to zero once all interfaces fulfilling their weight. In cifs_chan_update_iface, this reset logic was missing. As a result when the server interface list changes, the client may not be able to find a new candidate for other channels after all interfaces have been fulfilled. Fixes: a6d8fb5 ("cifs: distribute channels across interfaces based on speed") Cc: <stable@vger.kernel.org> Signed-off-by: Shyam Prasad N <sprasad@microsoft.com> Signed-off-by: Steve French <stfrench@microsoft.com> (cherry picked from commit 9d5eff7) Signed-off-by: Jonathan Maple <jmaple@ciq.com> # Conflicts: # fs/cifs/sess.c
1 parent 54169ff commit 1112564

File tree

1 file changed

+177
-0
lines changed

1 file changed

+177
-0
lines changed
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
cifs: reset iface weights when we cannot find a candidate
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 9d5eff7821f6d70f7d1b4d8a60680fba4de868a7
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/9d5eff78.failed
10+
11+
We now do a weighted selection of server interfaces when allocating
12+
new channels. The weights are decided based on the speed advertised.
13+
The fulfilled weight for an interface is a counter that is used to
14+
track the interface selection. It should be reset back to zero once
15+
all interfaces fulfilling their weight.
16+
17+
In cifs_chan_update_iface, this reset logic was missing. As a result
18+
when the server interface list changes, the client may not be able
19+
to find a new candidate for other channels after all interfaces have
20+
been fulfilled.
21+
22+
Fixes: a6d8fb54a515 ("cifs: distribute channels across interfaces based on speed")
23+
Cc: <stable@vger.kernel.org>
24+
Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
25+
Signed-off-by: Steve French <stfrench@microsoft.com>
26+
(cherry picked from commit 9d5eff7821f6d70f7d1b4d8a60680fba4de868a7)
27+
Signed-off-by: Jonathan Maple <jmaple@ciq.com>
28+
29+
# Conflicts:
30+
# fs/cifs/sess.c
31+
diff --cc fs/cifs/sess.c
32+
index f27026148ee7,0a8c2fcc9ded..000000000000
33+
--- a/fs/cifs/sess.c
34+
+++ b/fs/cifs/sess.c
35+
@@@ -226,29 -265,106 +226,48 @@@ int cifs_try_adding_channels(struct cif
36+
}
37+
38+
/*
39+
- * called when multichannel is disabled by the server.
40+
- * this always gets called from smb2_reconnect
41+
- * and cannot get called in parallel threads.
42+
+ * update the iface for the channel if necessary.
43+
+ * will return 0 when iface is updated. 1 otherwise
44+
+ * Must be called with chan_lock held.
45+
*/
46+
-void
47+
-cifs_disable_secondary_channels(struct cifs_ses *ses)
48+
-{
49+
- int i, chan_count;
50+
- struct TCP_Server_Info *server;
51+
- struct cifs_server_iface *iface;
52+
-
53+
- spin_lock(&ses->chan_lock);
54+
- chan_count = ses->chan_count;
55+
- if (chan_count == 1)
56+
- goto done;
57+
-
58+
- ses->chan_count = 1;
59+
-
60+
- /* for all secondary channels reset the need reconnect bit */
61+
- ses->chans_need_reconnect &= 1;
62+
-
63+
- for (i = 1; i < chan_count; i++) {
64+
- iface = ses->chans[i].iface;
65+
- server = ses->chans[i].server;
66+
-
67+
- /*
68+
- * remove these references first, since we need to unlock
69+
- * the chan_lock here, since iface_lock is a higher lock
70+
- */
71+
- ses->chans[i].iface = NULL;
72+
- ses->chans[i].server = NULL;
73+
- spin_unlock(&ses->chan_lock);
74+
-
75+
- if (iface) {
76+
- spin_lock(&ses->iface_lock);
77+
- iface->num_channels--;
78+
- if (iface->weight_fulfilled)
79+
- iface->weight_fulfilled--;
80+
- kref_put(&iface->refcount, release_iface);
81+
- spin_unlock(&ses->iface_lock);
82+
- }
83+
-
84+
- if (server) {
85+
- if (!server->terminate) {
86+
- server->terminate = true;
87+
- cifs_signal_cifsd_for_reconnect(server, false);
88+
- }
89+
- cifs_put_tcp_session(server, false);
90+
- }
91+
-
92+
- spin_lock(&ses->chan_lock);
93+
- }
94+
-
95+
-done:
96+
- spin_unlock(&ses->chan_lock);
97+
-}
98+
-
99+
-/* update the iface for the channel if necessary. */
100+
-void
101+
+int
102+
cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
103+
{
104+
- unsigned int chan_index;
105+
- size_t iface_weight = 0, iface_min_speed = 0;
106+
+ unsigned int chan_index = cifs_ses_get_chan_index(ses, server);
107+
struct cifs_server_iface *iface = NULL;
108+
struct cifs_server_iface *old_iface = NULL;
109+
++<<<<<<< HEAD:fs/cifs/sess.c
110+
+ int rc = 0;
111+
++=======
112+
+ struct cifs_server_iface *last_iface = NULL;
113+
+ struct sockaddr_storage ss;
114+
+ int retry = 0;
115+
++>>>>>>> 9d5eff7821f6 (cifs: reset iface weights when we cannot find a candidate):fs/smb/client/sess.c
116+
117+
- spin_lock(&ses->chan_lock);
118+
- chan_index = cifs_ses_get_chan_index(ses, server);
119+
- if (chan_index == CIFS_INVAL_CHAN_INDEX) {
120+
- spin_unlock(&ses->chan_lock);
121+
- return;
122+
- }
123+
+ /* primary channel. This can never go away */
124+
+ if (!chan_index)
125+
+ return 0;
126+
127+
if (ses->chans[chan_index].iface) {
128+
old_iface = ses->chans[chan_index].iface;
129+
- if (old_iface->is_active) {
130+
- spin_unlock(&ses->chan_lock);
131+
- return;
132+
- }
133+
+ if (old_iface->is_active)
134+
+ return 1;
135+
}
136+
- spin_unlock(&ses->chan_lock);
137+
-
138+
- spin_lock(&server->srv_lock);
139+
- ss = server->dstaddr;
140+
- spin_unlock(&server->srv_lock);
141+
142+
spin_lock(&ses->iface_lock);
143+
++<<<<<<< HEAD:fs/cifs/sess.c
144+
++=======
145+
+ if (!ses->iface_count) {
146+
+ spin_unlock(&ses->iface_lock);
147+
+ cifs_dbg(ONCE, "server %s does not advertise interfaces\n", ses->server->hostname);
148+
+ return;
149+
+ }
150+
+
151+
+ try_again:
152+
+ last_iface = list_last_entry(&ses->iface_list, struct cifs_server_iface,
153+
+ iface_head);
154+
+ iface_min_speed = last_iface->speed;
155+
++>>>>>>> 9d5eff7821f6 (cifs: reset iface weights when we cannot find a candidate):fs/smb/client/sess.c
156+
157+
/* then look for a new one */
158+
list_for_each_entry(iface, &ses->iface_list, iface_head) {
159+
@@@ -262,7 -399,13 +281,17 @@@
160+
}
161+
162+
if (list_entry_is_head(iface, &ses->iface_list, iface_head)) {
163+
++<<<<<<< HEAD:fs/cifs/sess.c
164+
+ rc = 1;
165+
++=======
166+
+ list_for_each_entry(iface, &ses->iface_list, iface_head)
167+
+ iface->weight_fulfilled = 0;
168+
+
169+
+ /* see if it can be satisfied in second attempt */
170+
+ if (!retry++)
171+
+ goto try_again;
172+
+
173+
++>>>>>>> 9d5eff7821f6 (cifs: reset iface weights when we cannot find a candidate):fs/smb/client/sess.c
174+
iface = NULL;
175+
cifs_dbg(FYI, "unable to find a suitable iface\n");
176+
}
177+
* Unmerged path fs/cifs/sess.c

0 commit comments

Comments
 (0)