Skip to content

Commit 07e76ea

Browse files
dhowellsgregkh
authored andcommitted
cifs: Add tracing for the cifs_tcon struct refcounting
[ Upstream commit afc23fe ] Add tracing for the refcounting/lifecycle of the cifs_tcon struct, marking different events with different labels and giving each tcon its own debug ID so that the tracelines corresponding to individual tcons can be distinguished. This can be enabled with: echo 1 >/sys/kernel/debug/tracing/events/cifs/smb3_tcon_ref/enable Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: Paulo Alcantara (Red Hat) <pc@manguebit.com> cc: Shyam Prasad N <nspmangalore@gmail.com> cc: linux-cifs@vger.kernel.org cc: linux-fsdevel@vger.kernel.org Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 2004e41 commit 07e76ea

File tree

11 files changed

+143
-26
lines changed

11 files changed

+143
-26
lines changed

fs/smb/client/cifsfs.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,8 @@ static void cifs_umount_begin(struct super_block *sb)
739739

740740
spin_lock(&cifs_tcp_ses_lock);
741741
spin_lock(&tcon->tc_lock);
742+
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
743+
netfs_trace_tcon_ref_see_umount);
742744
if ((tcon->tc_count > 1) || (tcon->status == TID_EXITING)) {
743745
/* we have other mounts to same share or we have
744746
already tried to umount this and woken up

fs/smb/client/cifsglob.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,6 +1190,7 @@ struct cifs_fattr {
11901190
*/
11911191
struct cifs_tcon {
11921192
struct list_head tcon_list;
1193+
int debug_id; /* Debugging for tracing */
11931194
int tc_count;
11941195
struct list_head rlist; /* reconnect list */
11951196
spinlock_t tc_lock; /* protect anything here that is not protected */

fs/smb/client/cifsproto.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
303303
struct TCP_Server_Info *primary_server);
304304
extern void cifs_put_tcp_session(struct TCP_Server_Info *server,
305305
int from_reconnect);
306-
extern void cifs_put_tcon(struct cifs_tcon *tcon);
306+
extern void cifs_put_tcon(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace);
307307

308308
extern void cifs_release_automount_timer(void);
309309

@@ -530,8 +530,9 @@ extern int CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses);
530530

531531
extern struct cifs_ses *sesInfoAlloc(void);
532532
extern void sesInfoFree(struct cifs_ses *);
533-
extern struct cifs_tcon *tcon_info_alloc(bool dir_leases_enabled);
534-
extern void tconInfoFree(struct cifs_tcon *);
533+
extern struct cifs_tcon *tcon_info_alloc(bool dir_leases_enabled,
534+
enum smb3_tcon_ref_trace trace);
535+
extern void tconInfoFree(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace);
535536

536537
extern int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
537538
__u32 *pexpected_response_sequence_number);
@@ -721,8 +722,6 @@ static inline int cifs_create_options(struct cifs_sb_info *cifs_sb, int options)
721722
return options;
722723
}
723724

724-
struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon);
725-
void cifs_put_tcon_super(struct super_block *sb);
726725
int cifs_wait_for_server_reconnect(struct TCP_Server_Info *server, bool retry);
727726

728727
/* Put references of @ses and its children */

fs/smb/client/connect.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1943,7 +1943,7 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx)
19431943
}
19441944

19451945
/* no need to setup directory caching on IPC share, so pass in false */
1946-
tcon = tcon_info_alloc(false);
1946+
tcon = tcon_info_alloc(false, netfs_trace_tcon_ref_new_ipc);
19471947
if (tcon == NULL)
19481948
return -ENOMEM;
19491949

@@ -1960,7 +1960,7 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx)
19601960

19611961
if (rc) {
19621962
cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
1963-
tconInfoFree(tcon);
1963+
tconInfoFree(tcon, netfs_trace_tcon_ref_free_ipc_fail);
19641964
goto out;
19651965
}
19661966

@@ -2043,7 +2043,7 @@ void __cifs_put_smb_ses(struct cifs_ses *ses)
20432043
* files on session close, as specified in MS-SMB2 3.3.5.6 Receiving an
20442044
* SMB2 LOGOFF Request.
20452045
*/
2046-
tconInfoFree(tcon);
2046+
tconInfoFree(tcon, netfs_trace_tcon_ref_free_ipc);
20472047
if (do_logoff) {
20482048
xid = get_xid();
20492049
rc = server->ops->logoff(xid, ses);
@@ -2432,6 +2432,8 @@ cifs_find_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
24322432
continue;
24332433
}
24342434
++tcon->tc_count;
2435+
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
2436+
netfs_trace_tcon_ref_get_find);
24352437
spin_unlock(&tcon->tc_lock);
24362438
spin_unlock(&cifs_tcp_ses_lock);
24372439
return tcon;
@@ -2441,7 +2443,7 @@ cifs_find_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
24412443
}
24422444

