* [PATCH 1/3] smb: client: relax session and tcon reconnect attempts @ 2025-12-04 18:06 Paulo Alcantara 2025-12-04 18:06 ` [PATCH 2/3] smb: client: improve error message when creating SMB session Paulo Alcantara 2025-12-04 18:06 ` [PATCH 3/3] smb: client: Add tracepoint for krb5 auth Paulo Alcantara 0 siblings, 2 replies; 4+ messages in thread From: Paulo Alcantara @ 2025-12-04 18:06 UTC (permalink / raw) To: smfrench Cc: Paulo Alcantara (Red Hat), David Howells, Pierguido Lambri, linux-cifs When the client re-establishes connection to the server, it will queue a worker thread that will attempt to reconnect sessions and tcons on every two seconds, which is kinda overkill as it is a very common scenario when having expired passwords or KRB5 TGT tickets, or deleted shares. Use an exponential backoff strategy to handle session/tcon reconnect attempts in the worker thread to prevent the client from overloading the system when it is very unlikely to re-establish any session/tcon soon while client is idle. Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.org> Reviewed-by: David Howells <dhowells@redhat.com> Cc: Pierguido Lambri <plambri@redhat.com> Cc: linux-cifs@vger.kernel.org --- fs/smb/client/cifsglob.h | 21 +++++++++++++++++++++ fs/smb/client/connect.c | 4 ++-- fs/smb/client/smb2pdu.c | 6 +++--- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index f9c1f553ffd0..3eca5bfb7030 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -745,6 +745,7 @@ struct TCP_Server_Info { struct session_key session_key; unsigned long lstrp; /* when we got last response from this server */ unsigned long neg_start; /* when negotiate started (jiffies) */ + unsigned long reconn_delay; /* when resched session and tcon reconnect */ struct cifs_secmech secmech; /* crypto sec mech functs, descriptors */ #define CIFS_NEGFLAVOR_UNENCAP 1 /* wct == 17, but no ext_sec */ #define CIFS_NEGFLAVOR_EXTENDED 2 /* wct == 17, ext_sec bit set */ @@ -2292,4 +2293,24 @@ struct cifs_calc_sig_ctx { struct shash_desc *shash; }; +#define CIFS_RECONN_DELAY_SECS 30 +#define CIFS_MAX_RECONN_DELAY (4 * CIFS_RECONN_DELAY_SECS) + +static inline void cifs_queue_server_reconn(struct TCP_Server_Info *server) +{ + if (!delayed_work_pending(&server->reconnect)) { + WRITE_ONCE(server->reconn_delay, 0); + mod_delayed_work(cifsiod_wq, &server->reconnect, 0); + } +} + +static inline void cifs_requeue_server_reconn(struct TCP_Server_Info *server) +{ + unsigned long delay = READ_ONCE(server->reconn_delay); + + delay = umin(delay + CIFS_RECONN_DELAY_SECS, CIFS_MAX_RECONN_DELAY); + WRITE_ONCE(server->reconn_delay, delay); + queue_delayed_work(cifsiod_wq, &server->reconnect, delay * HZ); +} + #endif /* _CIFS_GLOB_H */ diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index b306ee97a20a..3838dd14d4da 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -425,7 +425,7 @@ static int __cifs_reconnect(struct TCP_Server_Info *server, spin_unlock(&server->srv_lock); cifs_swn_reset_server_dstaddr(server); cifs_server_unlock(server); - mod_delayed_work(cifsiod_wq, &server->reconnect, 0); + cifs_queue_server_reconn(server); } } while (server->tcpStatus == CifsNeedReconnect); @@ -564,7 +564,7 @@ static int reconnect_dfs_server(struct TCP_Server_Info *server) spin_unlock(&server->srv_lock); cifs_swn_reset_server_dstaddr(server); cifs_server_unlock(server); - mod_delayed_work(cifsiod_wq, &server->reconnect, 0); + cifs_queue_server_reconn(server); } while (server->tcpStatus == CifsNeedReconnect); dfs_cache_noreq_update_tgthint(ref_path, target_hint); diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index e26d29d75f9f..0d2940808be6 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -493,7 +493,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon, spin_unlock(&ses->ses_lock); if (smb2_command != SMB2_INTERNAL_CMD) - mod_delayed_work(cifsiod_wq, &server->reconnect, 0); + cifs_queue_server_reconn(server); atomic_inc(&tconInfoReconnectCount); out: @@ -4312,7 +4312,7 @@ void smb2_reconnect_server(struct work_struct *work) done: cifs_dbg(FYI, "Reconnecting tcons and channels finished\n"); if (resched) - queue_delayed_work(cifsiod_wq, &server->reconnect, 2 * HZ); + cifs_requeue_server_reconn(server); mutex_unlock(&pserver->reconnect_mutex); /* now we can safely release srv struct */ @@ -4336,7 +4336,7 @@ SMB2_echo(struct TCP_Server_Info *server) server->ops->need_neg(server)) { spin_unlock(&server->srv_lock); /* No need to send echo on newly established connections */ - mod_delayed_work(cifsiod_wq, &server->reconnect, 0); + cifs_queue_server_reconn(server); return rc; } spin_unlock(&server->srv_lock); -- 2.52.0 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/3] smb: client: improve error message when creating SMB session 2025-12-04 18:06 [PATCH 1/3] smb: client: relax session and tcon reconnect attempts Paulo Alcantara @ 2025-12-04 18:06 ` Paulo Alcantara 2025-12-04 18:26 ` Steve French 2025-12-04 18:06 ` [PATCH 3/3] smb: client: Add tracepoint for krb5 auth Paulo Alcantara 1 sibling, 1 reply; 4+ messages in thread From: Paulo Alcantara @ 2025-12-04 18:06 UTC (permalink / raw) To: smfrench Cc: Paulo Alcantara (Red Hat), Pierguido Lambri, David Howells, linux-cifs When failing to create a new SMB session with 'sec=krb5' for example, the following error message isn't very useful CIFS: VFS: \\srv Send error in SessSetup = -126 Improve it by printing the following instead on dmesg CIFS: VFS: \\srv failed to create a new SMB session with Kerberos: -126 Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.org> Cc: Pierguido Lambri <plambri@redhat.com> Cc: David Howells <dhowells@redhat.com> Cc: linux-cifs@vger.kernel.org --- fs/smb/client/connect.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index 3838dd14d4da..bc28e21340e7 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -4238,8 +4238,10 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&pserver->dstaddr; struct sockaddr_in *addr = (struct sockaddr_in *)&pserver->dstaddr; bool is_binding = false; + bool new_ses; spin_lock(&ses->ses_lock); + new_ses = ses->ses_status == SES_NEW; cifs_dbg(FYI, "%s: channel connect bitmap: 0x%lx\n", __func__, ses->chans_need_reconnect); @@ -4325,7 +4327,10 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, } if (rc) { - cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc); + if (new_ses) { + cifs_server_dbg(VFS, "failed to create a new SMB session with %s: %d\n", + get_security_type_str(ses->sectype), rc); + } spin_lock(&ses->ses_lock); if (ses->ses_status == SES_IN_SETUP) ses->ses_status = SES_NEED_RECON; -- 2.52.0 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 2/3] smb: client: improve error message when creating SMB session 2025-12-04 18:06 ` [PATCH 2/3] smb: client: improve error message when creating SMB session Paulo Alcantara @ 2025-12-04 18:26 ` Steve French 0 siblings, 0 replies; 4+ messages in thread From: Steve French @ 2025-12-04 18:26 UTC (permalink / raw) To: Paulo Alcantara; +Cc: Pierguido Lambri, David Howells, linux-cifs Added the first two of the three patches to cifs-2.6.git for-next On Thu, Dec 4, 2025 at 12:06 PM Paulo Alcantara <pc@manguebit.org> wrote: > > When failing to create a new SMB session with 'sec=krb5' for example, > the following error message isn't very useful > > CIFS: VFS: \\srv Send error in SessSetup = -126 > > Improve it by printing the following instead on dmesg > > CIFS: VFS: \\srv failed to create a new SMB session with Kerberos: -126 > > Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.org> > Cc: Pierguido Lambri <plambri@redhat.com> > Cc: David Howells <dhowells@redhat.com> > Cc: linux-cifs@vger.kernel.org > --- > fs/smb/client/connect.c | 7 ++++++- > 1 file changed, 6 insertions(+), 1 deletion(-) > > diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c > index 3838dd14d4da..bc28e21340e7 100644 > --- a/fs/smb/client/connect.c > +++ b/fs/smb/client/connect.c > @@ -4238,8 +4238,10 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, > struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&pserver->dstaddr; > struct sockaddr_in *addr = (struct sockaddr_in *)&pserver->dstaddr; > bool is_binding = false; > + bool new_ses; > > spin_lock(&ses->ses_lock); > + new_ses = ses->ses_status == SES_NEW; > cifs_dbg(FYI, "%s: channel connect bitmap: 0x%lx\n", > __func__, ses->chans_need_reconnect); > > @@ -4325,7 +4327,10 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, > } > > if (rc) { > - cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc); > + if (new_ses) { > + cifs_server_dbg(VFS, "failed to create a new SMB session with %s: %d\n", > + get_security_type_str(ses->sectype), rc); > + } > spin_lock(&ses->ses_lock); > if (ses->ses_status == SES_IN_SETUP) > ses->ses_status = SES_NEED_RECON; > -- > 2.52.0 > -- Thanks, Steve ^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 3/3] smb: client: Add tracepoint for krb5 auth 2025-12-04 18:06 [PATCH 1/3] smb: client: relax session and tcon reconnect attempts Paulo Alcantara 2025-12-04 18:06 ` [PATCH 2/3] smb: client: improve error message when creating SMB session Paulo Alcantara @ 2025-12-04 18:06 ` Paulo Alcantara 1 sibling, 0 replies; 4+ messages in thread From: Paulo Alcantara @ 2025-12-04 18:06 UTC (permalink / raw) To: smfrench Cc: Paulo Alcantara (Red Hat), Pierguido Lambri, David Howells, linux-cifs Add tracepoint to help debugging krb5 auth failures. Example: $ trace-cmd record -e smb3_kerberos_auth $ mount.cifs ... $ trace-cmd report mount.cifs-1667 [003] ..... 5810.668549: smb3_kerberos_auth: vers=2 host=w22-dc1.zelda.test ip=192.168.124.30:445 sec=krb5 uid=0 cruid=0 user=root pid=1667 upcall_target=app err=-126 Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.org> Cc: Pierguido Lambri <plambri@redhat.com> Cc: David Howells <dhowells@redhat.com> Cc: linux-cifs@vger.kernel.org --- fs/smb/client/cifs_spnego.c | 25 ++++++++++------ fs/smb/client/smb2pdu.c | 2 -- fs/smb/client/trace.h | 60 +++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 11 deletions(-) diff --git a/fs/smb/client/cifs_spnego.c b/fs/smb/client/cifs_spnego.c index da935bd1ce87..48e90773462c 100644 --- a/fs/smb/client/cifs_spnego.c +++ b/fs/smb/client/cifs_spnego.c @@ -84,12 +84,13 @@ struct key * cifs_get_spnego_key(struct cifs_ses *sesInfo, struct TCP_Server_Info *server) { - struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr; struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr; + struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr; + const char *hostname = server->hostname; + const char *sec = "krb5"; char *description, *dp; - size_t desc_len; struct key *spnego_key; - const char *hostname = server->hostname; + size_t desc_len; /* length of fields (with semicolons): ver=0xyz ip4=ipaddress host=hostname sec=mechanism uid=0xFF user=username */ @@ -130,15 +131,14 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo, /* for now, only sec=krb5 and sec=mskrb5 and iakerb are valid */ if (server->sec_kerberos) - dp += sprintf(dp, ";sec=krb5"); + sec = "krb5"; else if (server->sec_mskerberos) - dp += sprintf(dp, ";sec=mskrb5"); + sec = "mskrb5"; else if (server->sec_iakerb) - dp += sprintf(dp, ";sec=iakerb"); - else { + sec = "iakerb"; + else cifs_dbg(VFS, "unknown or missing server auth type, use krb5\n"); - dp += sprintf(dp, ";sec=krb5"); - } + dp += sprintf(dp, ";sec=%s", sec); dp += sprintf(dp, ";uid=0x%x", from_kuid_munged(&init_user_ns, sesInfo->linux_uid)); @@ -159,6 +159,13 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo, cifs_dbg(FYI, "key description = %s\n", description); scoped_with_creds(spnego_cred) spnego_key = request_key(&cifs_spnego_key_type, description, ""); + trace_smb3_kerberos_auth(CIFS_SPNEGO_UPCALL_VERSION, + hostname, &server->dstaddr, sec, + from_kuid_munged(&init_user_ns, sesInfo->linux_uid), + from_kuid_munged(&init_user_ns, sesInfo->cred_uid), + sesInfo->user_name, current->pid, + sesInfo->upcall_target == UPTARGET_MOUNT ? "mount" : "app", + IS_ERR(spnego_key) ? PTR_ERR(spnego_key) : 0); #ifdef CONFIG_CIFS_DEBUG2 if (cifsFYI && !IS_ERR(spnego_key)) { diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 0d2940808be6..599cdc6db46c 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -1691,8 +1691,6 @@ SMB2_auth_kerberos(struct SMB2_sess_data *sess_data) spnego_key = cifs_get_spnego_key(ses, server); if (IS_ERR(spnego_key)) { rc = PTR_ERR(spnego_key); - if (rc == -ENOKEY) - cifs_dbg(VFS, "Verify user has a krb5 ticket and keyutils is installed\n"); spnego_key = NULL; goto out; } diff --git a/fs/smb/client/trace.h b/fs/smb/client/trace.h index 252073352e79..0d0261777aa9 100644 --- a/fs/smb/client/trace.h +++ b/fs/smb/client/trace.h @@ -1692,6 +1692,66 @@ DEFINE_SMB3_CREDIT_EVENT(waitff_credits); DEFINE_SMB3_CREDIT_EVENT(overflow_credits); DEFINE_SMB3_CREDIT_EVENT(set_credits); +DECLARE_EVENT_CLASS(smb3_kerberos_class, + TP_PROTO(int vers, + const char *host, + const struct __kernel_sockaddr_storage *addr, + const char *sec, + uid_t uid, + uid_t cruid, + const char *user, + pid_t pid, + const char *upcall_target, + int rc), + TP_ARGS(vers, host, addr, sec, uid, cruid, user, pid, upcall_target, rc), + TP_STRUCT__entry( + __field(int, vers) + __string(host, host) + __array(__u8, addr, sizeof(struct sockaddr_storage)) + __string(sec, sec) + __field(uid_t, uid) + __field(uid_t, cruid) + __string(user, user) + __field(pid_t, pid) + __string(upcall_target, upcall_target) + __field(int, rc) + ), + TP_fast_assign( + struct sockaddr_storage *pss = NULL; + + __entry->vers = vers; + __assign_str(host); + pss = (struct sockaddr_storage *)__entry->addr; + *pss = *addr; + __assign_str(sec); + __entry->uid = uid; + __entry->cruid = cruid; + __assign_str(user); + __entry->pid = pid; + __assign_str(upcall_target); + __entry->rc = rc; + ), + TP_printk("vers=%d host=%s ip=%pISpsfc sec=%s uid=%d cruid=%d user=%s pid=%d upcall_target=%s err=%d", + __entry->vers, __get_str(host), __entry->addr, + __get_str(sec), __entry->uid, __entry->cruid, + __get_str(user), __entry->pid, __get_str(upcall_target), + __entry->rc)) + +#define DEFINE_SMB3_KERBEROS_EVENT(name) \ +DEFINE_EVENT(smb3_kerberos_class, smb3_##name, \ + TP_PROTO(int vers, \ + const char *host, \ + const struct __kernel_sockaddr_storage *addr, \ + const char *sec, \ + uid_t uid, \ + uid_t cruid, \ + const char *user, \ + pid_t pid, \ + const char *upcall_target, \ + int rc), \ + TP_ARGS(vers, host, addr, sec, uid, cruid, user, pid, upcall_target, rc)) + +DEFINE_SMB3_KERBEROS_EVENT(kerberos_auth); TRACE_EVENT(smb3_tcon_ref, TP_PROTO(unsigned int tcon_debug_id, int ref, -- 2.52.0 ^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-12-04 18:27 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-12-04 18:06 [PATCH 1/3] smb: client: relax session and tcon reconnect attempts Paulo Alcantara 2025-12-04 18:06 ` [PATCH 2/3] smb: client: improve error message when creating SMB session Paulo Alcantara 2025-12-04 18:26 ` Steve French 2025-12-04 18:06 ` [PATCH 3/3] smb: client: Add tracepoint for krb5 auth Paulo Alcantara
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox