OSDN Git Service

Merge tag '6.6-rc-smb3-client-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 10 Sep 2023 02:56:23 +0000 (19:56 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 10 Sep 2023 02:56:23 +0000 (19:56 -0700)
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()

14 files changed:
fs/nls/Kconfig
fs/smb/client/cached_dir.c
fs/smb/client/cached_dir.h
fs/smb/client/cifsfs.c
fs/smb/client/cifsfs.h
fs/smb/client/cifsglob.h
fs/smb/client/connect.c
fs/smb/client/fs_context.c
fs/smb/client/fs_context.h
fs/smb/client/fscache.c
fs/smb/client/smb2ops.c
fs/smb/client/trace.h
fs/smb/common/smb2pdu.h
include/linux/oid_registry.h

index a0d0e2f..2a601af 100644 (file)
@@ -618,11 +618,6 @@ config NLS_UTF8
          the Unicode/ISO9646 universal character set.
 
 config NLS_UCS2_UTILS
-       tristate "NLS UCS-2 UTILS"
-       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.
+       tristate
 
 endif # NLS
index 2d5e9a9..b17f067 100644 (file)
@@ -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,
                                                    const char *path,
-                                                   bool lookup_only)
+                                                   bool lookup_only,
+                                                   __u32 max_cached_dirs)
 {
        struct cached_fid *cfid;
 
@@ -43,7 +44,7 @@ static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids,
                spin_unlock(&cfids->cfid_list_lock);
                return NULL;
        }
-       if (cfids->num_entries >= MAX_CACHED_FIDS) {
+       if (cfids->num_entries >= max_cached_dirs) {
                spin_unlock(&cfids->cfid_list_lock);
                return NULL;
        }
@@ -145,7 +146,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
        const char *npath;
 
        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;
 
        ses = tcon->ses;
@@ -162,7 +163,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
        if (!utf16_path)
                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) {
                kfree(utf16_path);
                return -ENOENT;
@@ -582,7 +583,7 @@ cifs_cfids_laundromat_thread(void *p)
                        return 0;
                spin_lock(&cfids->cfid_list_lock);
                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_add(&cfid->entry, &entry);
                                cfids->num_entries--;
index facc9b1..a82ff2c 100644 (file)
@@ -49,7 +49,7 @@ struct cached_fid {
        struct cached_dirents dirents;
 };
 
-#define MAX_CACHED_FIDS 16
+/* default MAX_CACHED_FIDS is 16 */
 struct cached_fids {
        /* Must be held when:
         * - accessing the cfids->entries list
index 73c44e0..22869cd 100644 (file)
@@ -117,6 +117,10 @@ module_param(cifs_max_pending, uint, 0444);
 MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server for "
                                   "CIFS/SMB1 dialect (N/A for SMB3) "
                                   "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
 unsigned int slow_rsp_threshold = 1;
 module_param(slow_rsp_threshold, uint, 0644);
@@ -695,6 +699,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
                seq_printf(s, ",snapshot=%llu", tcon->snapshot_time);
        if (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.
@@ -1679,6 +1685,12 @@ init_cifs(void)
                         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);
        if (!cifsiod_wq) {
                rc = -ENOMEM;
index 532c38f..41daebd 100644 (file)
@@ -152,6 +152,6 @@ extern const struct export_operations cifs_export_ops;
 #endif /* CONFIG_CIFS_NFSD_EXPORT */
 
 /* when changing internal version - update following two lines at same time */
-#define SMB3_PRODUCT_BUILD 44
-#define CIFS_VERSION   "2.44"
+#define SMB3_PRODUCT_BUILD 45
+#define CIFS_VERSION   "2.45"
 #endif                         /* _CIFSFS_H */
index 259e231..032d871 100644 (file)
@@ -1210,6 +1210,7 @@ struct cifs_tcon {
        __u32 max_chunks;
        __u32 max_bytes_chunk;
        __u32 max_bytes_copy;
+       __u32 max_cached_dirs;
 #ifdef CONFIG_CIFS_FSCACHE
        u64 resource_id;                /* server resource id */
        struct fscache_volume *fscache; /* cookie for share */
@@ -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_small;  /* min size of small buf pool */
 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 atomic_t mid_count;
 
index 3bd71f9..6877547 100644 (file)
@@ -2657,6 +2657,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
        tcon->retry = ctx->retry;
        tcon->nocase = ctx->nocase;
        tcon->broken_sparse_sup = ctx->no_sparse;
+       tcon->max_cached_dirs = ctx->max_cached_dirs;
        if (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING)
                tcon->nohandlecache = ctx->nohandlecache;
        else
index 67e16c2..e45ce31 100644 (file)
@@ -150,6 +150,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = {
        fsparam_u32("closetimeo", Opt_closetimeo),
        fsparam_u32("echo_interval", Opt_echo_interval),
        fsparam_u32("max_credits", Opt_max_credits),
+       fsparam_u32("max_cached_dirs", Opt_max_cached_dirs),
        fsparam_u32("handletimeout", Opt_handletimeout),
        fsparam_u64("snapshot", Opt_snapshot),
        fsparam_u32("max_channels", Opt_max_channels),
@@ -1165,6 +1166,14 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
                if (result.uint_32 > 1)
                        ctx->multichannel = true;
                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:
                ctx->handle_timeout = result.uint_32;
                if (ctx->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
@@ -1592,7 +1601,7 @@ int smb3_init_fs_context(struct fs_context *fc)
        ctx->acregmax = CIFS_DEF_ACTIMEO;
        ctx->acdirmax = CIFS_DEF_ACTIMEO;
        ctx->closetimeo = SMB3_DEF_DCLOSETIMEO;
-
+       ctx->max_cached_dirs = MAX_CACHED_FIDS;
        /* 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 */
 
index f4eaf85..9d8d34a 100644 (file)
@@ -128,6 +128,7 @@ enum cifs_param {
        Opt_closetimeo,
        Opt_echo_interval,
        Opt_max_credits,
+       Opt_max_cached_dirs,
        Opt_snapshot,
        Opt_max_channels,
        Opt_handletimeout,
@@ -261,6 +262,7 @@ struct smb3_fs_context {
        __u32 handle_timeout; /* persistent and durable handle timeout in ms */
        unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */
        unsigned int max_channels;
+       unsigned int max_cached_dirs;
        __u16 compression; /* compression algorithm 0xFFFF default 0=disabled */
        bool rootfs:1; /* if it's a SMB root file system */
        bool witness:1; /* use witness protocol */
@@ -287,7 +289,7 @@ extern void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb);
  */
 #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 MAX_CACHED_FIDS 16
 extern char *cifs_sanitize_prepath(char *prepath, gfp_t gfp);
 
 #endif
index 3677525..e5cad14 100644 (file)
@@ -48,7 +48,7 @@ int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
        sharename = extract_sharename(tcon->tree_name);
        if (IS_ERR(sharename)) {
                cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__);
-               return -EINVAL;
+               return PTR_ERR(sharename);
        }
 
        slen = strlen(sharename);
index e3dd698..d9eda2e 100644 (file)
@@ -2683,6 +2683,7 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
                smb2_copy_fs_info_to_kstatfs(info, buf);
 
 qfs_exit:
+       trace_smb3_qfs_done(xid, tcon->tid, tcon->ses->Suid, tcon->tree_name, rc);
        free_rsp_buf(buftype, rsp_iov.iov_base);
        return rc;
 }
index e671bd1..a7e4755 100644 (file)
@@ -691,7 +691,7 @@ DEFINE_EVENT(smb3_tcon_class, smb3_##name,    \
        TP_ARGS(xid, tid, sesid, unc_name, rc))
 
 DEFINE_SMB3_TCON_EVENT(tcon);
-
+DEFINE_SMB3_TCON_EVENT(qfs_done);
 
 /*
  * For smb2/smb3 open (including create and mkdir) calls
index 2680251..319fb9f 100644 (file)
@@ -406,7 +406,7 @@ struct smb2_tree_disconnect_rsp {
 /* Capabilities flags */
 #define SMB2_GLOBAL_CAP_DFS            0x00000001
 #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_PERSISTENT_HANDLES 0x00000010 /* New to SMB3 */
 #define SMB2_GLOBAL_CAP_DIRECTORY_LEASING  0x00000020 /* New to SMB3 */
index 0f4a890..f86a08b 100644 (file)
@@ -67,6 +67,7 @@ enum OID {
        OID_msOutlookExpress,           /* 1.3.6.1.4.1.311.16.4 */
 
        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 */