Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cacf02df authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull cifs updates from Steve French:

 - four fixes for stable

 - improvements to DFS including allowing failover to alternate targets

 - some small performance improvements

* tag '4.21-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6: (39 commits)
  cifs: update internal module version number
  cifs: we can not use small padding iovs together with encryption
  cifs: Minor Kconfig clarification
  cifs: Always resolve hostname before reconnecting
  cifs: Add support for failover in cifs_reconnect_tcon()
  cifs: Add support for failover in smb2_reconnect()
  cifs: Only free DFS target list if we actually got one
  cifs: start DFS cache refresher in cifs_mount()
  cifs: Use GFP_ATOMIC when a lock is held in cifs_mount()
  cifs: Add support for failover in cifs_reconnect()
  cifs: Add support for failover in cifs_mount()
  cifs: remove set but not used variable 'sep'
  cifs: Make use of DFS cache to get new DFS referrals
  cifs: minor updates to documentation
  cifs: check kzalloc return
  cifs: remove set but not used variable 'server'
  cifs: Use kzfree() to free password
  cifs: Fix to use kmem_cache_free() instead of kfree()
  cifs: update for current_kernel_time64() removal
  cifs: Add DFS cache routines
  ...
parents 74673fc5 fea17080
Loading
Loading
Loading
Loading
+20 −6
Original line number Diff line number Diff line
Version 2.11 September 13, 2017
Version 2.14 December 21, 2018

A Partial List of Missing Features
==================================
@@ -7,7 +7,7 @@ Contributions are welcome. There are plenty of opportunities
for visible, important contributions to this module.  Here
is a partial list of the known problems and missing features:

a) SMB3 (and SMB3.02) missing optional features:
a) SMB3 (and SMB3.1.1) missing optional features:
   - multichannel (started), integration with RDMA
   - directory leases (improved metadata caching), started (root dir only)
   - T10 copy offload ie "ODX" (copy chunk, and "Duplicate Extents" ioctl
@@ -21,8 +21,9 @@ using Directory Leases, currently only the root file handle is cached longer
d) quota support (needs minor kernel change since quota calls
to make it to network filesystems or deviceless filesystems)

e) Compounding (in progress) to reduce number of roundtrips, and also
better optimize open to reduce redundant opens (using reference counts more).
e) Additional use cases where we use "compoounding" (e.g. open/query/close
and open/setinfo/close) to reduce the number of roundtrips, and also
open to reduce redundant opens (using deferred close and reference counts more).

f) Finish inotify support so kde and gnome file list windows
will autorefresh (partially complete by Asser). Needs minor kernel
@@ -43,11 +44,13 @@ exists. Also better integration with winbind for resolving SID owners

k) Add tools to take advantage of more smb3 specific ioctls and features
(passthrough ioctl/fsctl for sending various SMB3 fsctls to the server
is in progress)
is in progress, and a passthrough query_info call is already implemented
in cifs.ko to allow smb3 info levels queries to be sent from userspace)

l) encrypted file support

m) improved stats gathering, tools (perhaps integration with nfsometer?)
m) improved stats gathering tools (perhaps integration with nfsometer?)
to extend and make easier to use what is currently in /proc/fs/cifs/Stats

n) allow setting more NTFS/SMB3 file attributes remotely (currently limited to compressed
file attribute via chflags) and improve user space tools for managing and
@@ -76,6 +79,9 @@ and simplify the code.
v) POSIX Extensions for SMB3.1.1 (started, create and mkdir support added
so far).

w) Add support for additional strong encryption types, and additional spnego
authentication mechanisms (see MS-SMB2)

KNOWN BUGS
====================================
See http://bugzilla.samba.org - search on product "CifsVFS" for
@@ -102,3 +108,11 @@ and when signing is disabled to request larger read sizes (larger than
negotiated size) and send larger write sizes to modern servers.

4) More exhaustively test against less common servers

5) Continue to extend the smb3 "buildbot" which does automated xfstesting
against Windows, Samba and Azure currently - to add additional tests and
to allow the buildbot to execute the tests faster.

6) Address various coverity warnings (most are not bugs per-se, but
the more warnings are addressed, the easier it is to spot real
problems that static analyzers will point out in the future).
+3 −2
Original line number Diff line number Diff line
@@ -190,8 +190,9 @@ config CIFS_DFS_UPCALL
	    moves to a different server.  This feature also enables
	    an upcall mechanism for CIFS which contacts userspace helper
	    utilities to provide server name resolution (host names to
	    IP addresses) which is needed for implicit mounts of DFS junction
	    points. If unsure, say Y.
	    IP addresses) which is needed in order to reconnect to
	    servers if their addresses change or for implicit mounts of
	    DFS junction points. If unsure, say Y.

