summaryrefslogtreecommitdiffstats
path: root/fs/cifs/smb2inode.c
diff options
context:
space:
mode:
authorSteve French <stfrench@microsoft.com>2018-04-26 05:19:09 +0200
committerSteve French <stfrench@microsoft.com>2018-05-28 00:56:35 +0200
commit3d4ef9a15343f038ccae17f60468569f23113312 (patch)
tree78a482f5ff0df0a41853800285f0df1a197851c1 /fs/cifs/smb2inode.c
parentLinux 4.17-rc7 (diff)
downloadlinux-3d4ef9a15343f038ccae17f60468569f23113312.tar.xz
linux-3d4ef9a15343f038ccae17f60468569f23113312.zip
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: Steve French <smfrench@gmail.com> Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
Diffstat (limited to 'fs/cifs/smb2inode.c')
-rw-r--r--fs/cifs/smb2inode.c43
1 files changed, 28 insertions, 15 deletions
diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c
index 1238cd3552f9..a6e786e39248 100644
--- a/fs/cifs/smb2inode.c
+++ b/fs/cifs/smb2inode.c
@@ -44,26 +44,38 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
__u32 create_options, void *data, int command)
{
int rc, tmprc = 0;
- __le16 *utf16_path;
+ __le16 *utf16_path = NULL;
__u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
struct cifs_open_parms oparms;
struct cifs_fid fid;
+ bool use_cached_root_handle = false;
- utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
- if (!utf16_path)
- return -ENOMEM;
+ if ((strcmp(full_path, "") == 0) && (create_options == 0) &&
+ (desired_access == FILE_READ_ATTRIBUTES) &&
+ (create_disposition == FILE_OPEN) &&
+ (tcon->nohandlecache == false)) {
+ rc = open_shroot(xid, tcon, &fid);
+ if (rc == 0)
+ use_cached_root_handle = true;
+ }
+
+ if (use_cached_root_handle == false) {
+ utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
+ if (!utf16_path)
+ return -ENOMEM;
- oparms.tcon = tcon;
- oparms.desired_access = desired_access;
- oparms.disposition = create_disposition;
- oparms.create_options = create_options;
- oparms.fid = &fid;
- oparms.reconnect = false;
+ oparms.tcon = tcon;
+ oparms.desired_access = desired_access;
+ oparms.disposition = create_disposition;
+ oparms.create_options = create_options;
+ oparms.fid = &fid;
+ oparms.reconnect = false;
- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
- if (rc) {
- kfree(utf16_path);
- return rc;
+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
+ if (rc) {
+ kfree(utf16_path);
+ return rc;
+ }
}
switch (command) {
@@ -107,7 +119,8 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
break;
}
- rc = SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
+ if (use_cached_root_handle == false)
+ rc = SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
if (tmprc)
rc = tmprc;
kfree(utf16_path);