Skip to content

Commit 9d1ddab

Browse files
committed
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
2 parents 71b1543 + 77d8aa7 commit 9d1ddab

File tree

13 files changed

+176
-26
lines changed

13 files changed

+176
-26
lines changed

fs/smb/client/cifsfs.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,7 @@ cifs_alloc_inode(struct super_block *sb)
389389
* server, can not assume caching of file data or metadata.
390390
*/
391391
cifs_set_oplock_level(cifs_inode, 0);
392+
cifs_inode->lease_granted = false;
392393
cifs_inode->flags = 0;
393394
spin_lock_init(&cifs_inode->writers_lock);
394395
cifs_inode->writers = 0;
@@ -739,6 +740,8 @@ static void cifs_umount_begin(struct super_block *sb)
739740

740741
spin_lock(&cifs_tcp_ses_lock);
741742
spin_lock(&tcon->tc_lock);
743+
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
744+
netfs_trace_tcon_ref_see_umount);
742745
if ((tcon->tc_count > 1) || (tcon->status == TID_EXITING)) {
743746
/* we have other mounts to same share or we have
744747
already tried to umount this and woken up

fs/smb/client/cifsglob.h

Lines changed: 3 additions & 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 */
@@ -1276,7 +1277,9 @@ struct cifs_tcon {
12761277
__u32 max_cached_dirs;
12771278
#ifdef CONFIG_CIFS_FSCACHE
12781279
u64 resource_id; /* server resource id */
1280+
bool fscache_acquired; /* T if we've tried acquiring a cookie */
12791281
struct fscache_volume *fscache; /* cookie for share */
1282+
struct mutex fscache_lock; /* Prevent regetting a cookie */
12801283
#endif
12811284
struct list_head pending_opens; /* list of incomplete opens */
12821285
struct cached_fids *cfids;

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/fs_context.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,16 @@ static int smb3_fs_context_validate(struct fs_context *fc)
748748
/* set the port that we got earlier */
749749
cifs_set_port((struct sockaddr *)&ctx->dstaddr, ctx->port);
750750

751+
if (ctx->uid_specified && !ctx->forceuid_specified) {
752+
ctx->override_uid = 1;
753+
pr_notice("enabling forceuid mount option implicitly because uid= option is specified\n");
754+
}
755+
756+
if (ctx->gid_specified && !ctx->forcegid_specified) {
757+
ctx->override_gid = 1;
758+
pr_notice("enabling forcegid mount option implicitly because gid= option is specified\n");
759+
}
760+
751761
if (ctx->override_uid && !ctx->uid_specified) {
752762
ctx->override_uid = 0;
753763
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,
10191029
ctx->override_uid = 0;
10201030
else
10211031
ctx->override_uid = 1;
1032+
ctx->forceuid_specified = true;
10221033
break;
10231034
case Opt_forcegid:
10241035
if (result.negated)
10251036
ctx->override_gid = 0;
10261037
else
10271038
ctx->override_gid = 1;
1039+
ctx->forcegid_specified = true;
10281040
break;
10291041
case Opt_perm:
10301042
if (result.negated)

fs/smb/client/fs_context.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ enum cifs_param {
165165
};
166166

167167
struct smb3_fs_context {
168+
bool forceuid_specified;
169+
bool forcegid_specified;
168170
bool uid_specified;
169171
bool cruid_specified;
170172
bool gid_specified;

fs/smb/client/fscache.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,23 @@ int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
4343
char *key;
4444
int ret = -ENOMEM;
4545

46+
if (tcon->fscache_acquired)
47+
return 0;
48+
49+
mutex_lock(&tcon->fscache_lock);
50+
if (tcon->fscache_acquired) {
51+
mutex_unlock(&tcon->fscache_lock);
52+
return 0;
53+
}
54+
tcon->fscache_acquired = true;
55+
4656
tcon->fscache = NULL;
4757
switch (sa->sa_family) {
4858
case AF_INET:
4959
case AF_INET6:
5060
break;
5161
default:
62+
mutex_unlock(&tcon->fscache_lock);
5263
cifs_dbg(VFS, "Unknown network family '%d'\n", sa->sa_family);
5364
return -EINVAL;
5465
}
@@ -57,6 +68,7 @@ int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
5768

5869
sharename = extract_sharename(tcon->tree_name);
5970
if (IS_ERR(sharename)) {
71+
mutex_unlock(&tcon->fscache_lock);
6072
cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__);
6173
return PTR_ERR(sharename);
6274
}
@@ -82,6 +94,11 @@ int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
8294
}
8395
pr_err("Cache volume key already in use (%s)\n", key);
8496
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);
85102
}
86103

87104
tcon->fscache = vcookie;
@@ -90,6 +107,7 @@ int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
90107
kfree(key);
91108
out:
92109
kfree(sharename);
110+
mutex_unlock(&tcon->fscache_lock);
93111
return ret;
94112
}
95113

@@ -102,6 +120,8 @@ void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon)
102120
cifs_fscache_fill_volume_coherency(tcon, &cd);
103121
fscache_relinquish_volume(tcon->fscache, &cd, false);
104122
tcon->fscache = NULL;
123+
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
124+
netfs_trace_tcon_ref_see_fscache_relinq);
105125
}
106126

107127
void cifs_fscache_get_inode_cookie(struct inode *inode)

fs/smb/client/misc.c

Lines changed: 10 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);
@@ -139,17 +141,22 @@ tcon_info_alloc(bool dir_leases_enabled)
139141
atomic_set(&ret_buf->num_local_opens, 0);
140142
atomic_set(&ret_buf->num_remote_opens, 0);
141143
ret_buf->stats_from_time = ktime_get_real_seconds();
144+
#ifdef CONFIG_CIFS_FSCACHE
145+
mutex_init(&ret_buf->fscache_lock);
146+
#endif
147+
trace_smb3_tcon_ref(ret_buf->debug_id, ret_buf->tc_count, trace);
142148

143149
return ret_buf;
144150
}
145151

146152
void
147-
tconInfoFree(struct cifs_tcon *tcon)
153+
tconInfoFree(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace)
148154
{
149155
if (tcon == NULL) {
150156
cifs_dbg(FYI, "Null buffer passed to tconInfoFree\n");
151157
return;
152158
}
159+
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, trace);
153160
free_cached_dirs(tcon->cfids);
154161
atomic_dec(&tconInfoAllocCount);
155162
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);

0 commit comments

Comments
 (0)