config CIFS_NFSD_EXPORT
	  bool "Allow nfsd to export CIFS file system"
+1 −1
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@ cifs-$(CONFIG_CIFS_ACL) += cifsacl.o

cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o

cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o
cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o dfs_cache.o

cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o

+12 −0
Original line number Diff line number Diff line
@@ -30,6 +30,9 @@
#include "cifsproto.h"
#include "cifs_debug.h"
#include "cifsfs.h"
#ifdef CONFIG_CIFS_DFS_UPCALL
#include "dfs_cache.h"
#endif
#ifdef CONFIG_CIFS_SMB_DIRECT
#include "smbdirect.h"
#endif
@@ -629,6 +632,11 @@ cifs_proc_init(void)
		    &cifs_security_flags_proc_fops);
	proc_create("LookupCacheEnabled", 0644, proc_fs_cifs,
		    &cifs_lookup_cache_proc_fops);

#ifdef CONFIG_CIFS_DFS_UPCALL
	proc_create("dfscache", 0644, proc_fs_cifs, &dfscache_proc_fops);
#endif

#ifdef CONFIG_CIFS_SMB_DIRECT
	proc_create("rdma_readwrite_threshold", 0644, proc_fs_cifs,
		&cifs_rdma_readwrite_threshold_proc_fops);
@@ -663,6 +671,10 @@ 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);

#ifdef CONFIG_CIFS_DFS_UPCALL
	remove_proc_entry("dfscache", proc_fs_cifs);
#endif
#ifdef CONFIG_CIFS_SMB_DIRECT
	remove_proc_entry("rdma_readwrite_threshold", proc_fs_cifs);
	remove_proc_entry("smbd_max_frmr_depth", proc_fs_cifs);
+86 −52
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include "dns_resolve.h"
#include "cifs_debug.h"
#include "cifs_unicode.h"
#include "dfs_cache.h"

static LIST_HEAD(cifs_dfs_automount_list);

@@ -126,7 +127,7 @@ cifs_build_devname(char *nodename, const char *prepath)
 * @sb_mountdata:	parent/root DFS mount options (template)
 * @fullpath:		full path in UNC format
 * @ref:		server's referral
 * @devname:		pointer for saving device name
 * @devname:		optional pointer for saving device name
 *
 * creates mount options for submount based on template options sb_mountdata
 * and replacing unc,ip,prefixpath options with ones we've got form ref_unc.
@@ -140,6 +141,7 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
				   char **devname)
{
	int rc;
	char *name;
	char *mountdata = NULL;
	const char *prepath = NULL;
	int md_len;
@@ -158,17 +160,17 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
			prepath++;
	}

	*devname = cifs_build_devname(ref->node_name, prepath);
	if (IS_ERR(*devname)) {
		rc = PTR_ERR(*devname);
		*devname = NULL;
	name = cifs_build_devname(ref->node_name, prepath);
	if (IS_ERR(name)) {
		rc = PTR_ERR(name);
		name = NULL;
		goto compose_mount_options_err;
	}

	rc = dns_resolve_server_name_to_ip(*devname, &srvIP);
	rc = dns_resolve_server_name_to_ip(name, &srvIP);
	if (rc < 0) {
		cifs_dbg(FYI, "%s: Failed to resolve server part of %s to IP: %d\n",
			 __func__, *devname, rc);
			 __func__, name, rc);
		goto compose_mount_options_err;
	}

@@ -224,6 +226,9 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
	strcat(mountdata, "ip=");
	strcat(mountdata, srvIP);

	if (devname)
		*devname = name;

	/*cifs_dbg(FYI, "%s: parent mountdata: %s\n", __func__, sb_mountdata);*/
	/*cifs_dbg(FYI, "%s: submount mountdata: %s\n", __func__, mountdata );*/

@@ -234,8 +239,7 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
compose_mount_options_err:
	kfree(mountdata);
	mountdata = ERR_PTR(rc);
	kfree(*devname);
	*devname = NULL;
	kfree(name);
	goto compose_mount_options_out;
}

@@ -251,20 +255,30 @@ static struct vfsmount *cifs_dfs_do_refmount(struct dentry *mntpt,
{
	struct vfsmount *mnt;
	char *mountdata;
	char *devname = NULL;
	char *devname;

	/*
	 * Always pass down the DFS full path to smb3_do_mount() so we
	 * can use it later for failover.
	 */
	devname = kstrndup(fullpath, strlen(fullpath), GFP_KERNEL);
	if (!devname)
		return ERR_PTR(-ENOMEM);

	convert_delimiter(devname, '/');

	/* strip first '\' from fullpath */
	mountdata = cifs_compose_mount_options(cifs_sb->mountdata,
			fullpath + 1, ref, &devname);

	if (IS_ERR(mountdata))
					       fullpath + 1, ref, NULL);
	if (IS_ERR(mountdata)) {
		kfree(devname);
		return (struct vfsmount *)mountdata;
	}

	mnt = vfs_submount(mntpt, &cifs_fs_type, devname, mountdata);
	kfree(mountdata);
	kfree(devname);
	return mnt;

}