24432445
void
2444-
cifs_put_tcon(struct cifs_tcon *tcon)
2446+
cifs_put_tcon(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace)
24452447
{
24462448
unsigned int xid;
24472449
struct cifs_ses *ses;
@@ -2457,6 +2459,7 @@ cifs_put_tcon(struct cifs_tcon *tcon)
24572459
cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
24582460
spin_lock(&cifs_tcp_ses_lock);
24592461
spin_lock(&tcon->tc_lock);
2462+
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count - 1, trace);
24602463
if (--tcon->tc_count > 0) {
24612464
spin_unlock(&tcon->tc_lock);
24622465
spin_unlock(&cifs_tcp_ses_lock);
@@ -2493,7 +2496,7 @@ cifs_put_tcon(struct cifs_tcon *tcon)
24932496
_free_xid(xid);
24942497

24952498
cifs_fscache_release_super_cookie(tcon);
2496-
tconInfoFree(tcon);
2499+
tconInfoFree(tcon, netfs_trace_tcon_ref_free);
24972500
cifs_put_smb_ses(ses);
24982501
}
24992502

@@ -2547,7 +2550,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
25472550
nohandlecache = ctx->nohandlecache;
25482551
else
25492552
nohandlecache = true;
2550-
tcon = tcon_info_alloc(!nohandlecache);
2553+
tcon = tcon_info_alloc(!nohandlecache, netfs_trace_tcon_ref_new);
25512554
if (tcon == NULL) {
25522555
rc = -ENOMEM;
25532556
goto out_fail;
@@ -2737,7 +2740,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
27372740
return tcon;
27382741

27392742
out_fail:
2740-
tconInfoFree(tcon);
2743+
tconInfoFree(tcon, netfs_trace_tcon_ref_free_fail);
27412744
return ERR_PTR(rc);
27422745
}
27432746

@@ -2754,7 +2757,7 @@ cifs_put_tlink(struct tcon_link *tlink)
27542757
}
27552758

27562759
if (!IS_ERR(tlink_tcon(tlink)))
2757-
cifs_put_tcon(tlink_tcon(tlink));
2760+
cifs_put_tcon(tlink_tcon(tlink), netfs_trace_tcon_ref_put_tlink);
27582761
kfree(tlink);
27592762
}
27602763

@@ -3319,7 +3322,7 @@ void cifs_mount_put_conns(struct cifs_mount_ctx *mnt_ctx)
33193322
int rc = 0;
33203323

33213324
if (mnt_ctx->tcon)
3322-
cifs_put_tcon(mnt_ctx->tcon);
3325+
cifs_put_tcon(mnt_ctx->tcon, netfs_trace_tcon_ref_put_mnt_ctx);
33233326
else if (mnt_ctx->ses)
33243327
cifs_put_smb_ses(mnt_ctx->ses);
33253328
else if (mnt_ctx->server)

fs/smb/client/fscache.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
9494
}
9595
pr_err("Cache volume key already in use (%s)\n", key);
9696
vcookie = NULL;
97+
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
98+
netfs_trace_tcon_ref_see_fscache_collision);
99+
} else {
100+
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
101+
netfs_trace_tcon_ref_see_fscache_okay);
97102
}
98103

99104
tcon->fscache = vcookie;
@@ -115,6 +120,8 @@ void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon)
115120
cifs_fscache_fill_volume_coherency(tcon, &cd);
116121
fscache_relinquish_volume(tcon->fscache, &cd, false);
117122
tcon->fscache = NULL;
123+
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
124+
netfs_trace_tcon_ref_see_fscache_relinq);
118125
}
119126

120127
void cifs_fscache_get_inode_cookie(struct inode *inode)

fs/smb/client/misc.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,10 @@ sesInfoFree(struct cifs_ses *buf_to_free)
111111
}
112112

113113
struct cifs_tcon *
114-
tcon_info_alloc(bool dir_leases_enabled)
114+
tcon_info_alloc(bool dir_leases_enabled, enum smb3_tcon_ref_trace trace)
115115
{
116116
struct cifs_tcon *ret_buf;
117+
static atomic_t tcon_debug_id;
117118

118119
ret_buf = kzalloc(sizeof(*ret_buf), GFP_KERNEL);
119120
if (!ret_buf)
@@ -130,7 +131,8 @@ tcon_info_alloc(bool dir_leases_enabled)
130131

131132
atomic_inc(&tconInfoAllocCount);
132133
ret_buf->status = TID_NEW;
133-
++ret_buf->tc_count;
134+
ret_buf->debug_id = atomic_inc_return(&tcon_debug_id);
135+
ret_buf->tc_count = 1;
134136
spin_lock_init(&ret_buf->tc_lock);
135137
INIT_LIST_HEAD(&ret_buf->openFileList);
136138
INIT_LIST_HEAD(&ret_buf->tcon_list);
@@ -142,17 +144,19 @@ tcon_info_alloc(bool dir_leases_enabled)
142144
#ifdef CONFIG_CIFS_FSCACHE
143145
mutex_init(&ret_buf->fscache_lock);
144146
#endif
147+
trace_smb3_tcon_ref(ret_buf->debug_id, ret_buf->tc_count, trace);
145148

146149
return ret_buf;
147150
}
148151

