[RFC,SMB3] Add cache=singleclient mount option to allow shares accessed by only client to be more aggressively cached
diff mbox series

Message ID CAH2r5msYxvoFhG0mrxH4UfirwEhH8Y8pWJRrd8pVwUiKZBucNg@mail.gmail.com
State New
Headers show
Series
  • [RFC,SMB3] Add cache=singleclient mount option to allow shares accessed by only client to be more aggressively cached
Related show

Commit Message

Steve French Aug. 30, 2019, 7:20 a.m. UTC
Similar to the "cache=ro" patch but for the read write case ...

    smb3: add mount option to allow RW caching of share accessed by
only 1 client

    If a share is known to be only to be accessed by one client, we
    can aggressively cache writes not just reads to it.

    Add "cache=" option (cache=singleclient) for mounting read write shares
    (that will not be read or written to from other clients while we have
    it mounted) in order to improve performance.

Patch
diff mbox series

From b9b3b6a86c3c6d34a89201e45837435af5e66441 Mon Sep 17 00:00:00 2001
From: Steve French <stfrench@microsoft.com>
Date: Fri, 30 Aug 2019 02:12:41 -0500
Subject: [PATCH] smb3: add mount option to allow RW caching of share accessed
 by only 1 client

If a share is known to be only to be accessed by one client, we
can aggressively cache writes not just reads to it.

Add "cache=" option (cache=singleclient) for mounting read write shares
(that will not be read or written to from other clients while we have
it mounted) in order to improve performance.

Signed-off-by: Steve French <stfrench@microsoft.com>
---
 fs/cifs/cifs_fs_sb.h |  1 +
 fs/cifs/cifsfs.c     |  2 ++
 fs/cifs/cifsglob.h   |  5 +++--
 fs/cifs/connect.c    | 20 +++++++++++++++++++-
 4 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index 286a104c4761..6e7c4427369d 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -54,6 +54,7 @@ 
 #define CIFS_MOUNT_NO_DFS 0x8000000 /* disable DFS resolving */
 #define CIFS_MOUNT_MODE_FROM_SID 0x10000000 /* retrieve mode from special ACE */
 #define CIFS_MOUNT_RO_CACHE	0x20000000  /* assumes share will not change */
+#define CIFS_MOUNT_RW_CACHE	0x40000000  /* assumes only client accessing */
 
 struct cifs_sb_info {
 	struct rb_root tlink_tree;
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 970251bc0661..de90e665ef11 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -400,6 +400,8 @@  cifs_show_cache_flavor(struct seq_file *s, struct cifs_sb_info *cifs_sb)
 		seq_puts(s, "strict");
 	else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
 		seq_puts(s, "none");
+	else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE)
+		seq_puts(s, "singleclient"); /* assume only one client access */
 	else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE)
 		seq_puts(s, "ro"); /* read only caching assumed */
 	else
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 3f12da7f2f7f..fa5abe3a8514 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -560,6 +560,7 @@  struct smb_vol {
 	bool direct_io:1;
 	bool strict_io:1; /* strict cache behavior */
 	bool cache_ro:1;
+	bool cache_rw:1;
 	bool remap:1;      /* set to remap seven reserved chars in filenames */
 	bool sfu_remap:1;  /* remap seven reserved chars ala SFU */
 	bool posix_paths:1; /* unset to not ask for posix pathnames. */
@@ -622,7 +623,7 @@  struct smb_vol {
 			 CIFS_MOUNT_CIFS_BACKUPUID | CIFS_MOUNT_CIFS_BACKUPGID | \
 			 CIFS_MOUNT_UID_FROM_ACL | CIFS_MOUNT_NO_HANDLE_CACHE | \
 			 CIFS_MOUNT_NO_DFS | CIFS_MOUNT_MODE_FROM_SID | \
-			 CIFS_MOUNT_RO_CACHE)
+			 CIFS_MOUNT_RO_CACHE | CIFS_MOUNT_RW_CACHE)
 
 /**
  * Generic VFS superblock mount flags (s_flags) to consider when
@@ -1370,7 +1371,7 @@  void cifsFileInfo_put(struct cifsFileInfo *cifs_file);
 
 #define CIFS_CACHE_READ(cinode) ((cinode->oplock & CIFS_CACHE_READ_FLG) || (CIFS_SB(cinode->vfs_inode.i_sb)->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE))
 #define CIFS_CACHE_HANDLE(cinode) (cinode->oplock & CIFS_CACHE_HANDLE_FLG)
-#define CIFS_CACHE_WRITE(cinode) (cinode->oplock & CIFS_CACHE_WRITE_FLG)
+#define CIFS_CACHE_WRITE(cinode) ((cinode->oplock & CIFS_CACHE_WRITE_FLG) || (CIFS_SB(cinode->vfs_inode.i_sb)->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE))
 
 /*
  * One of these for each file inode
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 072c01f4e9c1..d9a995588c74 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -299,6 +299,7 @@  enum {
 	Opt_cache_strict,
 	Opt_cache_none,
 	Opt_cache_ro,
+	Opt_cache_rw,
 	Opt_cache_err
 };
 
@@ -307,6 +308,7 @@  static const match_table_t cifs_cacheflavor_tokens = {
 	{ Opt_cache_strict, "strict" },
 	{ Opt_cache_none, "none" },
 	{ Opt_cache_ro, "ro" },
+	{ Opt_cache_rw, "singleclient" },
 	{ Opt_cache_err, NULL }
 };
 
@@ -1421,21 +1423,31 @@  cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
 		vol->direct_io = false;
 		vol->strict_io = false;
 		vol->cache_ro = false;
+		vol->cache_rw = false;
 		break;
 	case Opt_cache_strict:
 		vol->direct_io = false;
 		vol->strict_io = true;
 		vol->cache_ro = false;
+		vol->cache_rw = false;
 		break;
 	case Opt_cache_none:
 		vol->direct_io = true;
 		vol->strict_io = false;
 		vol->cache_ro = false;
+		vol->cache_rw = false;
 		break;
 	case Opt_cache_ro:
 		vol->direct_io = false;
 		vol->strict_io = false;
 		vol->cache_ro = true;
+		vol->cache_rw = false;
+		break;
+	case Opt_cache_rw:
+		vol->direct_io = false;
+		vol->strict_io = false;
+		vol->cache_ro = false;
+		vol->cache_rw = true;
 		break;
 	default:
 		cifs_dbg(VFS, "bad cache= option: %s\n", value);
@@ -4054,6 +4066,10 @@  int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
 	if (pvolume_info->cache_ro) {
 		cifs_dbg(VFS, "mounting share with read only caching. Ensure that the share will not be modified while in use.\n");
 		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE;
+	} else if (pvolume_info->cache_rw) {
+		cifs_dbg(VFS, "mounting share in single client RW caching mode. Ensure that no other systems will be accessing the share.\n");
+		cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE |
+					    CIFS_MOUNT_RW_CACHE);
 	}
 	if (pvolume_info->mfsymlinks) {
 		if (pvolume_info->sfu_emul) {
@@ -4203,8 +4219,10 @@  static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
 			if (tcon->fsDevInfo.DeviceCharacteristics &
 			    FILE_READ_ONLY_DEVICE)
 				cifs_dbg(VFS, "mounted to read only share\n");
-			else
+			else if ((cifs_sb->mnt_cifs_flags &
+				  CIFS_MOUNT_RW_CACHE) == 0)
 				cifs_dbg(VFS, "read only mount of RW share\n");
+			/* no need to log a RW mount of a typical RW share */
 		}
 	}
 
-- 
2.20.1