smb3 client fixes
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmYm8oEACgkQiiy9cAdy T1HAVAv/T9NXYhTYQK8EK7DvzcGDV4dOcFI6GVsrinp1KHGyuxoPABKGctQXfou0 4DJ9ik0CYFWmVuz8CODxmHkJq8fclnkJtVPH4DjcOm8CqhcaMJNVgEWP6eMGevGo sQPEtFAYRPQrIm5X8u2uvARE490YiUD85Se+6LrYZdzt/BOUQQHtKodSTre1ZCAV F6GLEVVuncP9iqno9lNu1EI8ltcOW6i1i15s4HOmULNwtUKdwsYTWVqW6JDOy5gM 9YqXJhPobVcZnY/m8QVWfE/lEPOwJO5lbRF4Ktykz4PQkxZqD6t+Noesj73GKEgC 7jnt3L79s1zA51gHdn96Z1qWlaIruX4ugYhfzQAW7PfYmSUr3I8G09ofzwFc77aH osYoU6mZWWL+4/RIKK3DGYRe2ET68KmlNheG2OTOeCNfwjSoI5rWHSLMGqlegTc0 40gz62OHuwncMyKFLwGaf6ztzlOLHIdVU4uhRv1/9ptZuMl/2LoiN7G8ZddbtYIS JxL/kIEE =PaAG -----END PGP SIGNATURE----- Merge tag '6.9-rc5-smb-client-fixes' of git://git.samba.org/sfrench/cifs-2.6 Pull smb client fixes from Steve French: - fscache fix - fix for case where we could use uninitialized lease - add tracepoint for debugging refcounting of tcon - fix mount option regression (e.g. forceuid vs. noforceuid when uid= specified) caused by conversion to the new mount API * tag '6.9-rc5-smb-client-fixes' of git://git.samba.org/sfrench/cifs-2.6: cifs: reinstate original behavior again for forceuid/forcegid smb: client: fix rename(2) regression against samba cifs: Add tracing for the cifs_tcon struct refcounting cifs: Fix reacquisition of volume cookie on still-live connection
This commit is contained in:
commit
9d1ddab261
|
@ -389,6 +389,7 @@ cifs_alloc_inode(struct super_block *sb)
|
||||||
* server, can not assume caching of file data or metadata.
|
* server, can not assume caching of file data or metadata.
|
||||||
*/
|
*/
|
||||||
cifs_set_oplock_level(cifs_inode, 0);
|
cifs_set_oplock_level(cifs_inode, 0);
|
||||||
|
cifs_inode->lease_granted = false;
|
||||||
cifs_inode->flags = 0;
|
cifs_inode->flags = 0;
|
||||||
spin_lock_init(&cifs_inode->writers_lock);
|
spin_lock_init(&cifs_inode->writers_lock);
|
||||||
cifs_inode->writers = 0;
|
cifs_inode->writers = 0;
|
||||||
|
@ -739,6 +740,8 @@ static void cifs_umount_begin(struct super_block *sb)
|
||||||
|
|
||||||
spin_lock(&cifs_tcp_ses_lock);
|
spin_lock(&cifs_tcp_ses_lock);
|
||||||
spin_lock(&tcon->tc_lock);
|
spin_lock(&tcon->tc_lock);
|
||||||
|
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
|
||||||
|
netfs_trace_tcon_ref_see_umount);
|
||||||
if ((tcon->tc_count > 1) || (tcon->status == TID_EXITING)) {
|
if ((tcon->tc_count > 1) || (tcon->status == TID_EXITING)) {
|
||||||
/* we have other mounts to same share or we have
|
/* we have other mounts to same share or we have
|
||||||
already tried to umount this and woken up
|
already tried to umount this and woken up
|
||||||
|
|
|
@ -1190,6 +1190,7 @@ struct cifs_fattr {
|
||||||
*/
|
*/
|
||||||
struct cifs_tcon {
|
struct cifs_tcon {
|
||||||
struct list_head tcon_list;
|
struct list_head tcon_list;
|
||||||
|
int debug_id; /* Debugging for tracing */
|
||||||
int tc_count;
|
int tc_count;
|
||||||
struct list_head rlist; /* reconnect list */
|
struct list_head rlist; /* reconnect list */
|
||||||
spinlock_t tc_lock; /* protect anything here that is not protected */
|
spinlock_t tc_lock; /* protect anything here that is not protected */
|
||||||
|
@ -1276,7 +1277,9 @@ struct cifs_tcon {
|
||||||
__u32 max_cached_dirs;
|
__u32 max_cached_dirs;
|
||||||
#ifdef CONFIG_CIFS_FSCACHE
|
#ifdef CONFIG_CIFS_FSCACHE
|
||||||
u64 resource_id; /* server resource id */
|
u64 resource_id; /* server resource id */
|
||||||
|
bool fscache_acquired; /* T if we've tried acquiring a cookie */
|
||||||
struct fscache_volume *fscache; /* cookie for share */
|
struct fscache_volume *fscache; /* cookie for share */
|
||||||
|
struct mutex fscache_lock; /* Prevent regetting a cookie */
|
||||||
#endif
|
#endif
|
||||||
struct list_head pending_opens; /* list of incomplete opens */
|
struct list_head pending_opens; /* list of incomplete opens */
|
||||||
struct cached_fids *cfids;
|
struct cached_fids *cfids;
|
||||||
|
|
|
@ -303,7 +303,7 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
|
||||||
struct TCP_Server_Info *primary_server);
|
struct TCP_Server_Info *primary_server);
|
||||||
extern void cifs_put_tcp_session(struct TCP_Server_Info *server,
|
extern void cifs_put_tcp_session(struct TCP_Server_Info *server,
|
||||||
int from_reconnect);
|
int from_reconnect);
|
||||||
extern void cifs_put_tcon(struct cifs_tcon *tcon);
|
extern void cifs_put_tcon(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace);
|
||||||
|
|
||||||
extern void cifs_release_automount_timer(void);
|
extern void cifs_release_automount_timer(void);
|
||||||
|
|
||||||
|
@ -530,8 +530,9 @@ extern int CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses);
|
||||||
|
|
||||||
extern struct cifs_ses *sesInfoAlloc(void);
|
extern struct cifs_ses *sesInfoAlloc(void);
|
||||||
extern void sesInfoFree(struct cifs_ses *);
|
extern void sesInfoFree(struct cifs_ses *);
|
||||||
extern struct cifs_tcon *tcon_info_alloc(bool dir_leases_enabled);
|
extern struct cifs_tcon *tcon_info_alloc(bool dir_leases_enabled,
|
||||||
extern void tconInfoFree(struct cifs_tcon *);
|
enum smb3_tcon_ref_trace trace);
|
||||||
|
extern void tconInfoFree(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace);
|
||||||
|
|
||||||
extern int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
|
extern int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
|
||||||
__u32 *pexpected_response_sequence_number);
|
__u32 *pexpected_response_sequence_number);
|
||||||
|
@ -721,8 +722,6 @@ static inline int cifs_create_options(struct cifs_sb_info *cifs_sb, int options)
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon);
|
|
||||||
void cifs_put_tcon_super(struct super_block *sb);
|
|
||||||
int cifs_wait_for_server_reconnect(struct TCP_Server_Info *server, bool retry);
|
int cifs_wait_for_server_reconnect(struct TCP_Server_Info *server, bool retry);
|
||||||
|
|
||||||
/* Put references of @ses and its children */
|
/* Put references of @ses and its children */
|
||||||
|
|
|
@ -1943,7 +1943,7 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* no need to setup directory caching on IPC share, so pass in false */
|
/* no need to setup directory caching on IPC share, so pass in false */
|
||||||
tcon = tcon_info_alloc(false);
|
tcon = tcon_info_alloc(false, netfs_trace_tcon_ref_new_ipc);
|
||||||
if (tcon == NULL)
|
if (tcon == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -1960,7 +1960,7 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx)
|
||||||
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
|
cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
|
||||||
tconInfoFree(tcon);
|
tconInfoFree(tcon, netfs_trace_tcon_ref_free_ipc_fail);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2043,7 +2043,7 @@ void __cifs_put_smb_ses(struct cifs_ses *ses)
|
||||||
* files on session close, as specified in MS-SMB2 3.3.5.6 Receiving an
|
* files on session close, as specified in MS-SMB2 3.3.5.6 Receiving an
|
||||||
* SMB2 LOGOFF Request.
|
* SMB2 LOGOFF Request.
|
||||||
*/
|
*/
|
||||||
tconInfoFree(tcon);
|
tconInfoFree(tcon, netfs_trace_tcon_ref_free_ipc);
|
||||||
if (do_logoff) {
|
if (do_logoff) {
|
||||||
xid = get_xid();
|
xid = get_xid();
|
||||||
rc = server->ops->logoff(xid, ses);
|
rc = server->ops->logoff(xid, ses);
|
||||||
|
@ -2432,6 +2432,8 @@ cifs_find_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
++tcon->tc_count;
|
++tcon->tc_count;
|
||||||
|
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
|
||||||
|
netfs_trace_tcon_ref_get_find);
|
||||||
spin_unlock(&tcon->tc_lock);
|
spin_unlock(&tcon->tc_lock);
|
||||||
spin_unlock(&cifs_tcp_ses_lock);
|
spin_unlock(&cifs_tcp_ses_lock);
|
||||||
return tcon;
|
return tcon;
|
||||||
|
@ -2441,7 +2443,7 @@ cifs_find_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cifs_put_tcon(struct cifs_tcon *tcon)
|
cifs_put_tcon(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace)
|
||||||
{
|
{
|
||||||
unsigned int xid;
|
unsigned int xid;
|
||||||
struct cifs_ses *ses;
|
struct cifs_ses *ses;
|
||||||
|
@ -2457,6 +2459,7 @@ cifs_put_tcon(struct cifs_tcon *tcon)
|
||||||
cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
|
cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
|
||||||
spin_lock(&cifs_tcp_ses_lock);
|
spin_lock(&cifs_tcp_ses_lock);
|
||||||
spin_lock(&tcon->tc_lock);
|
spin_lock(&tcon->tc_lock);
|
||||||
|
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count - 1, trace);
|
||||||
if (--tcon->tc_count > 0) {
|
if (--tcon->tc_count > 0) {
|
||||||
spin_unlock(&tcon->tc_lock);
|
spin_unlock(&tcon->tc_lock);
|
||||||
spin_unlock(&cifs_tcp_ses_lock);
|
spin_unlock(&cifs_tcp_ses_lock);
|
||||||
|
@ -2493,7 +2496,7 @@ cifs_put_tcon(struct cifs_tcon *tcon)
|
||||||
_free_xid(xid);
|
_free_xid(xid);
|
||||||
|
|
||||||
cifs_fscache_release_super_cookie(tcon);
|
cifs_fscache_release_super_cookie(tcon);
|
||||||
tconInfoFree(tcon);
|
tconInfoFree(tcon, netfs_trace_tcon_ref_free);
|
||||||
cifs_put_smb_ses(ses);
|
cifs_put_smb_ses(ses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2547,7 +2550,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
|
||||||
nohandlecache = ctx->nohandlecache;
|
nohandlecache = ctx->nohandlecache;
|
||||||
else
|
else
|
||||||
nohandlecache = true;
|
nohandlecache = true;
|
||||||
tcon = tcon_info_alloc(!nohandlecache);
|
tcon = tcon_info_alloc(!nohandlecache, netfs_trace_tcon_ref_new);
|
||||||
if (tcon == NULL) {
|
if (tcon == NULL) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto out_fail;
|
goto out_fail;
|
||||||
|
@ -2737,7 +2740,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
|
||||||
return tcon;
|
return tcon;
|
||||||
|
|
||||||
out_fail:
|
out_fail:
|
||||||
tconInfoFree(tcon);
|
tconInfoFree(tcon, netfs_trace_tcon_ref_free_fail);
|
||||||
return ERR_PTR(rc);
|
return ERR_PTR(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2754,7 +2757,7 @@ cifs_put_tlink(struct tcon_link *tlink)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IS_ERR(tlink_tcon(tlink)))
|
if (!IS_ERR(tlink_tcon(tlink)))
|
||||||
cifs_put_tcon(tlink_tcon(tlink));
|
cifs_put_tcon(tlink_tcon(tlink), netfs_trace_tcon_ref_put_tlink);
|
||||||
kfree(tlink);
|
kfree(tlink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3319,7 +3322,7 @@ void cifs_mount_put_conns(struct cifs_mount_ctx *mnt_ctx)
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (mnt_ctx->tcon)
|
if (mnt_ctx->tcon)
|
||||||
cifs_put_tcon(mnt_ctx->tcon);
|
cifs_put_tcon(mnt_ctx->tcon, netfs_trace_tcon_ref_put_mnt_ctx);
|
||||||
else if (mnt_ctx->ses)
|
else if (mnt_ctx->ses)
|
||||||
cifs_put_smb_ses(mnt_ctx->ses);
|
cifs_put_smb_ses(mnt_ctx->ses);
|
||||||
else if (mnt_ctx->server)
|
else if (mnt_ctx->server)
|
||||||
|
|
|
@ -748,6 +748,16 @@ static int smb3_fs_context_validate(struct fs_context *fc)
|
||||||
/* set the port that we got earlier */
|
/* set the port that we got earlier */
|
||||||
cifs_set_port((struct sockaddr *)&ctx->dstaddr, ctx->port);
|
cifs_set_port((struct sockaddr *)&ctx->dstaddr, ctx->port);
|
||||||
|
|
||||||
|
if (ctx->uid_specified && !ctx->forceuid_specified) {
|
||||||
|
ctx->override_uid = 1;
|
||||||
|
pr_notice("enabling forceuid mount option implicitly because uid= option is specified\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->gid_specified && !ctx->forcegid_specified) {
|
||||||
|
ctx->override_gid = 1;
|
||||||
|
pr_notice("enabling forcegid mount option implicitly because gid= option is specified\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx->override_uid && !ctx->uid_specified) {
|
if (ctx->override_uid && !ctx->uid_specified) {
|
||||||
ctx->override_uid = 0;
|
ctx->override_uid = 0;
|
||||||
pr_notice("ignoring forceuid mount option specified with no uid= option\n");
|
pr_notice("ignoring forceuid mount option specified with no uid= option\n");
|
||||||
|
@ -1019,12 +1029,14 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
|
||||||
ctx->override_uid = 0;
|
ctx->override_uid = 0;
|
||||||
else
|
else
|
||||||
ctx->override_uid = 1;
|
ctx->override_uid = 1;
|
||||||
|
ctx->forceuid_specified = true;
|
||||||
break;
|
break;
|
||||||
case Opt_forcegid:
|
case Opt_forcegid:
|
||||||
if (result.negated)
|
if (result.negated)
|
||||||
ctx->override_gid = 0;
|
ctx->override_gid = 0;
|
||||||
else
|
else
|
||||||
ctx->override_gid = 1;
|
ctx->override_gid = 1;
|
||||||
|
ctx->forcegid_specified = true;
|
||||||
break;
|
break;
|
||||||
case Opt_perm:
|
case Opt_perm:
|
||||||
if (result.negated)
|
if (result.negated)
|
||||||
|
|
|
@ -165,6 +165,8 @@ enum cifs_param {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct smb3_fs_context {
|
struct smb3_fs_context {
|
||||||
|
bool forceuid_specified;
|
||||||
|
bool forcegid_specified;
|
||||||
bool uid_specified;
|
bool uid_specified;
|
||||||
bool cruid_specified;
|
bool cruid_specified;
|
||||||
bool gid_specified;
|
bool gid_specified;
|
||||||
|
|
|
@ -43,12 +43,23 @@ int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
|
||||||
char *key;
|
char *key;
|
||||||
int ret = -ENOMEM;
|
int ret = -ENOMEM;
|
||||||
|
|
||||||
|
if (tcon->fscache_acquired)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
mutex_lock(&tcon->fscache_lock);
|
||||||
|
if (tcon->fscache_acquired) {
|
||||||
|
mutex_unlock(&tcon->fscache_lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
tcon->fscache_acquired = true;
|
||||||
|
|
||||||
tcon->fscache = NULL;
|
tcon->fscache = NULL;
|
||||||
switch (sa->sa_family) {
|
switch (sa->sa_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
mutex_unlock(&tcon->fscache_lock);
|
||||||
cifs_dbg(VFS, "Unknown network family '%d'\n", sa->sa_family);
|
cifs_dbg(VFS, "Unknown network family '%d'\n", sa->sa_family);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -57,6 +68,7 @@ int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
|
||||||
|
|
||||||
sharename = extract_sharename(tcon->tree_name);
|
sharename = extract_sharename(tcon->tree_name);
|
||||||
if (IS_ERR(sharename)) {
|
if (IS_ERR(sharename)) {
|
||||||
|
mutex_unlock(&tcon->fscache_lock);
|
||||||
cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__);
|
cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__);
|
||||||
return PTR_ERR(sharename);
|
return PTR_ERR(sharename);
|
||||||
}
|
}
|
||||||
|
@ -82,6 +94,11 @@ int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
|
||||||
}
|
}
|
||||||
pr_err("Cache volume key already in use (%s)\n", key);
|
pr_err("Cache volume key already in use (%s)\n", key);
|
||||||
vcookie = NULL;
|
vcookie = NULL;
|
||||||
|
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
|
||||||
|
netfs_trace_tcon_ref_see_fscache_collision);
|
||||||
|
} else {
|
||||||
|
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
|
||||||
|
netfs_trace_tcon_ref_see_fscache_okay);
|
||||||
}
|
}
|
||||||
|
|
||||||
tcon->fscache = vcookie;
|
tcon->fscache = vcookie;
|
||||||
|
@ -90,6 +107,7 @@ out_2:
|
||||||
kfree(key);
|
kfree(key);
|
||||||
out:
|
out:
|
||||||
kfree(sharename);
|
kfree(sharename);
|
||||||
|
mutex_unlock(&tcon->fscache_lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +120,8 @@ void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon)
|
||||||
cifs_fscache_fill_volume_coherency(tcon, &cd);
|
cifs_fscache_fill_volume_coherency(tcon, &cd);
|
||||||
fscache_relinquish_volume(tcon->fscache, &cd, false);
|
fscache_relinquish_volume(tcon->fscache, &cd, false);
|
||||||
tcon->fscache = NULL;
|
tcon->fscache = NULL;
|
||||||
|
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
|
||||||
|
netfs_trace_tcon_ref_see_fscache_relinq);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cifs_fscache_get_inode_cookie(struct inode *inode)
|
void cifs_fscache_get_inode_cookie(struct inode *inode)
|
||||||
|
|
|
@ -111,9 +111,10 @@ sesInfoFree(struct cifs_ses *buf_to_free)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cifs_tcon *
|
struct cifs_tcon *
|
||||||
tcon_info_alloc(bool dir_leases_enabled)
|
tcon_info_alloc(bool dir_leases_enabled, enum smb3_tcon_ref_trace trace)
|
||||||
{
|
{
|
||||||
struct cifs_tcon *ret_buf;
|
struct cifs_tcon *ret_buf;
|
||||||
|
static atomic_t tcon_debug_id;
|
||||||
|
|
||||||
ret_buf = kzalloc(sizeof(*ret_buf), GFP_KERNEL);
|
ret_buf = kzalloc(sizeof(*ret_buf), GFP_KERNEL);
|
||||||
if (!ret_buf)
|
if (!ret_buf)
|
||||||
|
@ -130,7 +131,8 @@ tcon_info_alloc(bool dir_leases_enabled)
|
||||||
|
|
||||||
atomic_inc(&tconInfoAllocCount);
|
atomic_inc(&tconInfoAllocCount);
|
||||||
ret_buf->status = TID_NEW;
|
ret_buf->status = TID_NEW;
|
||||||
++ret_buf->tc_count;
|
ret_buf->debug_id = atomic_inc_return(&tcon_debug_id);
|
||||||
|
ret_buf->tc_count = 1;
|
||||||
spin_lock_init(&ret_buf->tc_lock);
|
spin_lock_init(&ret_buf->tc_lock);
|
||||||
INIT_LIST_HEAD(&ret_buf->openFileList);
|
INIT_LIST_HEAD(&ret_buf->openFileList);
|
||||||
INIT_LIST_HEAD(&ret_buf->tcon_list);
|
INIT_LIST_HEAD(&ret_buf->tcon_list);
|
||||||
|
@ -139,17 +141,22 @@ tcon_info_alloc(bool dir_leases_enabled)
|
||||||
atomic_set(&ret_buf->num_local_opens, 0);
|
atomic_set(&ret_buf->num_local_opens, 0);
|
||||||
atomic_set(&ret_buf->num_remote_opens, 0);
|
atomic_set(&ret_buf->num_remote_opens, 0);
|
||||||
ret_buf->stats_from_time = ktime_get_real_seconds();
|
ret_buf->stats_from_time = ktime_get_real_seconds();
|
||||||
|
#ifdef CONFIG_CIFS_FSCACHE
|
||||||
|
mutex_init(&ret_buf->fscache_lock);
|
||||||
|
#endif
|
||||||
|
trace_smb3_tcon_ref(ret_buf->debug_id, ret_buf->tc_count, trace);
|
||||||
|
|
||||||
return ret_buf;
|
return ret_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
tconInfoFree(struct cifs_tcon *tcon)
|
tconInfoFree(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace)
|
||||||
{
|
{
|
||||||
if (tcon == NULL) {
|
if (tcon == NULL) {
|
||||||
cifs_dbg(FYI, "Null buffer passed to tconInfoFree\n");
|
cifs_dbg(FYI, "Null buffer passed to tconInfoFree\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, trace);
|
||||||
free_cached_dirs(tcon->cfids);
|
free_cached_dirs(tcon->cfids);
|
||||||
atomic_dec(&tconInfoAllocCount);
|
atomic_dec(&tconInfoAllocCount);
|
||||||
kfree(tcon->nativeFileSystem);
|
kfree(tcon->nativeFileSystem);
|
||||||
|
|
|
@ -767,7 +767,7 @@ smb2_cancelled_close_fid(struct work_struct *work)
|
||||||
if (rc)
|
if (rc)
|
||||||
cifs_tcon_dbg(VFS, "Close cancelled mid failed rc:%d\n", rc);
|
cifs_tcon_dbg(VFS, "Close cancelled mid failed rc:%d\n", rc);
|
||||||
|
|
||||||
cifs_put_tcon(tcon);
|
cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cancelled_close_fid);
|
||||||
kfree(cancelled);
|
kfree(cancelled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -811,6 +811,8 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid,
|
||||||
if (tcon->tc_count <= 0) {
|
if (tcon->tc_count <= 0) {
|
||||||
struct TCP_Server_Info *server = NULL;
|
struct TCP_Server_Info *server = NULL;
|
||||||
|
|
||||||
|
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
|
||||||
|
netfs_trace_tcon_ref_see_cancelled_close);
|
||||||
WARN_ONCE(tcon->tc_count < 0, "tcon refcount is negative");
|
WARN_ONCE(tcon->tc_count < 0, "tcon refcount is negative");
|
||||||
spin_unlock(&cifs_tcp_ses_lock);
|
spin_unlock(&cifs_tcp_ses_lock);
|
||||||
|
|
||||||
|
@ -823,12 +825,14 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
tcon->tc_count++;
|
tcon->tc_count++;
|
||||||
|
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
|
||||||
|
netfs_trace_tcon_ref_get_cancelled_close);
|
||||||
spin_unlock(&cifs_tcp_ses_lock);
|
spin_unlock(&cifs_tcp_ses_lock);
|
||||||
|
|
||||||
rc = __smb2_handle_cancelled_cmd(tcon, SMB2_CLOSE_HE, 0,
|
rc = __smb2_handle_cancelled_cmd(tcon, SMB2_CLOSE_HE, 0,
|
||||||
persistent_fid, volatile_fid);
|
persistent_fid, volatile_fid);
|
||||||
if (rc)
|
if (rc)
|
||||||
cifs_put_tcon(tcon);
|
cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cancelled_close);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -856,7 +860,7 @@ smb2_handle_cancelled_mid(struct mid_q_entry *mid, struct TCP_Server_Info *serve
|
||||||
rsp->PersistentFileId,
|
rsp->PersistentFileId,
|
||||||
rsp->VolatileFileId);
|
rsp->VolatileFileId);
|
||||||
if (rc)
|
if (rc)
|
||||||
cifs_put_tcon(tcon);
|
cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cancelled_mid);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2915,8 +2915,11 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
|
||||||
tcon = list_first_entry_or_null(&ses->tcon_list,
|
tcon = list_first_entry_or_null(&ses->tcon_list,
|
||||||
struct cifs_tcon,
|
struct cifs_tcon,
|
||||||
tcon_list);
|
tcon_list);
|
||||||
if (tcon)
|
if (tcon) {
|
||||||
tcon->tc_count++;
|
tcon->tc_count++;
|
||||||
|
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
|
||||||
|
netfs_trace_tcon_ref_get_dfs_refer);
|
||||||
|
}
|
||||||
spin_unlock(&cifs_tcp_ses_lock);
|
spin_unlock(&cifs_tcp_ses_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2980,6 +2983,8 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
|
||||||
/* ipc tcons are not refcounted */
|
/* ipc tcons are not refcounted */
|
||||||
spin_lock(&cifs_tcp_ses_lock);
|
spin_lock(&cifs_tcp_ses_lock);
|
||||||
tcon->tc_count--;
|
tcon->tc_count--;
|
||||||
|
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
|
||||||
|
netfs_trace_tcon_ref_dec_dfs_refer);
|
||||||
/* tc_count can never go negative */
|
/* tc_count can never go negative */
|
||||||
WARN_ON(tcon->tc_count < 0);
|
WARN_ON(tcon->tc_count < 0);
|
||||||
spin_unlock(&cifs_tcp_ses_lock);
|
spin_unlock(&cifs_tcp_ses_lock);
|
||||||
|
|
|
@ -4138,6 +4138,8 @@ void smb2_reconnect_server(struct work_struct *work)
|
||||||
list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
|
list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
|
||||||
if (tcon->need_reconnect || tcon->need_reopen_files) {
|
if (tcon->need_reconnect || tcon->need_reopen_files) {
|
||||||
tcon->tc_count++;
|
tcon->tc_count++;
|
||||||
|
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
|
||||||
|
netfs_trace_tcon_ref_get_reconnect_server);
|
||||||
list_add_tail(&tcon->rlist, &tmp_list);
|
list_add_tail(&tcon->rlist, &tmp_list);
|
||||||
tcon_selected = true;
|
tcon_selected = true;
|
||||||
}
|
}
|
||||||
|
@ -4176,14 +4178,14 @@ void smb2_reconnect_server(struct work_struct *work)
|
||||||
if (tcon->ipc)
|
if (tcon->ipc)
|
||||||
cifs_put_smb_ses(tcon->ses);
|
cifs_put_smb_ses(tcon->ses);
|
||||||
else
|
else
|
||||||
cifs_put_tcon(tcon);
|
cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_reconnect_server);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ses_exist)
|
if (!ses_exist)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* allocate a dummy tcon struct used for reconnect */
|
/* allocate a dummy tcon struct used for reconnect */
|
||||||
tcon = tcon_info_alloc(false);
|
tcon = tcon_info_alloc(false, netfs_trace_tcon_ref_new_reconnect_server);
|
||||||
if (!tcon) {
|
if (!tcon) {
|
||||||
resched = true;
|
resched = true;
|
||||||
list_for_each_entry_safe(ses, ses2, &tmp_ses_list, rlist) {
|
list_for_each_entry_safe(ses, ses2, &tmp_ses_list, rlist) {
|
||||||
|
@ -4206,7 +4208,7 @@ void smb2_reconnect_server(struct work_struct *work)
|
||||||
list_del_init(&ses->rlist);
|
list_del_init(&ses->rlist);
|
||||||
cifs_put_smb_ses(ses);
|
cifs_put_smb_ses(ses);
|
||||||
}
|
}
|
||||||
tconInfoFree(tcon);
|
tconInfoFree(tcon, netfs_trace_tcon_ref_free_reconnect_server);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
cifs_dbg(FYI, "Reconnecting tcons and channels finished\n");
|
cifs_dbg(FYI, "Reconnecting tcons and channels finished\n");
|
||||||
|
|
|
@ -189,6 +189,8 @@ smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32 tid)
|
||||||
if (tcon->tid != tid)
|
if (tcon->tid != tid)
|
||||||
continue;
|
continue;
|
||||||
++tcon->tc_count;
|
++tcon->tc_count;
|
||||||
|
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
|
||||||
|
netfs_trace_tcon_ref_get_find_sess_tcon);
|
||||||
return tcon;
|
return tcon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
* Copyright (C) 2018, Microsoft Corporation.
|
* Copyright (C) 2018, Microsoft Corporation.
|
||||||
*
|
*
|
||||||
* Author(s): Steve French <stfrench@microsoft.com>
|
* Author(s): Steve French <stfrench@microsoft.com>
|
||||||
|
*
|
||||||
|
* Please use this 3-part article as a reference for writing new tracepoints:
|
||||||
|
* https://lwn.net/Articles/379903/
|
||||||
*/
|
*/
|
||||||
#undef TRACE_SYSTEM
|
#undef TRACE_SYSTEM
|
||||||
#define TRACE_SYSTEM cifs
|
#define TRACE_SYSTEM cifs
|
||||||
|
@ -15,9 +18,70 @@
|
||||||
#include <linux/inet.h>
|
#include <linux/inet.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Please use this 3-part article as a reference for writing new tracepoints:
|
* Specify enums for tracing information.
|
||||||
* https://lwn.net/Articles/379903/
|
|
||||||
*/
|
*/
|
||||||
|
#define smb3_tcon_ref_traces \
|
||||||
|
EM(netfs_trace_tcon_ref_dec_dfs_refer, "DEC DfsRef") \
|
||||||
|
EM(netfs_trace_tcon_ref_free, "FRE ") \
|
||||||
|
EM(netfs_trace_tcon_ref_free_fail, "FRE Fail ") \
|
||||||
|
EM(netfs_trace_tcon_ref_free_ipc, "FRE Ipc ") \
|
||||||
|
EM(netfs_trace_tcon_ref_free_ipc_fail, "FRE Ipc-F ") \
|
||||||
|
EM(netfs_trace_tcon_ref_free_reconnect_server, "FRE Reconn") \
|
||||||
|
EM(netfs_trace_tcon_ref_get_cancelled_close, "GET Cn-Cls") \
|
||||||
|
EM(netfs_trace_tcon_ref_get_dfs_refer, "GET DfsRef") \
|
||||||
|
EM(netfs_trace_tcon_ref_get_find, "GET Find ") \
|
||||||
|
EM(netfs_trace_tcon_ref_get_find_sess_tcon, "GET FndSes") \
|
||||||
|
EM(netfs_trace_tcon_ref_get_reconnect_server, "GET Reconn") \
|
||||||
|
EM(netfs_trace_tcon_ref_new, "NEW ") \
|
||||||
|
EM(netfs_trace_tcon_ref_new_ipc, "NEW Ipc ") \
|
||||||
|
EM(netfs_trace_tcon_ref_new_reconnect_server, "NEW Reconn") \
|
||||||
|
EM(netfs_trace_tcon_ref_put_cancelled_close, "PUT Cn-Cls") \
|
||||||
|
EM(netfs_trace_tcon_ref_put_cancelled_close_fid, "PUT Cn-Fid") \
|
||||||
|
EM(netfs_trace_tcon_ref_put_cancelled_mid, "PUT Cn-Mid") \
|
||||||
|
EM(netfs_trace_tcon_ref_put_mnt_ctx, "PUT MntCtx") \
|
||||||
|
EM(netfs_trace_tcon_ref_put_reconnect_server, "PUT Reconn") \
|
||||||
|
EM(netfs_trace_tcon_ref_put_tlink, "PUT Tlink ") \
|
||||||
|
EM(netfs_trace_tcon_ref_see_cancelled_close, "SEE Cn-Cls") \
|
||||||
|
EM(netfs_trace_tcon_ref_see_fscache_collision, "SEE FV-CO!") \
|
||||||
|
EM(netfs_trace_tcon_ref_see_fscache_okay, "SEE FV-Ok ") \
|
||||||
|
EM(netfs_trace_tcon_ref_see_fscache_relinq, "SEE FV-Rlq") \
|
||||||
|
E_(netfs_trace_tcon_ref_see_umount, "SEE Umount")
|
||||||
|
|
||||||
|
#undef EM
|
||||||
|
#undef E_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define those tracing enums.
|
||||||
|
*/
|
||||||
|
#ifndef __SMB3_DECLARE_TRACE_ENUMS_ONCE_ONLY
|
||||||
|
#define __SMB3_DECLARE_TRACE_ENUMS_ONCE_ONLY
|
||||||
|
|
||||||
|
#define EM(a, b) a,
|
||||||
|
#define E_(a, b) a
|
||||||
|
|
||||||
|
enum smb3_tcon_ref_trace { smb3_tcon_ref_traces } __mode(byte);
|
||||||
|
|
||||||
|
#undef EM
|
||||||
|
#undef E_
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Export enum symbols via userspace.
|
||||||
|
*/
|
||||||
|
#define EM(a, b) TRACE_DEFINE_ENUM(a);
|
||||||
|
#define E_(a, b) TRACE_DEFINE_ENUM(a);
|
||||||
|
|
||||||
|
smb3_tcon_ref_traces;
|
||||||
|
|
||||||
|
#undef EM
|
||||||
|
#undef E_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now redefine the EM() and E_() macros to map the enums to the strings that
|
||||||
|
* will be printed in the output.
|
||||||
|
*/
|
||||||
|
#define EM(a, b) { a, b },
|
||||||
|
#define E_(a, b) { a, b }
|
||||||
|
|
||||||
/* For logging errors in read or write */
|
/* For logging errors in read or write */
|
||||||
DECLARE_EVENT_CLASS(smb3_rw_err_class,
|
DECLARE_EVENT_CLASS(smb3_rw_err_class,
|
||||||
|
@ -1125,6 +1189,30 @@ DEFINE_SMB3_CREDIT_EVENT(waitff_credits);
|
||||||
DEFINE_SMB3_CREDIT_EVENT(overflow_credits);
|
DEFINE_SMB3_CREDIT_EVENT(overflow_credits);
|
||||||
DEFINE_SMB3_CREDIT_EVENT(set_credits);
|
DEFINE_SMB3_CREDIT_EVENT(set_credits);
|
||||||
|
|
||||||
|
|
||||||
|
TRACE_EVENT(smb3_tcon_ref,
|
||||||
|
TP_PROTO(unsigned int tcon_debug_id, int ref,
|
||||||
|
enum smb3_tcon_ref_trace trace),
|
||||||
|
TP_ARGS(tcon_debug_id, ref, trace),
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__field(unsigned int, tcon)
|
||||||
|
__field(int, ref)
|
||||||
|
__field(enum smb3_tcon_ref_trace, trace)
|
||||||
|
),
|
||||||
|
TP_fast_assign(
|
||||||
|
__entry->tcon = tcon_debug_id;
|
||||||
|
__entry->ref = ref;
|
||||||
|
__entry->trace = trace;
|
||||||
|
),
|
||||||
|
TP_printk("TC=%08x %s r=%u",
|
||||||
|
__entry->tcon,
|
||||||
|
__print_symbolic(__entry->trace, smb3_tcon_ref_traces),
|
||||||
|
__entry->ref)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
#undef EM
|
||||||
|
#undef E_
|
||||||
#endif /* _CIFS_TRACE_H */
|
#endif /* _CIFS_TRACE_H */
|
||||||
|
|
||||||
#undef TRACE_INCLUDE_PATH
|
#undef TRACE_INCLUDE_PATH
|
||||||
|
|
Loading…
Reference in New Issue