summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorEnzo Matsumiya <ematsumiya@suse.de>2025-06-16 15:58:41 -0300
committerEnzo Matsumiya <ematsumiya@suse.de>2025-06-16 16:17:02 -0300
commit962f1f332f07206e2023ee0f7e2dbaf5762bb4cd (patch)
tree07e4c89c01ecdaaf4ca6e05903001f0878f9fb53 /fs
parent0ca564b2f2990cc260b66a40399132b5dceeef97 (diff)
downloadlinux-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.h4
-rw-r--r--fs/smb/client/connect.c16
-rw-r--r--fs/smb/client/misc.c2
-rw-r--r--fs/smb/client/smb1ops.c6
-rw-r--r--fs/smb/client/smb2misc.c26
-rw-r--r--fs/smb/client/smb2ops.c16
-rw-r--r--fs/smb/client/smb2pdu.c19
-rw-r--r--fs/smb/client/smb2transport.c16
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) {