Commit 6d20e840 authored by Suresh Jayaraman's avatar Suresh Jayaraman Committed by Steve French

cifs: add attribute cache timeout (actimeo) tunable

Currently, the attribute cache timeout for CIFS is hardcoded to 1 second. This
means that the client might have to issue a QPATHINFO/QFILEINFO call every 1
second to verify if something has changes, which seems too expensive. On the
other hand, if the timeout is hardcoded to a higher value, workloads that
expect strict cache coherency might see unexpected results.

Making attribute cache timeout as a tunable will allow us to make a tradeoff
between performance and cache metadata correctness depending on the
application/workload needs.

Add 'actimeo' tunable that can be used to tune the attribute cache timeout.
The default timeout is set to 1 second. Also, display actimeo option value in
/proc/mounts.

It appears to me that 'actimeo' and the proposed (but not yet merged)
'strictcache' option cannot coexist, so care must be taken that we reset the
other option if one of them is set.

Changes since last post:
   - fix option parsing and handle possible values correcly
Reviewed-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarSuresh Jayaraman <sjayaraman@suse.de>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent 8cb280c9
...@@ -337,6 +337,15 @@ A partial list of the supported mount options follows: ...@@ -337,6 +337,15 @@ A partial list of the supported mount options follows:
wsize default write size (default 57344) wsize default write size (default 57344)
maximum wsize currently allowed by CIFS is 57344 (fourteen maximum wsize currently allowed by CIFS is 57344 (fourteen
4096 byte pages) 4096 byte pages)
actimeo=n attribute cache timeout in seconds (default 1 second).
After this timeout, the cifs client requests fresh attribute
information from the server. This option allows to tune the
attribute cache timeout to suit the workload needs. Shorter
timeouts mean better the cache coherency, but increased number
of calls to the server. Longer timeouts mean reduced number
of calls to the server at the expense of less stricter cache
coherency checks (i.e. incorrect attribute cache for a short
period of time).
rw mount the network share read-write (note that the rw mount the network share read-write (note that the
server may still consider the share read-only) server may still consider the share read-only)
ro mount network share read-only ro mount network share read-only
......
...@@ -48,6 +48,7 @@ struct cifs_sb_info { ...@@ -48,6 +48,7 @@ struct cifs_sb_info {
struct nls_table *local_nls; struct nls_table *local_nls;
unsigned int rsize; unsigned int rsize;
unsigned int wsize; unsigned int wsize;
unsigned long actimeo; /* attribute cache timeout (jiffies) */
atomic_t active; atomic_t active;
uid_t mnt_uid; uid_t mnt_uid;
gid_t mnt_gid; gid_t mnt_gid;
......
...@@ -463,6 +463,8 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) ...@@ -463,6 +463,8 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
seq_printf(s, ",rsize=%d", cifs_sb->rsize); seq_printf(s, ",rsize=%d", cifs_sb->rsize);
seq_printf(s, ",wsize=%d", cifs_sb->wsize); seq_printf(s, ",wsize=%d", cifs_sb->wsize);
/* convert actimeo and display it in seconds */
seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ);
return 0; return 0;
} }
......
...@@ -44,6 +44,16 @@ ...@@ -44,6 +44,16 @@
#define CIFS_MIN_RCV_POOL 4 #define CIFS_MIN_RCV_POOL 4
/*
* default attribute cache timeout (jiffies)
*/
#define CIFS_DEF_ACTIMEO (1 * HZ)
/*
* max attribute cache timeout (jiffies) - 2^30
*/
#define CIFS_MAX_ACTIMEO (1 << 30)
/* /*
* MAX_REQ is the maximum number of requests that WE will send * MAX_REQ is the maximum number of requests that WE will send
* on one socket concurrently. It also matches the most common * on one socket concurrently. It also matches the most common
......
...@@ -105,6 +105,7 @@ struct smb_vol { ...@@ -105,6 +105,7 @@ struct smb_vol {
unsigned int wsize; unsigned int wsize;
bool sockopt_tcp_nodelay:1; bool sockopt_tcp_nodelay:1;
unsigned short int port; unsigned short int port;
unsigned long actimeo; /* attribute cache timeout (jiffies) */
char *prepath; char *prepath;
struct sockaddr_storage srcaddr; /* allow binding to a local IP */ struct sockaddr_storage srcaddr; /* allow binding to a local IP */
struct nls_table *local_nls; struct nls_table *local_nls;
...@@ -840,6 +841,8 @@ cifs_parse_mount_options(char *options, const char *devname, ...@@ -840,6 +841,8 @@ cifs_parse_mount_options(char *options, const char *devname,
/* default to using server inode numbers where available */ /* default to using server inode numbers where available */
vol->server_ino = 1; vol->server_ino = 1;
vol->actimeo = CIFS_DEF_ACTIMEO;
if (!options) if (!options)
return 1; return 1;
...@@ -1214,6 +1217,16 @@ cifs_parse_mount_options(char *options, const char *devname, ...@@ -1214,6 +1217,16 @@ cifs_parse_mount_options(char *options, const char *devname,
printk(KERN_WARNING "CIFS: server net" printk(KERN_WARNING "CIFS: server net"
"biosname longer than 15 truncated.\n"); "biosname longer than 15 truncated.\n");
} }
} else if (strnicmp(data, "actimeo", 7) == 0) {
if (value && *value) {
vol->actimeo = HZ * simple_strtoul(value,
&value, 0);
if (vol->actimeo > CIFS_MAX_ACTIMEO) {
cERROR(1, "CIFS: attribute cache"
"timeout too large");
return 1;
}
}
} else if (strnicmp(data, "credentials", 4) == 0) { } else if (strnicmp(data, "credentials", 4) == 0) {
/* ignore */ /* ignore */
} else if (strnicmp(data, "version", 3) == 0) { } else if (strnicmp(data, "version", 3) == 0) {
...@@ -2571,6 +2584,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info, ...@@ -2571,6 +2584,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
cFYI(1, "file mode: 0x%x dir mode: 0x%x", cFYI(1, "file mode: 0x%x dir mode: 0x%x",
cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode); cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
cifs_sb->actimeo = pvolume_info->actimeo;
if (pvolume_info->noperm) if (pvolume_info->noperm)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM; cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
if (pvolume_info->setuids) if (pvolume_info->setuids)
......
...@@ -1653,6 +1653,7 @@ static bool ...@@ -1653,6 +1653,7 @@ static bool
cifs_inode_needs_reval(struct inode *inode) cifs_inode_needs_reval(struct inode *inode)
{ {
struct cifsInodeInfo *cifs_i = CIFS_I(inode); struct cifsInodeInfo *cifs_i = CIFS_I(inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
if (cifs_i->clientCanCacheRead) if (cifs_i->clientCanCacheRead)
return false; return false;
...@@ -1663,12 +1664,12 @@ cifs_inode_needs_reval(struct inode *inode) ...@@ -1663,12 +1664,12 @@ cifs_inode_needs_reval(struct inode *inode)
if (cifs_i->time == 0) if (cifs_i->time == 0)
return true; return true;
/* FIXME: the actimeo should be tunable */ if (!time_in_range(jiffies, cifs_i->time,
if (time_after_eq(jiffies, cifs_i->time + HZ)) cifs_i->time + cifs_sb->actimeo))
return true; return true;
/* hardlinked files w/ noserverino get "special" treatment */ /* hardlinked files w/ noserverino get "special" treatment */
if (!(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) && if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
S_ISREG(inode->i_mode) && inode->i_nlink != 1) S_ISREG(inode->i_mode) && inode->i_nlink != 1)
return true; return true;
......
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