149152
void
150-
tconInfoFree(struct cifs_tcon *tcon)
153+
tconInfoFree(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace)
151154
{
152155
if (tcon == NULL) {
153156
cifs_dbg(FYI, "Null buffer passed to tconInfoFree\n");
154157
return;
155158
}
159+
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, trace);
156160
free_cached_dirs(tcon->cfids);
157161
atomic_dec(&tconInfoAllocCount);
158162
kfree(tcon->nativeFileSystem);

fs/smb/client/smb2misc.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,7 @@ smb2_cancelled_close_fid(struct work_struct *work)
767767
if (rc)
768768
cifs_tcon_dbg(VFS, "Close cancelled mid failed rc:%d\n", rc);
769769

770-
cifs_put_tcon(tcon);
770+
cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cancelled_close_fid);
771771
kfree(cancelled);
772772
}
773773

@@ -811,6 +811,8 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid,
811811
if (tcon->tc_count <= 0) {
812812
struct TCP_Server_Info *server = NULL;
813813

814+
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
815+
netfs_trace_tcon_ref_see_cancelled_close);
814816
WARN_ONCE(tcon->tc_count < 0, "tcon refcount is negative");
815817
spin_unlock(&cifs_tcp_ses_lock);
816818

@@ -823,12 +825,14 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid,
823825
return 0;
824826
}
825827
tcon->tc_count++;
828+
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
829+
netfs_trace_tcon_ref_get_cancelled_close);
826830
spin_unlock(&cifs_tcp_ses_lock);
827831

828832
rc = __smb2_handle_cancelled_cmd(tcon, SMB2_CLOSE_HE, 0,
829833
persistent_fid, volatile_fid);
830834
if (rc)
831-
cifs_put_tcon(tcon);
835+
cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cancelled_close);
832836

833837
return rc;
834838
}
@@ -856,7 +860,7 @@ smb2_handle_cancelled_mid(struct mid_q_entry *mid, struct TCP_Server_Info *serve
856860
rsp->PersistentFileId,
857861
rsp->VolatileFileId);
858862
if (rc)
859-
cifs_put_tcon(tcon);
863+
cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cancelled_mid);
860864

861865
return rc;
862866
}

fs/smb/client/smb2ops.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2915,8 +2915,11 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
29152915
tcon = list_first_entry_or_null(&ses->tcon_list,
29162916
struct cifs_tcon,
29172917
tcon_list);
2918-
if (tcon)
2918+
if (tcon) {
29192919
tcon->tc_count++;
2920+
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
2921+
netfs_trace_tcon_ref_get_dfs_refer);
2922+
}
29202923
spin_unlock(&cifs_tcp_ses_lock);
29212924
}
29222925

@@ -2980,6 +2983,8 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
29802983
/* ipc tcons are not refcounted */
29812984
spin_lock(&cifs_tcp_ses_lock);
29822985
tcon->tc_count--;
2986+
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
2987+
netfs_trace_tcon_ref_dec_dfs_refer);
29832988
/* tc_count can never go negative */
29842989
WARN_ON(tcon->tc_count < 0);
29852990
spin_unlock(&cifs_tcp_ses_lock);

fs/smb/client/smb2pdu.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4138,6 +4138,8 @@ void smb2_reconnect_server(struct work_struct *work)
41384138
list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
41394139
if (tcon->need_reconnect || tcon->need_reopen_files) {
41404140
tcon->tc_count++;
4141+
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
4142+
netfs_trace_tcon_ref_get_reconnect_server);
41414143
list_add_tail(&tcon->rlist, &tmp_list);
41424144
tcon_selected = true;
41434145
}
@@ -4176,14 +4178,14 @@ void smb2_reconnect_server(struct work_struct *work)
41764178
if (tcon->ipc)
41774179
cifs_put_smb_ses(tcon->ses);
41784180
else
4179-
cifs_put_tcon(tcon);
4181+
cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_reconnect_server);
41804182
}
41814183

41824184
if (!ses_exist)
41834185
goto done;
41844186

41854187
/* allocate a dummy tcon struct used for reconnect */
4186-
tcon = tcon_info_alloc(false);
4188+
tcon = tcon_info_alloc(false, netfs_trace_tcon_ref_new_reconnect_server);
41874189
if (!tcon) {
41884190
resched = true;
41894191
list_for_each_entry_safe(ses, ses2, &tmp_ses_list, rlist) {
@@ -4206,7 +4208,7 @@ void smb2_reconnect_server(struct work_struct *work)
42064208
list_del_init(&ses->rlist);
42074209
cifs_put_smb_ses(ses);
42084210
}
4209-
tconInfoFree(tcon);
4211+
tconInfoFree(tcon, netfs_trace_tcon_ref_free_reconnect_server);
42104212

42114213
done:
42124214
cifs_dbg(FYI, "Reconnecting tcons and channels finished\n");

fs/smb/client/smb2transport.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32 tid)
189189
if (tcon->tid != tid)
190190
continue;
191191
++tcon->tc_count;
192+
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
193+
netfs_trace_tcon_ref_get_find_sess_tcon);
192194
return tcon;
193195
}
194196

0 commit comments

Comments
 (0)