Commit fd3a5940 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag '6.6-rc-smb3-client-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French:

 - six smb3 client fixes including ones to allow controlling smb3
   directory caching timeout and limits, and one debugging improvement

 - one fix for nls Kconfig (don't need to expose NLS_UCS2_UTILS option)

 - one minor spnego registry update

* tag '6.6-rc-smb3-client-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6:
  spnego: add missing OID to oid registry
  smb3: fix minor typo in SMB2_GLOBAL_CAP_LARGE_MTU
  cifs: update internal module version number for cifs.ko
  smb3: allow controlling maximum number of cached directories
  smb3: add trace point for queryfs (statfs)
  nls: Hide new NLS_UCS2_UTILS
  smb3: allow controlling length of time directory entries are cached with dir leases
  smb: propagate error code of extract_sharename()
parents a3c57ab7 5d153cd1
...@@ -618,11 +618,6 @@ config NLS_UTF8 ...@@ -618,11 +618,6 @@ config NLS_UTF8
the Unicode/ISO9646 universal character set. the Unicode/ISO9646 universal character set.
config NLS_UCS2_UTILS config NLS_UCS2_UTILS
tristate "NLS UCS-2 UTILS" tristate
help
Set of older UCS-2 conversion utilities and tables used by some
filesystems including SMB/CIFS. This includes upper case conversion
tables. This will automatically be selected when the filesystem
that uses it is selected.
endif # NLS endif # NLS
...@@ -18,7 +18,8 @@ static void smb2_close_cached_fid(struct kref *ref); ...@@ -18,7 +18,8 @@ static void smb2_close_cached_fid(struct kref *ref);
static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids, static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids,
const char *path, const char *path,
bool lookup_only) bool lookup_only,
__u32 max_cached_dirs)
{ {
struct cached_fid *cfid; struct cached_fid *cfid;
...@@ -43,7 +44,7 @@ static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids, ...@@ -43,7 +44,7 @@ static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids,
spin_unlock(&cfids->cfid_list_lock); spin_unlock(&cfids->cfid_list_lock);
return NULL; return NULL;
} }
if (cfids->num_entries >= MAX_CACHED_FIDS) { if (cfids->num_entries >= max_cached_dirs) {
spin_unlock(&cfids->cfid_list_lock); spin_unlock(&cfids->cfid_list_lock);
return NULL; return NULL;
} }
...@@ -145,7 +146,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon, ...@@ -145,7 +146,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
const char *npath; const char *npath;
if (tcon == NULL || tcon->cfids == NULL || tcon->nohandlecache || if (tcon == NULL || tcon->cfids == NULL || tcon->nohandlecache ||
is_smb1_server(tcon->ses->server)) is_smb1_server(tcon->ses->server) || (dir_cache_timeout == 0))
return -EOPNOTSUPP; return -EOPNOTSUPP;
ses = tcon->ses; ses = tcon->ses;
...@@ -162,7 +163,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon, ...@@ -162,7 +163,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
if (!utf16_path) if (!utf16_path)
return -ENOMEM; return -ENOMEM;
cfid = find_or_create_cached_dir(cfids, path, lookup_only); cfid = find_or_create_cached_dir(cfids, path, lookup_only, tcon->max_cached_dirs);
if (cfid == NULL) { if (cfid == NULL) {
kfree(utf16_path); kfree(utf16_path);
return -ENOENT; return -ENOENT;
...@@ -582,7 +583,7 @@ cifs_cfids_laundromat_thread(void *p) ...@@ -582,7 +583,7 @@ cifs_cfids_laundromat_thread(void *p)
return 0; return 0;
spin_lock(&cfids->cfid_list_lock); spin_lock(&cfids->cfid_list_lock);
list_for_each_entry_safe(cfid, q, &cfids->entries, entry) { list_for_each_entry_safe(cfid, q, &cfids->entries, entry) {
if (time_after(jiffies, cfid->time + HZ * 30)) { if (time_after(jiffies, cfid->time + HZ * dir_cache_timeout)) {
list_del(&cfid->entry); list_del(&cfid->entry);
list_add(&cfid->entry, &entry); list_add(&cfid->entry, &entry);
cfids->num_entries--; cfids->num_entries--;
......
...@@ -49,7 +49,7 @@ struct cached_fid { ...@@ -49,7 +49,7 @@ struct cached_fid {
struct cached_dirents dirents; struct cached_dirents dirents;
}; };
#define MAX_CACHED_FIDS 16 /* default MAX_CACHED_FIDS is 16 */
struct cached_fids { struct cached_fids {
/* Must be held when: /* Must be held when:
* - accessing the cfids->entries list * - accessing the cfids->entries list
......
...@@ -117,6 +117,10 @@ module_param(cifs_max_pending, uint, 0444); ...@@ -117,6 +117,10 @@ module_param(cifs_max_pending, uint, 0444);
MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server for " MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server for "
"CIFS/SMB1 dialect (N/A for SMB3) " "CIFS/SMB1 dialect (N/A for SMB3) "
"Default: 32767 Range: 2 to 32767."); "Default: 32767 Range: 2 to 32767.");
unsigned int dir_cache_timeout = 30;
module_param(dir_cache_timeout, uint, 0644);
MODULE_PARM_DESC(dir_cache_timeout, "Number of seconds to cache directory contents for which we have a lease. Default: 30 "
"Range: 1 to 65000 seconds, 0 to disable caching dir contents");
#ifdef CONFIG_CIFS_STATS2 #ifdef CONFIG_CIFS_STATS2
unsigned int slow_rsp_threshold = 1; unsigned int slow_rsp_threshold = 1;
module_param(slow_rsp_threshold, uint, 0644); module_param(slow_rsp_threshold, uint, 0644);
...@@ -695,6 +699,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root) ...@@ -695,6 +699,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
seq_printf(s, ",snapshot=%llu", tcon->snapshot_time); seq_printf(s, ",snapshot=%llu", tcon->snapshot_time);
if (tcon->handle_timeout) if (tcon->handle_timeout)
seq_printf(s, ",handletimeout=%u", tcon->handle_timeout); seq_printf(s, ",handletimeout=%u", tcon->handle_timeout);
if (tcon->max_cached_dirs != MAX_CACHED_FIDS)
seq_printf(s, ",max_cached_dirs=%u", tcon->max_cached_dirs);
/* /*
* Display file and directory attribute timeout in seconds. * Display file and directory attribute timeout in seconds.
...@@ -1679,6 +1685,12 @@ init_cifs(void) ...@@ -1679,6 +1685,12 @@ init_cifs(void)
CIFS_MAX_REQ); CIFS_MAX_REQ);
} }
/* Limit max to about 18 hours, and setting to zero disables directory entry caching */
if (dir_cache_timeout > 65000) {
dir_cache_timeout = 65000;
cifs_dbg(VFS, "dir_cache_timeout set to max of 65000 seconds\n");
}
cifsiod_wq = alloc_workqueue("cifsiod", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0); cifsiod_wq = alloc_workqueue("cifsiod", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
if (!cifsiod_wq) { if (!cifsiod_wq) {
rc = -ENOMEM; rc = -ENOMEM;
......
...@@ -152,6 +152,6 @@ extern const struct export_operations cifs_export_ops; ...@@ -152,6 +152,6 @@ extern const struct export_operations cifs_export_ops;
#endif /* CONFIG_CIFS_NFSD_EXPORT */ #endif /* CONFIG_CIFS_NFSD_EXPORT */
/* when changing internal version - update following two lines at same time */ /* when changing internal version - update following two lines at same time */
#define SMB3_PRODUCT_BUILD 44 #define SMB3_PRODUCT_BUILD 45
#define CIFS_VERSION "2.44" #define CIFS_VERSION "2.45"
#endif /* _CIFSFS_H */ #endif /* _CIFSFS_H */
...@@ -1210,6 +1210,7 @@ struct cifs_tcon { ...@@ -1210,6 +1210,7 @@ struct cifs_tcon {
__u32 max_chunks; __u32 max_chunks;
__u32 max_bytes_chunk; __u32 max_bytes_chunk;
__u32 max_bytes_copy; __u32 max_bytes_copy;
__u32 max_cached_dirs;
#ifdef CONFIG_CIFS_FSCACHE #ifdef CONFIG_CIFS_FSCACHE
u64 resource_id; /* server resource id */ u64 resource_id; /* server resource id */
struct fscache_volume *fscache; /* cookie for share */ struct fscache_volume *fscache; /* cookie for share */
...@@ -2016,6 +2017,7 @@ extern unsigned int CIFSMaxBufSize; /* max size not including hdr */ ...@@ -2016,6 +2017,7 @@ extern unsigned int CIFSMaxBufSize; /* max size not including hdr */
extern unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */ extern unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */
extern unsigned int cifs_min_small; /* min size of small buf pool */ extern unsigned int cifs_min_small; /* min size of small buf pool */
extern unsigned int cifs_max_pending; /* MAX requests at once to server*/ extern unsigned int cifs_max_pending; /* MAX requests at once to server*/
extern unsigned int dir_cache_timeout; /* max time for directory lease caching of dir */
extern bool disable_legacy_dialects; /* forbid vers=1.0 and vers=2.0 mounts */ extern bool disable_legacy_dialects; /* forbid vers=1.0 and vers=2.0 mounts */
extern atomic_t mid_count; extern atomic_t mid_count;
......
...@@ -2657,6 +2657,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx) ...@@ -2657,6 +2657,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
tcon->retry = ctx->retry; tcon->retry = ctx->retry;
tcon->nocase = ctx->nocase; tcon->nocase = ctx->nocase;
tcon->broken_sparse_sup = ctx->no_sparse; tcon->broken_sparse_sup = ctx->no_sparse;
tcon->max_cached_dirs = ctx->max_cached_dirs;
if (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING) if (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING)
tcon->nohandlecache = ctx->nohandlecache; tcon->nohandlecache = ctx->nohandlecache;
else else
......
...@@ -150,6 +150,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = { ...@@ -150,6 +150,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = {
fsparam_u32("closetimeo", Opt_closetimeo), fsparam_u32("closetimeo", Opt_closetimeo),
fsparam_u32("echo_interval", Opt_echo_interval), fsparam_u32("echo_interval", Opt_echo_interval),
fsparam_u32("max_credits", Opt_max_credits), fsparam_u32("max_credits", Opt_max_credits),
fsparam_u32("max_cached_dirs", Opt_max_cached_dirs),
fsparam_u32("handletimeout", Opt_handletimeout), fsparam_u32("handletimeout", Opt_handletimeout),
fsparam_u64("snapshot", Opt_snapshot), fsparam_u64("snapshot", Opt_snapshot),
fsparam_u32("max_channels", Opt_max_channels), fsparam_u32("max_channels", Opt_max_channels),
...@@ -1165,6 +1166,14 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, ...@@ -1165,6 +1166,14 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
if (result.uint_32 > 1) if (result.uint_32 > 1)
ctx->multichannel = true; ctx->multichannel = true;
break; break;
case Opt_max_cached_dirs:
if (result.uint_32 < 1) {
cifs_errorf(fc, "%s: Invalid max_cached_dirs, needs to be 1 or more\n",
__func__);
goto cifs_parse_mount_err;
}
ctx->max_cached_dirs = result.uint_32;
break;
case Opt_handletimeout: case Opt_handletimeout:
ctx->handle_timeout = result.uint_32; ctx->handle_timeout = result.uint_32;
if (ctx->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) { if (ctx->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
...@@ -1592,7 +1601,7 @@ int smb3_init_fs_context(struct fs_context *fc) ...@@ -1592,7 +1601,7 @@ int smb3_init_fs_context(struct fs_context *fc)
ctx->acregmax = CIFS_DEF_ACTIMEO; ctx->acregmax = CIFS_DEF_ACTIMEO;
ctx->acdirmax = CIFS_DEF_ACTIMEO; ctx->acdirmax = CIFS_DEF_ACTIMEO;
ctx->closetimeo = SMB3_DEF_DCLOSETIMEO; ctx->closetimeo = SMB3_DEF_DCLOSETIMEO;
ctx->max_cached_dirs = MAX_CACHED_FIDS;
/* Most clients set timeout to 0, allows server to use its default */ /* Most clients set timeout to 0, allows server to use its default */
ctx->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */ ctx->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */
......
...@@ -128,6 +128,7 @@ enum cifs_param { ...@@ -128,6 +128,7 @@ enum cifs_param {
Opt_closetimeo, Opt_closetimeo,
Opt_echo_interval, Opt_echo_interval,
Opt_max_credits, Opt_max_credits,
Opt_max_cached_dirs,
Opt_snapshot, Opt_snapshot,
Opt_max_channels, Opt_max_channels,
Opt_handletimeout, Opt_handletimeout,
...@@ -261,6 +262,7 @@ struct smb3_fs_context { ...@@ -261,6 +262,7 @@ struct smb3_fs_context {
__u32 handle_timeout; /* persistent and durable handle timeout in ms */ __u32 handle_timeout; /* persistent and durable handle timeout in ms */
unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */ unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */
unsigned int max_channels; unsigned int max_channels;
unsigned int max_cached_dirs;
__u16 compression; /* compression algorithm 0xFFFF default 0=disabled */ __u16 compression; /* compression algorithm 0xFFFF default 0=disabled */
bool rootfs:1; /* if it's a SMB root file system */ bool rootfs:1; /* if it's a SMB root file system */
bool witness:1; /* use witness protocol */ bool witness:1; /* use witness protocol */
...@@ -287,7 +289,7 @@ extern void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb); ...@@ -287,7 +289,7 @@ extern void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb);
*/ */
#define SMB3_MAX_DCLOSETIMEO (1 << 30) #define SMB3_MAX_DCLOSETIMEO (1 << 30)
#define SMB3_DEF_DCLOSETIMEO (1 * HZ) /* even 1 sec enough to help eg open/write/close/open/read */ #define SMB3_DEF_DCLOSETIMEO (1 * HZ) /* even 1 sec enough to help eg open/write/close/open/read */
#define MAX_CACHED_FIDS 16
extern char *cifs_sanitize_prepath(char *prepath, gfp_t gfp); extern char *cifs_sanitize_prepath(char *prepath, gfp_t gfp);
#endif #endif
...@@ -48,7 +48,7 @@ int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) ...@@ -48,7 +48,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)) {
cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__); cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__);
return -EINVAL; return PTR_ERR(sharename);
} }
slen = strlen(sharename); slen = strlen(sharename);
......
...@@ -2683,6 +2683,7 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -2683,6 +2683,7 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
smb2_copy_fs_info_to_kstatfs(info, buf); smb2_copy_fs_info_to_kstatfs(info, buf);
qfs_exit: qfs_exit:
trace_smb3_qfs_done(xid, tcon->tid, tcon->ses->Suid, tcon->tree_name, rc);
free_rsp_buf(buftype, rsp_iov.iov_base); free_rsp_buf(buftype, rsp_iov.iov_base);
return rc; return rc;
} }
......
...@@ -691,7 +691,7 @@ DEFINE_EVENT(smb3_tcon_class, smb3_##name, \ ...@@ -691,7 +691,7 @@ DEFINE_EVENT(smb3_tcon_class, smb3_##name, \
TP_ARGS(xid, tid, sesid, unc_name, rc)) TP_ARGS(xid, tid, sesid, unc_name, rc))
DEFINE_SMB3_TCON_EVENT(tcon); DEFINE_SMB3_TCON_EVENT(tcon);
DEFINE_SMB3_TCON_EVENT(qfs_done);
/* /*
* For smb2/smb3 open (including create and mkdir) calls * For smb2/smb3 open (including create and mkdir) calls
......
...@@ -406,7 +406,7 @@ struct smb2_tree_disconnect_rsp { ...@@ -406,7 +406,7 @@ struct smb2_tree_disconnect_rsp {
/* Capabilities flags */ /* Capabilities flags */
#define SMB2_GLOBAL_CAP_DFS 0x00000001 #define SMB2_GLOBAL_CAP_DFS 0x00000001
#define SMB2_GLOBAL_CAP_LEASING 0x00000002 /* Resp only New to SMB2.1 */ #define SMB2_GLOBAL_CAP_LEASING 0x00000002 /* Resp only New to SMB2.1 */
#define SMB2_GLOBAL_CAP_LARGE_MTU 0X00000004 /* Resp only New to SMB2.1 */ #define SMB2_GLOBAL_CAP_LARGE_MTU 0x00000004 /* Resp only New to SMB2.1 */
#define SMB2_GLOBAL_CAP_MULTI_CHANNEL 0x00000008 /* New to SMB3 */ #define SMB2_GLOBAL_CAP_MULTI_CHANNEL 0x00000008 /* New to SMB3 */
#define SMB2_GLOBAL_CAP_PERSISTENT_HANDLES 0x00000010 /* New to SMB3 */ #define SMB2_GLOBAL_CAP_PERSISTENT_HANDLES 0x00000010 /* New to SMB3 */
#define SMB2_GLOBAL_CAP_DIRECTORY_LEASING 0x00000020 /* New to SMB3 */ #define SMB2_GLOBAL_CAP_DIRECTORY_LEASING 0x00000020 /* New to SMB3 */
......
...@@ -67,6 +67,7 @@ enum OID { ...@@ -67,6 +67,7 @@ enum OID {
OID_msOutlookExpress, /* 1.3.6.1.4.1.311.16.4 */ OID_msOutlookExpress, /* 1.3.6.1.4.1.311.16.4 */
OID_ntlmssp, /* 1.3.6.1.4.1.311.2.2.10 */ OID_ntlmssp, /* 1.3.6.1.4.1.311.2.2.10 */
OID_negoex, /* 1.3.6.1.4.1.311.2.2.30 */
OID_spnego, /* 1.3.6.1.5.5.2 */ OID_spnego, /* 1.3.6.1.5.5.2 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment