From b9b3b6a86c3c6d34a89201e45837435af5e66441 Mon Sep 17 00:00:00 2001 From: Steve French 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 --- 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