Commit 41e033fe authored by Steve French's avatar Steve French

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: default avatarSteve French <stfrench@microsoft.com>
parent 1981ebaa
...@@ -54,6 +54,7 @@ ...@@ -54,6 +54,7 @@
#define CIFS_MOUNT_NO_DFS 0x8000000 /* disable DFS resolving */ #define CIFS_MOUNT_NO_DFS 0x8000000 /* disable DFS resolving */
#define CIFS_MOUNT_MODE_FROM_SID 0x10000000 /* retrieve mode from special ACE */ #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_RO_CACHE 0x20000000 /* assumes share will not change */
#define CIFS_MOUNT_RW_CACHE 0x40000000 /* assumes only client accessing */
struct cifs_sb_info { struct cifs_sb_info {
struct rb_root tlink_tree; struct rb_root tlink_tree;
......
...@@ -400,6 +400,8 @@ cifs_show_cache_flavor(struct seq_file *s, struct cifs_sb_info *cifs_sb) ...@@ -400,6 +400,8 @@ cifs_show_cache_flavor(struct seq_file *s, struct cifs_sb_info *cifs_sb)
seq_puts(s, "strict"); seq_puts(s, "strict");
else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
seq_puts(s, "none"); 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) else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE)
seq_puts(s, "ro"); /* read only caching assumed */ seq_puts(s, "ro"); /* read only caching assumed */
else else
......
...@@ -560,6 +560,7 @@ struct smb_vol { ...@@ -560,6 +560,7 @@ struct smb_vol {
bool direct_io:1; bool direct_io:1;
bool strict_io:1; /* strict cache behavior */ bool strict_io:1; /* strict cache behavior */
bool cache_ro:1; bool cache_ro:1;
bool cache_rw:1;
bool remap:1; /* set to remap seven reserved chars in filenames */ bool remap:1; /* set to remap seven reserved chars in filenames */
bool sfu_remap:1; /* remap seven reserved chars ala SFU */ bool sfu_remap:1; /* remap seven reserved chars ala SFU */
bool posix_paths:1; /* unset to not ask for posix pathnames. */ bool posix_paths:1; /* unset to not ask for posix pathnames. */
...@@ -622,7 +623,7 @@ struct smb_vol { ...@@ -622,7 +623,7 @@ struct smb_vol {
CIFS_MOUNT_CIFS_BACKUPUID | CIFS_MOUNT_CIFS_BACKUPGID | \ CIFS_MOUNT_CIFS_BACKUPUID | CIFS_MOUNT_CIFS_BACKUPGID | \
CIFS_MOUNT_UID_FROM_ACL | CIFS_MOUNT_NO_HANDLE_CACHE | \ CIFS_MOUNT_UID_FROM_ACL | CIFS_MOUNT_NO_HANDLE_CACHE | \
CIFS_MOUNT_NO_DFS | CIFS_MOUNT_MODE_FROM_SID | \ 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 * Generic VFS superblock mount flags (s_flags) to consider when
...@@ -1370,7 +1371,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file); ...@@ -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_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_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 * One of these for each file inode
......
...@@ -299,6 +299,7 @@ enum { ...@@ -299,6 +299,7 @@ enum {
Opt_cache_strict, Opt_cache_strict,
Opt_cache_none, Opt_cache_none,
Opt_cache_ro, Opt_cache_ro,
Opt_cache_rw,
Opt_cache_err Opt_cache_err
}; };
...@@ -307,6 +308,7 @@ static const match_table_t cifs_cacheflavor_tokens = { ...@@ -307,6 +308,7 @@ static const match_table_t cifs_cacheflavor_tokens = {
{ Opt_cache_strict, "strict" }, { Opt_cache_strict, "strict" },
{ Opt_cache_none, "none" }, { Opt_cache_none, "none" },
{ Opt_cache_ro, "ro" }, { Opt_cache_ro, "ro" },
{ Opt_cache_rw, "singleclient" },
{ Opt_cache_err, NULL } { Opt_cache_err, NULL }
}; };
...@@ -1421,21 +1423,31 @@ cifs_parse_cache_flavor(char *value, struct smb_vol *vol) ...@@ -1421,21 +1423,31 @@ cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
vol->direct_io = false; vol->direct_io = false;
vol->strict_io = false; vol->strict_io = false;
vol->cache_ro = false; vol->cache_ro = false;
vol->cache_rw = false;
break; break;
case Opt_cache_strict: case Opt_cache_strict:
vol->direct_io = false; vol->direct_io = false;
vol->strict_io = true; vol->strict_io = true;
vol->cache_ro = false; vol->cache_ro = false;
vol->cache_rw = false;
break; break;
case Opt_cache_none: case Opt_cache_none:
vol->direct_io = true; vol->direct_io = true;
vol->strict_io = false; vol->strict_io = false;
vol->cache_ro = false; vol->cache_ro = false;
vol->cache_rw = false;
break; break;
case Opt_cache_ro: case Opt_cache_ro:
vol->direct_io = false; vol->direct_io = false;
vol->strict_io = false; vol->strict_io = false;
vol->cache_ro = true; 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; break;
default: default:
cifs_dbg(VFS, "bad cache= option: %s\n", value); cifs_dbg(VFS, "bad cache= option: %s\n", value);
...@@ -4054,6 +4066,10 @@ int cifs_setup_cifs_sb(struct smb_vol *pvolume_info, ...@@ -4054,6 +4066,10 @@ int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
if (pvolume_info->cache_ro) { 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_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; 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->mfsymlinks) {
if (pvolume_info->sfu_emul) { if (pvolume_info->sfu_emul) {
...@@ -4203,8 +4219,10 @@ static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb, ...@@ -4203,8 +4219,10 @@ static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
if (tcon->fsDevInfo.DeviceCharacteristics & if (tcon->fsDevInfo.DeviceCharacteristics &
FILE_READ_ONLY_DEVICE) FILE_READ_ONLY_DEVICE)
cifs_dbg(VFS, "mounted to read only share\n"); 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"); cifs_dbg(VFS, "read only mount of RW share\n");
/* no need to log a RW mount of a typical RW share */
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment