Commit 2a19866b authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag '5.12-rc-smb3-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs updates from Steve French:

 - improvements to root directory metadata caching

 - addition of new "rasize" mount parameter which can significantly
   increase read ahead performance (e.g. copy can be much faster,
   especially with multichannel)

 - addition of support for insert and collapse range

 - improvements to error handling in mount

* tag '5.12-rc-smb3-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6: (40 commits)
  cifs: update internal version number
  smb3: add rasize mount parameter to improve readahead performance
  smb3: limit noisy error
  cifs: fix leak in cifs_smb3_do_mount() ctx
  cifs: remove unnecessary copies of tcon->crfid.fid
  cifs: Return correct error code from smb2_get_enc_key
  cifs: fix out-of-bound memory access when calling smb3_notify() at mount point
  smb2: fix use-after-free in smb2_ioctl_query_info()
  cifs: export supported mount options via new mount_params /proc file
  cifs: log mount errors using cifs_errorf()
  cifs: add fs_context param to parsing helpers
  cifs: make fs_context error logging wrapper
  cifs: add FALLOC_FL_INSERT_RANGE support
  cifs: add support for FALLOC_FL_COLLAPSE_RANGE
  cifs: check the timestamp for the cached dirent when deciding on revalidate
  cifs: pass the dentry instead of the inode down to the revalidation check functions
  cifs: add a timestamp to track when the lease of the cached dir was taken
  cifs: add a function to get a cached dir based on its dentry
  cifs: Grab a reference for the dentry of the cached directory during the lifetime of the cache
  cifs: store a pointer to the root dentry in cifs_sb_info once we have completed mounting the share
  ...
parents c065c429 a8a6082d
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -714,6 +714,7 @@ DebugData Displays information about active CIFS sessions and
			version.
Stats			Lists summary resource usage information as well as per
			share statistics.
open_files		List all the open file handles on all active SMB sessions.
======================= =======================================================

Configuration pseudo-files:
@@ -794,6 +795,8 @@ LinuxExtensionsEnabled If set to one then the client will attempt to
			support and want to map the uid and gid fields
			to values supplied at mount (rather than the
			actual values, then set this to zero. (default 1)
dfscache		List the content of the DFS cache.
			If set to 0, the client will clear the cache.
======================= =======================================================

These experimental features and tracing can be enabled by changing flags in
+51 −7
Original line number Diff line number Diff line
@@ -17,15 +17,14 @@
#include "cifsproto.h"
#include "cifs_debug.h"
#include "cifsfs.h"
#include "fs_context.h"
#ifdef CONFIG_CIFS_DFS_UPCALL
#include "dfs_cache.h"
#endif
#ifdef CONFIG_CIFS_SMB_DIRECT
#include "smbdirect.h"
#endif
#ifdef CONFIG_CIFS_SWN_UPCALL
#include "cifs_swn.h"
#endif

void
cifs_dump_mem(char *label, void *data, int length)
@@ -118,10 +117,8 @@ static void cifs_debug_tcon(struct seq_file *m, struct cifs_tcon *tcon)
		seq_printf(m, " POSIX Extensions");
	if (tcon->ses->server->ops->dump_share_caps)
		tcon->ses->server->ops->dump_share_caps(m, tcon);
#ifdef CONFIG_CIFS_SWN_UPCALL
	if (tcon->use_witness)
		seq_puts(m, " Witness");
#endif

	if (tcon->need_reconnect)
		seq_puts(m, "\tDISCONNECTED ");
@@ -490,10 +487,8 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)

	spin_unlock(&cifs_tcp_ses_lock);
	seq_putc(m, '\n');

#ifdef CONFIG_CIFS_SWN_UPCALL
	cifs_swn_dump(m);
#endif

	/* BB add code to dump additional info such as TCP session info now */
	return 0;
}
@@ -702,6 +697,7 @@ static const struct proc_ops cifs_lookup_cache_proc_ops;
static const struct proc_ops traceSMB_proc_ops;
static const struct proc_ops cifs_security_flags_proc_ops;
static const struct proc_ops cifs_linux_ext_proc_ops;
static const struct proc_ops cifs_mount_params_proc_ops;

void
cifs_proc_init(void)
@@ -726,6 +722,8 @@ cifs_proc_init(void)
	proc_create("LookupCacheEnabled", 0644, proc_fs_cifs,
		    &cifs_lookup_cache_proc_ops);

	proc_create("mount_params", 0444, proc_fs_cifs, &cifs_mount_params_proc_ops);

#ifdef CONFIG_CIFS_DFS_UPCALL
	proc_create("dfscache", 0644, proc_fs_cifs, &dfscache_proc_ops);
#endif
@@ -764,6 +762,7 @@ cifs_proc_clean(void)
	remove_proc_entry("SecurityFlags", proc_fs_cifs);
	remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs);
	remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);
	remove_proc_entry("mount_params", proc_fs_cifs);

#ifdef CONFIG_CIFS_DFS_UPCALL
	remove_proc_entry("dfscache", proc_fs_cifs);
@@ -1023,6 +1022,51 @@ static const struct proc_ops cifs_security_flags_proc_ops = {
	.proc_release	= single_release,
	.proc_write	= cifs_security_flags_proc_write,
};

/* To make it easier to debug, can help to show mount params */
static int cifs_mount_params_proc_show(struct seq_file *m, void *v)
{
	const struct fs_parameter_spec *p;
	const char *type;

	for (p = smb3_fs_parameters; p->name; p++) {
		/* cannot use switch with pointers... */
		if (!p->type) {
			if (p->flags == fs_param_neg_with_no)
				type = "noflag";
			else
				type = "flag";
		} else if (p->type == fs_param_is_bool)
			type = "bool";
		else if (p->type == fs_param_is_u32)
			type = "u32";
		else if (p->type == fs_param_is_u64)
			type = "u64";
		else if (p->type == fs_param_is_string)
			type = "string";
		else
			type = "unknown";

		seq_printf(m, "%s:%s\n", p->name, type);
	}

	return 0;
}

static int cifs_mount_params_proc_open(struct inode *inode, struct file *file)
{
	return single_open(file, cifs_mount_params_proc_show, NULL);
}

static const struct proc_ops cifs_mount_params_proc_ops = {
	.proc_open	= cifs_mount_params_proc_open,
	.proc_read	= seq_read,
	.proc_lseek	= seq_lseek,
	.proc_release	= single_release,
	/* No need for write for now */
	/* .proc_write	= cifs_mount_params_proc_write, */
};

#else
inline void cifs_proc_init(void)
{
+9 −5
Original line number Diff line number Diff line
@@ -270,7 +270,7 @@ static struct vfsmount *cifs_dfs_do_mount(struct dentry *mntpt,
	char *mountdata;
	char *devname;

	devname = kstrndup(fullpath, strlen(fullpath), GFP_KERNEL);
	devname = kstrdup(fullpath, GFP_KERNEL);
	if (!devname)
		return ERR_PTR(-ENOMEM);

@@ -302,6 +302,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
	struct cifs_sb_info *cifs_sb;
	struct cifs_ses *ses;
	struct cifs_tcon *tcon;
	void *page;
	char *full_path, *root_path;
	unsigned int xid;
	int rc;
@@ -324,10 +325,13 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
		goto cdda_exit;
	}

	page = alloc_dentry_path();
	/* always use tree name prefix */
	full_path = build_path_from_dentry_optional_prefix(mntpt, true);
	if (full_path == NULL)
		goto cdda_exit;
	full_path = build_path_from_dentry_optional_prefix(mntpt, page, true);
	if (IS_ERR(full_path)) {
		mnt = ERR_CAST(full_path);
		goto free_full_path;
	}

	convert_delimiter(full_path, '\\');

@@ -385,7 +389,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
free_root_path:
	kfree(root_path);
free_full_path:
	kfree(full_path);
	free_dentry_path(page);
cdda_exit:
	cifs_dbg(FYI, "leaving %s\n" , __func__);
	return mnt;
+4 −0
Original line number Diff line number Diff line
@@ -81,5 +81,9 @@ struct cifs_sb_info {
	 * (cifs_autodisable_serverino) in order to match new mounts.
	 */
	bool mnt_cifs_serverino_autodisabled;
	/*
	 * Available once the mount has completed.
	 */
	struct dentry *root;
};
#endif				/* _CIFS_FS_SB_H */
+27 −0
Original line number Diff line number Diff line
@@ -7,11 +7,13 @@

#ifndef _CIFS_SWN_H
#define _CIFS_SWN_H
#include "cifsglob.h"

struct cifs_tcon;
struct sk_buff;
struct genl_info;

#ifdef CONFIG_CIFS_SWN_UPCALL
extern int cifs_swn_register(struct cifs_tcon *tcon);

extern int cifs_swn_unregister(struct cifs_tcon *tcon);
@@ -22,4 +24,29 @@ extern void cifs_swn_dump(struct seq_file *m);

extern void cifs_swn_check(void);

static inline bool cifs_swn_set_server_dstaddr(struct TCP_Server_Info *server)
{
	if (server->use_swn_dstaddr) {
		server->dstaddr = server->swn_dstaddr;
		return true;
	}
	return false;
}

static inline void cifs_swn_reset_server_dstaddr(struct TCP_Server_Info *server)
{
	server->use_swn_dstaddr = false;
}

#else

static inline int cifs_swn_register(struct cifs_tcon *tcon) { return 0; }
static inline int cifs_swn_unregister(struct cifs_tcon *tcon) { return 0; }
static inline int cifs_swn_notify(struct sk_buff *s, struct genl_info *i) { return 0; }
static inline void cifs_swn_dump(struct seq_file *m) {}
static inline void cifs_swn_check(void) {}
static inline bool cifs_swn_set_server_dstaddr(struct TCP_Server_Info *server) { return false; }
static inline void cifs_swn_reset_server_dstaddr(struct TCP_Server_Info *server) {}

#endif /* CONFIG_CIFS_SWN_UPCALL */
#endif /* _CIFS_SWN_H */
Loading