Commit 3d4ef9a1 authored by Steve French's avatar Steve French
Browse files

smb3: fix redundant opens on root



In SMB2/SMB3 unlike in cifs we unnecessarily open the root of the share
over and over again in various places during mount and path revalidation
and also in statfs.  This patch cuts redundant traffic (opens and closes)
by simply keeping the directory handle for the root around (and reopening
it as needed on reconnect), so query calls don't require three round
trips to copmlete - just one, and eases load on network, client and
server (on mount alone, cuts network traffic by more than a third).

Also add a new cifs mount parm "nohandlecache" to allow users whose
servers might have resource constraints (eg in case they have a server
with so many users connecting to it that this extra handle per mount
could possibly be a resource concern).

Signed-off-by: default avatarSteve French <smfrench@gmail.com>
Reviewed-by: default avatarRonnie Sahlberg <lsahlber@redhat.com>
parent b04e2177
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@
					      * root mountable
					      */
#define CIFS_MOUNT_UID_FROM_ACL 0x2000000 /* try to get UID via special SID */
#define CIFS_MOUNT_NO_HANDLE_CACHE 0x4000000 /* disable caching dir handles */

struct cifs_sb_info {
	struct rb_root tlink_tree;
+2 −0
Original line number Diff line number Diff line
@@ -495,6 +495,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
		seq_puts(s, ",sfu");
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
		seq_puts(s, ",nobrl");
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_HANDLE_CACHE)
		seq_puts(s, ",nohandlecache");
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
		seq_puts(s, ",cifsacl");
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
+5 −0
Original line number Diff line number Diff line
@@ -525,6 +525,7 @@ struct smb_vol {
	bool nullauth:1;   /* attempt to authenticate with null user */
	bool nocase:1;     /* request case insensitive filenames */
	bool nobrl:1;      /* disable sending byte range locks to srv */
	bool nohandlecache:1; /* disable caching dir handles if srvr probs */
	bool mand_lock:1;  /* send mandatory not posix byte range lock reqs */
	bool seal:1;       /* request transport encryption on share */
	bool nodfs:1;      /* Do not request DFS, even if available */
@@ -953,6 +954,7 @@ struct cifs_tcon {
	bool print:1; /* set if connection to printer share */
	bool retry:1;
	bool nocase:1;
	bool nohandlecache:1; /* if strange server resource prob can turn off */
	bool seal:1;      /* transport encryption for this mounted share */
	bool unix_ext:1;  /* if false disable Linux extensions to CIFS protocol
				for this mount even if server would support */
@@ -979,6 +981,9 @@ struct cifs_tcon {
	struct fscache_cookie *fscache;	/* cookie for share */
#endif
	struct list_head pending_opens;	/* list of incomplete opens */
	bool valid_root_fid:1;	/* Do we have a useable root fid */
	struct mutex prfid_mutex; /* prevents reopen race after dead ses*/
	struct cifs_fid *prfid;	/* handle to the directory at top of share */
	/* BB add field for back pointer to sb struct(s)? */
};

+6 −0
Original line number Diff line number Diff line
@@ -106,6 +106,12 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
		open_file->oplock_break_cancelled = true;
	}
	spin_unlock(&tcon->open_file_lock);

	mutex_lock(&tcon->prfid_mutex);
	tcon->valid_root_fid = false;
	memset(tcon->prfid, 0, sizeof(struct cifs_fid));
	mutex_unlock(&tcon->prfid_mutex);

	/*
	 * BB Add call to invalidate_inodes(sb) for all superblocks mounted
	 * to this tcon.
+13 −0
Original line number Diff line number Diff line
@@ -79,6 +79,7 @@ enum {
	Opt_noposixpaths, Opt_nounix,
	Opt_nocase,
	Opt_brl, Opt_nobrl,
	Opt_handlecache, Opt_nohandlecache,
	Opt_forcemandatorylock, Opt_setuidfromacl, Opt_setuids,
	Opt_nosetuids, Opt_dynperm, Opt_nodynperm,
	Opt_nohard, Opt_nosoft,
@@ -148,6 +149,8 @@ static const match_table_t cifs_mount_option_tokens = {
	{ Opt_nocase, "ignorecase" },
	{ Opt_brl, "brl" },
	{ Opt_nobrl, "nobrl" },
	{ Opt_handlecache, "handlecache" },
	{ Opt_nohandlecache, "nohandlecache" },
	{ Opt_nobrl, "nolock" },
	{ Opt_forcemandatorylock, "forcemandatorylock" },
	{ Opt_forcemandatorylock, "forcemand" },
@@ -1445,6 +1448,12 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
				(S_IALLUGO & ~(S_ISUID | S_IXGRP)))
				vol->file_mode = S_IALLUGO;
			break;
		case Opt_nohandlecache:
			vol->nohandlecache = 1;
			break;
		case Opt_handlecache:
			vol->nohandlecache = 0;
			break;
		case Opt_forcemandatorylock:
			vol->mand_lock = 1;
			break;
@@ -3022,6 +3031,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
	 */
	tcon->retry = volume_info->retry;
	tcon->nocase = volume_info->nocase;
	tcon->nohandlecache = volume_info->nohandlecache;
	tcon->local_lease = volume_info->local_lease;
	INIT_LIST_HEAD(&tcon->pending_opens);

@@ -3580,6 +3590,8 @@ int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
	if (pvolume_info->nobrl)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
	if (pvolume_info->nohandlecache)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
	if (pvolume_info->nostrictsync)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
	if (pvolume_info->mand_lock)
@@ -4353,6 +4365,7 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
	vol_info->UNC = master_tcon->treeName;
	vol_info->retry = master_tcon->retry;
	vol_info->nocase = master_tcon->nocase;
	vol_info->nohandlecache = master_tcon->nohandlecache;
	vol_info->local_lease = master_tcon->local_lease;
	vol_info->no_linux_ext = !master_tcon->unix_ext;
	vol_info->sectype = master_tcon->ses->sectype;
Loading