static void dump_referral(const struct dfs_info3_param *ref)
@@ -282,16 +296,15 @@ static void dump_referral(const struct dfs_info3_param *ref)
 */
static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
{
	struct dfs_info3_param *referrals = NULL;
	unsigned int num_referrals = 0;
	struct dfs_info3_param referral = {0};
	struct cifs_sb_info *cifs_sb;
	struct cifs_ses *ses;
	char *full_path;
	struct cifs_tcon *tcon;
	char *full_path, *root_path;
	unsigned int xid;
	int i;
	int len;
	int rc;
	struct vfsmount *mnt;
	struct tcon_link *tlink;

	cifs_dbg(FYI, "in %s\n", __func__);
	BUG_ON(IS_ROOT(mntpt));
@@ -315,48 +328,69 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
	if (full_path == NULL)
		goto cdda_exit;

	tlink = cifs_sb_tlink(cifs_sb);
	if (IS_ERR(tlink)) {
		mnt = ERR_CAST(tlink);
	cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);

	if (!cifs_sb_master_tlink(cifs_sb)) {
		cifs_dbg(FYI, "%s: master tlink is NULL\n", __func__);
		goto free_full_path;
	}

	tcon = cifs_sb_master_tcon(cifs_sb);
	if (!tcon) {
		cifs_dbg(FYI, "%s: master tcon is NULL\n", __func__);
		goto free_full_path;
	}

	root_path = kstrdup(tcon->treeName, GFP_KERNEL);
	if (!root_path) {
		mnt = ERR_PTR(-ENOMEM);
		goto free_full_path;
	}
	ses = tlink_tcon(tlink)->ses;
	cifs_dbg(FYI, "%s: root path: %s\n", __func__, root_path);

	ses = tcon->ses;
	xid = get_xid();
	rc = get_dfs_path(xid, ses, full_path + 1, cifs_sb->local_nls,
		&num_referrals, &referrals,
		cifs_remap(cifs_sb));

	/*
	 * If DFS root has been expired, then unconditionally fetch it again to
	 * refresh DFS referral cache.
	 */
	rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
			    root_path + 1, NULL, NULL);
	if (!rc) {
		rc = dfs_cache_find(xid, ses, cifs_sb->local_nls,
				    cifs_remap(cifs_sb), full_path + 1,
				    &referral, NULL);
	}

	free_xid(xid);

	cifs_put_tlink(tlink);
	if (rc) {
		mnt = ERR_PTR(rc);
		goto free_root_path;
	}

	mnt = ERR_PTR(-ENOENT);
	for (i = 0; i < num_referrals; i++) {
		int len;
		dump_referral(referrals + i);
		/* connect to a node */
		len = strlen(referrals[i].node_name);
	dump_referral(&referral);

	len = strlen(referral.node_name);
	if (len < 2) {
		cifs_dbg(VFS, "%s: Net Address path too short: %s\n",
				 __func__, referrals[i].node_name);
			 __func__, referral.node_name);
		mnt = ERR_PTR(-EINVAL);
			break;
		goto free_dfs_ref;
	}
		mnt = cifs_dfs_do_refmount(mntpt, cifs_sb,
				full_path, referrals + i);
		cifs_dbg(FYI, "%s: cifs_dfs_do_refmount:%s , mnt:%p\n",
			 __func__, referrals[i].node_name, mnt);
		if (!IS_ERR(mnt))
			goto success;
	}

	/* no valid submounts were found; return error from get_dfs_path() by
	 * preference */
	if (rc != 0)
		mnt = ERR_PTR(rc);

success:
	free_dfs_info_array(referrals, num_referrals);
	/*
	 * cifs_mount() will retry every available node server in case
	 * of failures.
	 */
	mnt = cifs_dfs_do_refmount(mntpt, cifs_sb, full_path, &referral);
	cifs_dbg(FYI, "%s: cifs_dfs_do_refmount:%s , mnt:%p\n", __func__,
		 referral.node_name, mnt);

free_dfs_ref:
	free_dfs_info_param(&referral);
free_root_path:
	kfree(root_path);
free_full_path:
	kfree(full_path);
cdda_exit:
Loading