diff options
| author | Enzo Matsumiya <ematsumiya@suse.de> | 2025-06-16 15:58:41 -0300 |
|---|---|---|
| committer | Enzo Matsumiya <ematsumiya@suse.de> | 2025-06-16 16:17:02 -0300 |
| commit | 962f1f332f07206e2023ee0f7e2dbaf5762bb4cd (patch) | |
| tree | 07e4c89c01ecdaaf4ca6e05903001f0878f9fb53 /fs | |
| parent | 0ca564b2f2990cc260b66a40399132b5dceeef97 (diff) | |
| download | linux-962f1f332f07206e2023ee0f7e2dbaf5762bb4cd.tar.gz linux-962f1f332f07206e2023ee0f7e2dbaf5762bb4cd.tar.bz2 linux-962f1f332f07206e2023ee0f7e2dbaf5762bb4cd.zip | |
smb: client: set 'server->primary_server = server'
Make server->primary_server always point to the primary server, even if
it's itself.
By making it directly accessible, this also removes possible branch
mispredictions in runtime.
Signed-off-by: Enzo Matsumiya <ematsumiya@suse.de>
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/smb/client/cifsglob.h | 4 | ||||
| -rw-r--r-- | fs/smb/client/connect.c | 16 | ||||
| -rw-r--r-- | fs/smb/client/misc.c | 2 | ||||
| -rw-r--r-- | fs/smb/client/smb1ops.c | 6 | ||||
| -rw-r--r-- | fs/smb/client/smb2misc.c | 26 | ||||
| -rw-r--r-- | fs/smb/client/smb2ops.c | 16 | ||||
| -rw-r--r-- | fs/smb/client/smb2pdu.c | 19 | ||||
| -rw-r--r-- | fs/smb/client/smb2transport.c | 16 |
8 files changed, 34 insertions, 71 deletions
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 9958748b9f28..75cd0f8d095d 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -835,8 +835,10 @@ struct TCP_Server_Info { * If this is a session channel, * primary_server holds the ref-counted * pointer to primary channel connection for the session. + * + * If this is a primary channel, primary_server points to itself. */ -#define SERVER_IS_CHAN(server) (!!(server)->primary_server) +#define SERVER_IS_CHAN(server) ((server)->primary_server != (server)) struct TCP_Server_Info *primary_server; __u16 channel_sequence_num; /* incremented on primary channel on each chan reconnect */ diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index 0454e96f1573..c66bd630b769 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -121,13 +121,9 @@ void cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server, bool all_channels) { - struct TCP_Server_Info *pserver; struct cifs_ses *ses; int i; - /* If server is a channel, select the primary channel */ - pserver = SERVER_IS_CHAN(server) ? server->primary_server : server; - /* if we need to signal just this channel */ if (!all_channels) { spin_lock(&server->srv_lock); @@ -138,7 +134,7 @@ cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server, } spin_lock(&cifs_tcp_ses_lock); - list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) { + list_for_each_entry(ses, &server->primary_server->smb_ses_list, smb_ses_list) { if (cifs_ses_exiting(ses)) continue; spin_lock(&ses->chan_lock); @@ -181,7 +177,7 @@ cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server, cifs_dbg(FYI, "%s: marking necessary sessions and tcons for reconnect\n", __func__); /* If server is a channel, select the primary channel */ - pserver = SERVER_IS_CHAN(server) ? server->primary_server : server; + pserver = server->primary_server; /* * if the server has been marked for termination, there is a @@ -1828,8 +1824,10 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx, spin_lock(&cifs_tcp_ses_lock); ++primary_server->srv_count; spin_unlock(&cifs_tcp_ses_lock); - tcp_ses->primary_server = primary_server; + } else { + primary_server = tcp_ses; } + tcp_ses->primary_server = primary_server; spin_lock_init(&tcp_ses->iface_lock); INIT_LIST_HEAD(&tcp_ses->iface_list); init_waitqueue_head(&tcp_ses->response_q); @@ -4267,7 +4265,7 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, struct nls_table *nls_info) { int rc = 0; - struct TCP_Server_Info *pserver = SERVER_IS_CHAN(server) ? server->primary_server : server; + struct TCP_Server_Info *pserver = server->primary_server; struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&pserver->dstaddr; struct sockaddr_in *addr = (struct sockaddr_in *)&pserver->dstaddr; bool is_binding = false; @@ -4302,7 +4300,7 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, spin_unlock(&ses->ses_lock); /* update ses ip_addr only for primary chan */ - if (server == pserver) { + if (!SERVER_IS_CHAN(server)) { spin_lock(&server->srv_lock); /* force iface_list refresh */ server->iface_last_update = 0; diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c index 608b75c10926..fce0650a762e 100644 --- a/fs/smb/client/misc.c +++ b/fs/smb/client/misc.c @@ -489,7 +489,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv) return false; /* If server is a channel, select the primary channel */ - pserver = SERVER_IS_CHAN(srv) ? srv->primary_server : srv; + pserver = srv->primary_server; /* look up tcon based on tid & uid */ spin_lock(&cifs_tcp_ses_lock); diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c index b27a182629ec..157ddbe66c69 100644 --- a/fs/smb/client/smb1ops.c +++ b/fs/smb/client/smb1ops.c @@ -1280,7 +1280,6 @@ static bool cifs_is_network_name_deleted(char *buf, struct TCP_Server_Info *server) { struct smb_hdr *shdr = (struct smb_hdr *)buf; - struct TCP_Server_Info *pserver; struct cifs_ses *ses; struct cifs_tcon *tcon; @@ -1293,11 +1292,8 @@ cifs_is_network_name_deleted(char *buf, struct TCP_Server_Info *server) return false; } - /* If server is a channel, select the primary channel */ - pserver = SERVER_IS_CHAN(server) ? server->primary_server : server; - spin_lock(&cifs_tcp_ses_lock); - list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) { + list_for_each_entry(ses, &server->primary_server->smb_ses_list, smb_ses_list) { if (cifs_ses_exiting(ses)) continue; list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { diff --git a/fs/smb/client/smb2misc.c b/fs/smb/client/smb2misc.c index cddf273c14ae..cf644b3c1d1a 100644 --- a/fs/smb/client/smb2misc.c +++ b/fs/smb/client/smb2misc.c @@ -135,7 +135,6 @@ static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len, int smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *server) { - struct TCP_Server_Info *pserver; struct smb2_hdr *shdr = (struct smb2_hdr *)buf; struct smb2_pdu *pdu = (struct smb2_pdu *)shdr; int hdr_size = sizeof(struct smb2_hdr); @@ -144,8 +143,7 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *server) __u32 calc_len; /* calculated length */ __u64 mid; - /* If server is a channel, select the primary channel */ - pserver = SERVER_IS_CHAN(server) ? server->primary_server : server; + server = server->primary_server; /* * Add function to do table lookup of StructureSize by command @@ -159,7 +157,7 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *server) /* decrypt frame now that it is completely read in */ spin_lock(&cifs_tcp_ses_lock); - list_for_each_entry(iter, &pserver->smb_ses_list, smb_ses_list) { + list_for_each_entry(iter, &server->smb_ses_list, smb_ses_list) { if (iter->Suid == le64_to_cpu(thdr->SessionId)) { ses = iter; break; @@ -609,19 +607,15 @@ static bool smb2_is_valid_lease_break(char *buffer, struct TCP_Server_Info *server) { struct smb2_lease_break *rsp = (struct smb2_lease_break *)buffer; - struct TCP_Server_Info *pserver; struct cifs_ses *ses; struct cifs_tcon *tcon; struct cifs_pending_open *open; cifs_dbg(FYI, "Checking for lease break\n"); - /* If server is a channel, select the primary channel */ - pserver = SERVER_IS_CHAN(server) ? server->primary_server : server; - /* look up tcon based on tid & uid */ spin_lock(&cifs_tcp_ses_lock); - list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) { + list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { if (cifs_ses_exiting(ses)) continue; list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { @@ -672,7 +666,6 @@ bool smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) { struct smb2_oplock_break *rsp = (struct smb2_oplock_break *)buffer; - struct TCP_Server_Info *pserver; struct cifs_ses *ses; struct cifs_tcon *tcon; struct cifsInodeInfo *cinode; @@ -683,22 +676,19 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) if (rsp->hdr.Command != SMB2_OPLOCK_BREAK) return false; - if (rsp->StructureSize != - smb2_rsp_struct_sizes[SMB2_OPLOCK_BREAK_HE]) { + server = server->primary_server; + + if (rsp->StructureSize != smb2_rsp_struct_sizes[SMB2_OPLOCK_BREAK_HE]) { if (le16_to_cpu(rsp->StructureSize) == 44) return smb2_is_valid_lease_break(buffer, server); - else - return false; + return false; } cifs_dbg(FYI, "oplock level 0x%x\n", rsp->OplockLevel); - /* If server is a channel, select the primary channel */ - pserver = SERVER_IS_CHAN(server) ? server->primary_server : server; - /* look up tcon based on tid & uid */ spin_lock(&cifs_tcp_ses_lock); - list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) { + list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { if (cifs_ses_exiting(ses)) continue; list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index f27da2612327..4d431f0d136a 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -195,10 +195,7 @@ smb2_set_credits(struct TCP_Server_Info *server, const int val) * ChannelSequence updated for all channels in primary channel so that consistent * across SMB3 requests sent on any channel. See MS-SMB2 3.2.4.1 and 3.2.7.1 */ - if (SERVER_IS_CHAN(server)) - server->primary_server->channel_sequence_num++; - else - server->channel_sequence_num++; + server->primary_server->channel_sequence_num++; } scredits = server->credits; in_flight = server->in_flight; @@ -2594,7 +2591,6 @@ static bool smb2_is_network_name_deleted(char *buf, struct TCP_Server_Info *server) { struct smb2_hdr *shdr = (struct smb2_hdr *)buf; - struct TCP_Server_Info *pserver; struct cifs_ses *ses; struct cifs_tcon *tcon; @@ -2602,10 +2598,10 @@ smb2_is_network_name_deleted(char *buf, struct TCP_Server_Info *server) return false; /* If server is a channel, select the primary channel */ - pserver = SERVER_IS_CHAN(server) ? server->primary_server : server; + server = server->primary_server; spin_lock(&cifs_tcp_ses_lock); - list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) { + list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { if (cifs_ses_exiting(ses)) continue; list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { @@ -4324,15 +4320,11 @@ static void *smb2_get_aead_req(struct crypto_aead *tfm, struct smb_rqst *rqst, static int smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key) { - struct TCP_Server_Info *pserver; struct cifs_ses *ses; u8 *ses_enc_key; - /* If server is a channel, select the primary channel */ - pserver = SERVER_IS_CHAN(server) ? server->primary_server : server; - spin_lock(&cifs_tcp_ses_lock); - list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) { + list_for_each_entry(ses, &server->primary_server->smb_ses_list, smb_ses_list) { if (ses->Suid == ses_id) { spin_lock(&ses->ses_lock); ses_enc_key = enc ? ses->smb3encryptionkey : diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index f8755f111be4..605dd04469da 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -110,12 +110,8 @@ smb2_hdr_assemble(struct smb2_hdr *shdr, __le16 smb2_cmd, * if primary channel is not set yet, use default * channel for chan sequence num */ - if (SERVER_IS_CHAN(server)) - smb3_hdr->ChannelSequence = - cpu_to_le16(server->primary_server->channel_sequence_num); - else - smb3_hdr->ChannelSequence = - cpu_to_le16(server->channel_sequence_num); + smb3_hdr->ChannelSequence = + cpu_to_le16(server->primary_server->channel_sequence_num); } spin_lock(&server->req_lock); /* Request up to 10 credits but don't go over the limit. */ @@ -659,7 +655,6 @@ assemble_neg_contexts(struct smb2_negotiate_req *req, struct TCP_Server_Info *server, unsigned int *total_len) { unsigned int ctxt_len, neg_context_count; - struct TCP_Server_Info *pserver; char *pneg_ctxt; char *hostname; @@ -692,9 +687,9 @@ assemble_neg_contexts(struct smb2_negotiate_req *req, * secondary channels don't have the hostname field populated * use the hostname field in the primary channel instead */ - pserver = SERVER_IS_CHAN(server) ? server->primary_server : server; - cifs_server_lock(pserver); - hostname = pserver->hostname; + server = server->primary_server; + cifs_server_lock(server); + hostname = server->hostname; if (hostname && (hostname[0] != 0)) { ctxt_len = build_netname_ctxt((struct smb2_netname_neg_context *)pneg_ctxt, hostname); @@ -703,7 +698,7 @@ assemble_neg_contexts(struct smb2_negotiate_req *req, neg_context_count = 3; } else neg_context_count = 2; - cifs_server_unlock(pserver); + cifs_server_unlock(server); build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt); *total_len += sizeof(struct smb2_posix_neg_context); @@ -4106,7 +4101,7 @@ void smb2_reconnect_server(struct work_struct *work) spin_unlock(&cifs_tcp_ses_lock); /* If server is a channel, select the primary channel */ - pserver = SERVER_IS_CHAN(server) ? server->primary_server : server; + pserver = server->primary_server; /* Prevent simultaneous reconnects that can corrupt tcon->rlist list */ mutex_lock(&pserver->reconnect_mutex); diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c index 475b36c27f65..7db158f926bc 100644 --- a/fs/smb/client/smb2transport.c +++ b/fs/smb/client/smb2transport.c @@ -77,18 +77,13 @@ static int smb3_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key) { struct cifs_chan *chan; - struct TCP_Server_Info *pserver; struct cifs_ses *ses = NULL; int i; int rc = 0; bool is_binding = false; spin_lock(&cifs_tcp_ses_lock); - - /* If server is a channel, select the primary channel */ - pserver = SERVER_IS_CHAN(server) ? server->primary_server : server; - - list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) { + list_for_each_entry(ses, &server->primary_server->smb_ses_list, smb_ses_list) { if (ses->Suid == ses_id) goto found; } @@ -145,13 +140,9 @@ out: static struct cifs_ses * smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id) { - struct TCP_Server_Info *pserver; struct cifs_ses *ses; - /* If server is a channel, select the primary channel */ - pserver = SERVER_IS_CHAN(server) ? server->primary_server : server; - - list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) { + list_for_each_entry(ses, &server->primary_server->smb_ses_list, smb_ses_list) { if (ses->Suid != ses_id) continue; @@ -174,8 +165,7 @@ static int smb2_get_sign_key(struct TCP_Server_Info *server, struct cifs_ses *ses; int rc = -ENOENT; - if (SERVER_IS_CHAN(server)) - server = server->primary_server; + server = server->primary_server; spin_lock(&cifs_tcp_ses_lock); list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { |
