Skip to content

Commit c8103c2

Browse files
committed
Merge tag '5.16-rc-part2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6
Pull more cifs updates from Steve French: - improvements to reconnect and multichannel - a performance improvement (additional use of SMB3 compounding) - DFS code cleanup and improvements - various trivial Coverity fixes - two fscache fixes - an fsync fix * tag '5.16-rc-part2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6: (23 commits) cifs: do not duplicate fscache cookie for secondary channels cifs: connect individual channel servers to primary channel server cifs: protect session channel fields with chan_lock cifs: do not negotiate session if session already exists smb3: do not setup the fscache_super_cookie until fsinfo initialized cifs: fix potential use-after-free bugs cifs: fix memory leak of smb3_fs_context_dup::server_hostname smb3: add additional null check in SMB311_posix_mkdir cifs: release lock earlier in dequeue_mid error case smb3: add additional null check in SMB2_tcon smb3: add additional null check in SMB2_open smb3: add additional null check in SMB2_ioctl smb3: remove trivial dfs compile warning cifs: support nested dfs links over reconnect smb3: do not error on fsync when readonly cifs: for compound requests, use open handle if possible cifs: set a minimum of 120s for next dns resolution cifs: split out dfs code from cifs_reconnect() cifs: convert list_for_each to entry variant cifs: introduce new helper for cifs_reconnect() ...
2 parents d0b51bf + 46bb1b9 commit c8103c2

18 files changed

+1184
-933
lines changed

fs/cifs/cifs_debug.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,8 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
271271
c = 0;
272272
spin_lock(&cifs_tcp_ses_lock);
273273
list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
274-
if (server->is_channel)
274+
/* channel info will be printed as a part of sessions below */
275+
if (CIFS_SERVER_IS_CHAN(server))
275276
continue;
276277

277278
c++;
@@ -358,6 +359,8 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
358359
seq_printf(m, " signed");
359360
if (server->posix_ext_supported)
360361
seq_printf(m, " posix");
362+
if (server->nosharesock)
363+
seq_printf(m, " nosharesock");
361364

362365
if (server->rdma)
363366
seq_printf(m, "\nRDMA ");
@@ -412,12 +415,14 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
412415
from_kuid(&init_user_ns, ses->linux_uid),
413416
from_kuid(&init_user_ns, ses->cred_uid));
414417

418+
spin_lock(&ses->chan_lock);
415419
if (ses->chan_count > 1) {
416420
seq_printf(m, "\n\n\tExtra Channels: %zu ",
417421
ses->chan_count-1);
418422
for (j = 1; j < ses->chan_count; j++)
419423
cifs_dump_channel(m, j, &ses->chans[j]);
420424
}
425+
spin_unlock(&ses->chan_lock);
421426

422427
seq_puts(m, "\n\n\tShares: ");
423428
j = 0;

fs/cifs/cifs_dfs_ref.c

Lines changed: 2 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -307,12 +307,8 @@ static struct vfsmount *cifs_dfs_do_mount(struct dentry *mntpt,
307307
static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
308308
{
309309
struct cifs_sb_info *cifs_sb;
310-
struct cifs_ses *ses;
311-
struct cifs_tcon *tcon;
312310
void *page;
313-
char *full_path, *root_path;
314-
unsigned int xid;
315-
int rc;
311+
char *full_path;
316312
struct vfsmount *mnt;
317313

318314
cifs_dbg(FYI, "in %s\n", __func__);
@@ -324,8 +320,6 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
324320
* the double backslashes usually used in the UNC. This function
325321
* gives us the latter, so we must adjust the result.
326322
*/
327-
mnt = ERR_PTR(-ENOMEM);
328-
329323
cifs_sb = CIFS_SB(mntpt->d_sb);
330324
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) {
331325
mnt = ERR_PTR(-EREMOTE);
@@ -341,60 +335,11 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
341335
}
342336

343337
convert_delimiter(full_path, '\\');
344-
345338
cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
346339

347-
if (!cifs_sb_master_tlink(cifs_sb)) {
348-
cifs_dbg(FYI, "%s: master tlink is NULL\n", __func__);
349-
goto free_full_path;
350-
}
351-
352-
tcon = cifs_sb_master_tcon(cifs_sb);
353-
if (!tcon) {
354-
cifs_dbg(FYI, "%s: master tcon is NULL\n", __func__);
355-
goto free_full_path;
356-
}
357-
358-
root_path = kstrdup(tcon->treeName, GFP_KERNEL);
359-
if (!root_path) {
360-
mnt = ERR_PTR(-ENOMEM);
361-
goto free_full_path;
362-
}
363-
cifs_dbg(FYI, "%s: root path: %s\n", __func__, root_path);
364-
365-
ses = tcon->ses;
366-
xid = get_xid();
367-
368-
/*
369-
* If DFS root has been expired, then unconditionally fetch it again to
370-
* refresh DFS referral cache.
371-
*/
372-
rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
373-
root_path + 1, NULL, NULL);
374-
if (!rc) {
375-
rc = dfs_cache_find(xid, ses, cifs_sb->local_nls,
376-
cifs_remap(cifs_sb), full_path + 1,
377-
NULL, NULL);
378-
}
379-
380-
free_xid(xid);
381-
382-
if (rc) {
383-
mnt = ERR_PTR(rc);
384-
goto free_root_path;
385-
}
386-
/*
387-
* OK - we were able to get and cache a referral for @full_path.
388-
*
389-
* Now, pass it down to cifs_mount() and it will retry every available
390-
* node server in case of failures - no need to do it here.
391-
*/
392340
mnt = cifs_dfs_do_mount(mntpt, cifs_sb, full_path);
393-
cifs_dbg(FYI, "%s: cifs_dfs_do_mount:%s , mnt:%p\n", __func__,
394-
full_path + 1, mnt);
341+
cifs_dbg(FYI, "%s: cifs_dfs_do_mount:%s , mnt:%p\n", __func__, full_path + 1, mnt);
395342

396-
free_root_path:
397-
kfree(root_path);
398343
free_full_path:
399344
free_dentry_path(page);
400345
cdda_exit:

fs/cifs/cifs_fs_sb.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,6 @@ struct cifs_sb_info {
6161
/* only used when CIFS_MOUNT_USE_PREFIX_PATH is set */
6262
char *prepath;
6363

64-
/*
65-
* Canonical DFS path initially provided by the mount call. We might connect to something
66-
* different via DFS but we want to keep it to do failover properly.
67-
*/
68-
char *origin_fullpath; /* \\HOST\SHARE\[OPTIONAL PATH] */
6964
/* randomly generated 128-bit number for indexing dfs mount groups in referral cache */
7065
uuid_t dfs_mount_id;
7166
/*

fs/cifs/cifsglob.h

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/slab.h>
1616
#include <linux/mempool.h>
1717
#include <linux/workqueue.h>
18+
#include <linux/utsname.h>
1819
#include "cifs_fs_sb.h"
1920
#include "cifsacl.h"
2021
#include <crypto/internal/hash.h>
@@ -75,7 +76,8 @@
7576
#define SMB_ECHO_INTERVAL_MAX 600
7677
#define SMB_ECHO_INTERVAL_DEFAULT 60
7778

78-
/* dns resolution interval in seconds */
79+
/* dns resolution intervals in seconds */
80+
#define SMB_DNS_RESOLVE_INTERVAL_MIN 120
7981
#define SMB_DNS_RESOLVE_INTERVAL_DEFAULT 600
8082

8183
/* maximum number of PDUs in one compound */
@@ -99,6 +101,8 @@
99101
#define XATTR_DOS_ATTRIB "user.DOSATTRIB"
100102
#endif
101103

104+
#define CIFS_MAX_WORKSTATION_LEN (__NEW_UTS_LEN + 1) /* reasonable max for client */
105+
102106
/*
103107
* CIFS vfs client Status information (based on what we know.)
104108
*/
@@ -592,6 +596,7 @@ struct TCP_Server_Info {
592596
struct list_head pending_mid_q;
593597
bool noblocksnd; /* use blocking sendmsg */
594598
bool noautotune; /* do not autotune send buf sizes */
599+
bool nosharesock;
595600
bool tcp_nodelay;
596601
unsigned int credits; /* send no more requests at once */
597602
unsigned int max_credits; /* can override large 32000 default at mnt */
@@ -685,13 +690,34 @@ struct TCP_Server_Info {
685690
*/
686691
int nr_targets;
687692
bool noblockcnt; /* use non-blocking connect() */
688-
bool is_channel; /* if a session channel */
693+
694+
/*
695+
* If this is a session channel,
696+
* primary_server holds the ref-counted
697+
* pointer to primary channel connection for the session.
698+
*/
699+
#define CIFS_SERVER_IS_CHAN(server) (!!(server)->primary_server)
700+
struct TCP_Server_Info *primary_server;
701+
689702
#ifdef CONFIG_CIFS_SWN_UPCALL
690703
bool use_swn_dstaddr;
691704
struct sockaddr_storage swn_dstaddr;
692705
#endif
693706
#ifdef CONFIG_CIFS_DFS_UPCALL
694707
bool is_dfs_conn; /* if a dfs connection */
708+
struct mutex refpath_lock; /* protects leaf_fullpath */
709+
/*
710+
* Canonical DFS full paths that were used to chase referrals in mount and reconnect.
711+
*
712+
* origin_fullpath: first or original referral path
713+
* leaf_fullpath: last referral path (might be changed due to nested links in reconnect)
714+
*
715+
* current_fullpath: pointer to either origin_fullpath or leaf_fullpath
716+
* NOTE: cannot be accessed outside cifs_reconnect() and smb2_reconnect()
717+
*
718+
* format: \\HOST\SHARE\[OPTIONAL PATH]
719+
*/
720+
char *origin_fullpath, *leaf_fullpath, *current_fullpath;
695721
#endif
696722
};
697723

@@ -908,6 +934,7 @@ struct cifs_ses {
908934
and after mount option parsing we fill it */
909935
char *domainName;
910936
char *password;
937+
char *workstation_name;
911938
struct session_key auth_key;
912939
struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */
913940
enum securityEnum sectype; /* what security flavor was specified? */
@@ -933,16 +960,21 @@ struct cifs_ses {
933960
* iface_lock should be taken when accessing any of these fields
934961
*/
935962
spinlock_t iface_lock;
963+
/* ========= begin: protected by iface_lock ======== */
936964
struct cifs_server_iface *iface_list;
937965
size_t iface_count;
938966
unsigned long iface_last_update; /* jiffies */
967+
/* ========= end: protected by iface_lock ======== */
939968

969+
spinlock_t chan_lock;
970+
/* ========= begin: protected by chan_lock ======== */
940971
#define CIFS_MAX_CHANNELS 16
941972
struct cifs_chan chans[CIFS_MAX_CHANNELS];
942973
struct cifs_chan *binding_chan;
943974
size_t chan_count;
944975
size_t chan_max;
945976
atomic_t chan_seq; /* round robin state */
977+
/* ========= end: protected by chan_lock ======== */
946978
};
947979

948980
/*
@@ -1091,7 +1123,6 @@ struct cifs_tcon {
10911123
struct cached_fid crfid; /* Cached root fid */
10921124
/* BB add field for back pointer to sb struct(s)? */
10931125
#ifdef CONFIG_CIFS_DFS_UPCALL
1094-
char *dfs_path; /* canonical DFS path */
10951126
struct list_head ulist; /* cache update list */
10961127
#endif
10971128
};
@@ -1942,4 +1973,14 @@ static inline bool is_tcon_dfs(struct cifs_tcon *tcon)
19421973
tcon->share_flags & (SHI1005_FLAGS_DFS | SHI1005_FLAGS_DFS_ROOT);
19431974
}
19441975

1976+
static inline bool cifs_is_referral_server(struct cifs_tcon *tcon,
1977+
const struct dfs_info3_param *ref)
1978+
{
1979+
/*
1980+
* Check if all targets are capable of handling DFS referrals as per
1981+
* MS-DFSC 2.2.4 RESP_GET_DFS_REFERRAL.
1982+
*/
1983+
return is_tcon_dfs(tcon) || (ref && (ref->flags & DFSREF_REFERRAL_SERVER));
1984+
}
1985+
19451986
#endif /* _CIFS_GLOB_H */

fs/cifs/cifsproto.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,8 +269,9 @@ extern void cifs_close_all_deferred_files(struct cifs_tcon *cifs_tcon);
269269

270270
extern void cifs_close_deferred_file_under_dentry(struct cifs_tcon *cifs_tcon,
271271
const char *path);
272-
273-
extern struct TCP_Server_Info *cifs_get_tcp_session(struct smb3_fs_context *ctx);
272+
extern struct TCP_Server_Info *
273+
cifs_get_tcp_session(struct smb3_fs_context *ctx,
274+
struct TCP_Server_Info *primary_server);
274275
extern void cifs_put_tcp_session(struct TCP_Server_Info *server,
275276
int from_reconnect);
276277
extern void cifs_put_tcon(struct cifs_tcon *tcon);
@@ -607,7 +608,7 @@ int smb2_parse_query_directory(struct cifs_tcon *tcon, struct kvec *rsp_iov,
607608

608609
struct super_block *cifs_get_tcp_super(struct TCP_Server_Info *server);
609610
void cifs_put_tcp_super(struct super_block *sb);
610-
int update_super_prepath(struct cifs_tcon *tcon, char *prefix);
611+
int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix);
611612
char *extract_hostname(const char *unc);
612613
char *extract_sharename(const char *unc);
613614

@@ -634,4 +635,7 @@ static inline int cifs_create_options(struct cifs_sb_info *cifs_sb, int options)
634635
return options;
635636
}
636637

638+
struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon);
639+
void cifs_put_tcon_super(struct super_block *sb);
640+
637641
#endif /* _CIFSPROTO_H */

0 commit comments

Comments
 (0)