From: Enzo Matsumiya <ematsumiya@suse.de>
To: Steve French <smfrench@gmail.com>
Cc: linux-cifs@vger.kernel.org, pc@manguebit.org,
ronniesahlberg@gmail.com, sprasad@microsoft.com, tom@talpey.com,
bharathsm@microsoft.com, henrique.carvalho@suse.com
Subject: Re: [PATCH] smb: client: require CONFIG_CIFS_DEBUG2=y for accounting tcon bytes stats
Date: Fri, 7 Aug 2026 09:21:32 -0300 [thread overview]
Message-ID: <anXLZxgBXIYcfkTT@suse.de> (raw)
In-Reply-To: <CAH2r5muNkfU9LyfvKhQjHUqTF-y=GX1BSXMgyVSR9tHoJYHQvQ@mail.gmail.com>
On 08/06, Steve French wrote:
>the problem I see with this is that for customer perf issues, it is
>often asked to look at the bytes read and bytes written stats to
>narrow down what is causing the perf issue, which tcon (and thus which
>server share)?
The point is, currently this is a debugging feature that has a perceptible
impact on non-debugging settings, so IMO it should definitely be disabled
by default, regardless of the choice on how to enable it.
That's why I suggested, in private to you, a runtime toggling approach by
writing something to /proc/fs/cifs/Stats to enable this.
>On Thu, Aug 6, 2026 at 2:06 PM Enzo Matsumiya <ematsumiya@suse.de> wrote:
>>
>> cifs_stats_bytes_{read,written} uses tcon->stat_lock to account for
>> R/W bytes. This is done unconditionally on every read/write since
>> commit fcabb89299d7 ("cifs: simple stats should always be enabled").
>>
>> On a highly concurrent workload, a spinlock in the middle of the R/W
>> codepaths can become heavily contended, which is absurd given its
>> purpose (protect non-actionable debug/stat data).
>>
>> Make tcon->{bytes_read,bytes_written,stat_lock} usage depend on
>> CONFIG_CIFS_DEBUG2=y.
>>
>> Fixes: fcabb89299d7 ("cifs: simple stats should always be enabled")
>> Signed-off-by: Enzo Matsumiya <ematsumiya@suse.de>
>> ---
>> fs/smb/client/cifs_debug.c | 4 +++-
>> fs/smb/client/cifsglob.h | 24 ++++++++++++++++++++----
>> fs/smb/client/misc.c | 2 ++
>> fs/smb/client/smb1ops.c | 19 +++++++++++++++----
>> fs/smb/client/smb2ops.c | 7 +++++--
>> 5 files changed, 45 insertions(+), 11 deletions(-)
>>
>> diff --git a/fs/smb/client/cifs_debug.c b/fs/smb/client/cifs_debug.c
>> index 4ed4f55a0bb7..3118174745e0 100644
>> --- a/fs/smb/client/cifs_debug.c
>> +++ b/fs/smb/client/cifs_debug.c
>> @@ -762,11 +762,13 @@ static ssize_t cifs_stats_proc_write(struct file *file,
>> continue;
>> list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
>> atomic_set(&tcon->num_smbs_sent, 0);
>> +#ifdef CONFIG_CIFS_DEBUG2
>> spin_lock(&tcon->stat_lock);
>> tcon->bytes_read = 0;
>> tcon->bytes_written = 0;
>> - tcon->stats_from_time = ktime_get_real_seconds();
>> spin_unlock(&tcon->stat_lock);
>> +#endif /* CONFIG_CIFS_DEBUG2 */
>> + tcon->stats_from_time = ktime_get_real_seconds();
>> if (server->ops->clear_stats)
>> server->ops->clear_stats(tcon);
>> }
>> diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
>> index 79e4e84f8985..e0e945c1de0f 100644
>> --- a/fs/smb/client/cifsglob.h
>> +++ b/fs/smb/client/cifsglob.h
>> @@ -1240,9 +1240,11 @@ struct cifs_tcon {
>> atomic_t smb2_com_failed[NUMBER_OF_SMB2_COMMANDS];
>> } smb2_stats;
>> } stats;
>> +#ifdef CONFIG_CIFS_DEBUG2
>> __u64 bytes_read;
>> __u64 bytes_written;
>> spinlock_t stat_lock; /* protects the two fields above */
>> +#endif /* CONFIG_CIFS_DEBUG2 */
>> time64_t stats_from_time;
>> FILE_SYSTEM_DEVICE_INFO fsDevInfo;
>> FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */
>> @@ -1655,10 +1657,11 @@ convert_delimiter(char *path, char delim)
>>
>> #define cifs_stats_inc atomic_inc
>>
>> +#ifdef CONFIG_CIFS_DEBUG2
>> static inline void cifs_stats_bytes_written(struct cifs_tcon *tcon,
>> unsigned int bytes)
>> {
>> - if (bytes) {
>> + if (likely(bytes)) {
>> spin_lock(&tcon->stat_lock);
>> tcon->bytes_written += bytes;
>> spin_unlock(&tcon->stat_lock);
>> @@ -1668,10 +1671,23 @@ static inline void cifs_stats_bytes_written(struct cifs_tcon *tcon,
>> static inline void cifs_stats_bytes_read(struct cifs_tcon *tcon,
>> unsigned int bytes)
>> {
>> - spin_lock(&tcon->stat_lock);
>> - tcon->bytes_read += bytes;
>> - spin_unlock(&tcon->stat_lock);
>> + if (likely(bytes)) {
>> + spin_lock(&tcon->stat_lock);
>> + tcon->bytes_read += bytes;
>> + spin_unlock(&tcon->stat_lock);
>> + }
>> +}
>> +#else /* CONFIG_CIFS_DEBUG2 */
>> +static inline void cifs_stats_bytes_written(struct cifs_tcon *tcon,
>> + unsigned int bytes)
>> +{
>> +}
>> +
>> +static inline void cifs_stats_bytes_read(struct cifs_tcon *tcon,
>> + unsigned int bytes)
>> +{
>> }
>> +#endif /* !CONFIG_CIFS_DEBUG2 */
>>
>>
>> /*
>> diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c
>> index 46e1382e8e04..597dc3c68cd2 100644
>> --- a/fs/smb/client/misc.c
>> +++ b/fs/smb/client/misc.c
>> @@ -145,7 +145,9 @@ tcon_info_alloc(bool dir_leases_enabled, enum smb3_tcon_ref_trace trace)
>> INIT_LIST_HEAD(&ret_buf->tcon_list);
>> INIT_LIST_HEAD(&ret_buf->cifs_sb_list);
>> spin_lock_init(&ret_buf->open_file_lock);
>> +#ifdef CONFIG_CIFS_DEBUG2
>> spin_lock_init(&ret_buf->stat_lock);
>> +#endif /* CONFIG_CIFS_DEBUG2 */
>> spin_lock_init(&ret_buf->sb_list_lock);
>> atomic_set(&ret_buf->num_local_opens, 0);
>> atomic_set(&ret_buf->num_remote_opens, 0);
>> diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c
>> index dc5a8c1da623..484e12cb9181 100644
>> --- a/fs/smb/client/smb1ops.c
>> +++ b/fs/smb/client/smb1ops.c
>> @@ -817,14 +817,25 @@ cifs_clear_stats(struct cifs_tcon *tcon)
>> static void
>> cifs_print_stats(struct seq_file *m, struct cifs_tcon *tcon)
>> {
>> + u64 bytes_read = 0, bytes_written = 0;
>> +
>> +#ifdef CONFIG_CIFS_DEBUG2
>> + bytes_read = tcon->bytes_read;
>> + bytes_written = tcon->bytes_written;
>> +#endif /* CONFIG_CIFS_DEBUG2 */
>> +
>> seq_printf(m, " Oplocks breaks: %d",
>> atomic_read(&tcon->stats.cifs_stats.num_oplock_brks));
>> seq_printf(m, "\nReads: %d Bytes: %llu",
>> - atomic_read(&tcon->stats.cifs_stats.num_reads),
>> - (long long)(tcon->bytes_read));
>> + atomic_read(&tcon->stats.cifs_stats.num_reads), bytes_read);
>> +#ifndef CONFIG_CIFS_DEBUG2
>> + seq_puts(m, " (CONFIG_CIFS_DEBUG2 is disabled)");
>> +#endif /* !CONFIG_CIFS_DEBUG2 */
>> seq_printf(m, "\nWrites: %d Bytes: %llu",
>> - atomic_read(&tcon->stats.cifs_stats.num_writes),
>> - (long long)(tcon->bytes_written));
>> + atomic_read(&tcon->stats.cifs_stats.num_writes), bytes_written);
>> +#ifndef CONFIG_CIFS_DEBUG2
>> + seq_puts(m, " (CONFIG_CIFS_DEBUG2 is disabled)");
>> +#endif /* !CONFIG_CIFS_DEBUG2 */
>> seq_printf(m, "\nFlushes: %d",
>> atomic_read(&tcon->stats.cifs_stats.num_flushes));
>> seq_printf(m, "\nLocks: %d HardLinks: %d Symlinks: %d",
>> diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
>> index 192649fec25d..e1e28f202d0c 100644
>> --- a/fs/smb/client/smb2ops.c
>> +++ b/fs/smb/client/smb2ops.c
>> @@ -1425,9 +1425,12 @@ smb2_print_stats(struct seq_file *m, struct cifs_tcon *tcon)
>> * Can't display SMB2_NEGOTIATE, SESSION_SETUP, LOGOFF, CANCEL and ECHO
>> * totals (requests sent) since those SMBs are per-session not per tcon
>> */
>> +#ifdef CONFIG_CIFS_DEBUG2
>> seq_printf(m, "\nBytes read: %llu Bytes written: %llu",
>> - (long long)(tcon->bytes_read),
>> - (long long)(tcon->bytes_written));
>> + tcon->bytes_read, tcon->bytes_written);
>> +#else /* CONFIG_CIFS_DEBUG2 */
>> + seq_puts(m, "\nBytes read: 0 Bytes written: 0 (CONFIG_CIFS_DEBUG2 is disabled)");
>> +#endif /* !CONFIG_CIFS_DEBUG2 */
>> seq_printf(m, "\nOpen files: %d total (local), %d open on server",
>> atomic_read(&tcon->num_local_opens),
>> atomic_read(&tcon->num_remote_opens));
>> --
>> 2.55.0
>>
>
>
>--
>Thanks,
>
>Steve
>
prev parent reply other threads:[~2026-08-07 12:21 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-06 19:05 [PATCH] smb: client: require CONFIG_CIFS_DEBUG2=y for accounting tcon bytes stats Enzo Matsumiya
2026-08-06 22:12 ` Steve French
2026-08-07 12:21 ` Enzo Matsumiya [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=anXLZxgBXIYcfkTT@suse.de \
--to=ematsumiya@suse.de \
--cc=bharathsm@microsoft.com \
--cc=henrique.carvalho@suse.com \
--cc=linux-cifs@vger.kernel.org \
--cc=pc@manguebit.org \
--cc=ronniesahlberg@gmail.com \
--cc=smfrench@gmail.com \
--cc=sprasad@microsoft.com \
--cc=tom@talpey.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox