[PATCH] per-mountpoint noatime/nodiratime

Turn noatime and nodiratime into per-mount instead of per-sb flags.

After all the preparations this is a rather trivial patch.  The mount code
needs to treat the two options as per-mount instead of per-superblock, and
touch_atime needs to be changed to check the new MNT_ flags in addition to
the MS_ flags that are kept for filesystems that are always
noatime/nodiratime but not user settable anymore.  Besides that core code
only nfs needed an update because it's leaving atime updates to the server
and thus sets the S_NOATIME flag on every inode, but needs to know whether
it's a real noatime mount for an getattr optimization.

While we're at it I've killed the IS_NOATIME/IS_NODIRATIME macros that were
only used by touch_atime.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Christoph Hellwig 2006-01-09 20:52:17 -08:00 committed by Linus Torvalds
parent 0d456fa426
commit fc33a7bb9c
6 changed files with 45 additions and 19 deletions

View File

@ -22,6 +22,7 @@
#include <linux/cdev.h> #include <linux/cdev.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/inotify.h> #include <linux/inotify.h>
#include <linux/mount.h>
/* /*
* This is needed for the following functions: * This is needed for the following functions:
@ -1189,14 +1190,22 @@ void touch_atime(struct vfsmount *mnt, struct dentry *dentry)
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
struct timespec now; struct timespec now;
/* per-mountpoint checks will go here */
if (IS_NOATIME(inode))
return;
if (IS_NODIRATIME(inode) && S_ISDIR(inode->i_mode))
return;
if (IS_RDONLY(inode)) if (IS_RDONLY(inode))
return; return;
if ((inode->i_flags & S_NOATIME) ||
(inode->i_sb->s_flags & MS_NOATIME) ||
((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode)))
return;
/*
* We may have a NULL vfsmount when coming from NFSD
*/
if (mnt &&
((mnt->mnt_flags & MNT_NOATIME) ||
((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))))
return;
now = current_fs_time(inode->i_sb); now = current_fs_time(inode->i_sb);
if (!timespec_equal(&inode->i_atime, &now)) { if (!timespec_equal(&inode->i_atime, &now)) {
inode->i_atime = now; inode->i_atime = now;

View File

@ -355,14 +355,14 @@ static int show_vfsmnt(struct seq_file *m, void *v)
{ MS_SYNCHRONOUS, ",sync" }, { MS_SYNCHRONOUS, ",sync" },
{ MS_DIRSYNC, ",dirsync" }, { MS_DIRSYNC, ",dirsync" },
{ MS_MANDLOCK, ",mand" }, { MS_MANDLOCK, ",mand" },
{ MS_NOATIME, ",noatime" },
{ MS_NODIRATIME, ",nodiratime" },
{ 0, NULL } { 0, NULL }
}; };
static struct proc_fs_info mnt_info[] = { static struct proc_fs_info mnt_info[] = {
{ MNT_NOSUID, ",nosuid" }, { MNT_NOSUID, ",nosuid" },
{ MNT_NODEV, ",nodev" }, { MNT_NODEV, ",nodev" },
{ MNT_NOEXEC, ",noexec" }, { MNT_NOEXEC, ",noexec" },
{ MNT_NOATIME, ",noatime" },
{ MNT_NODIRATIME, ",nodiratime" },
{ 0, NULL } { 0, NULL }
}; };
struct proc_fs_info *fs_infop; struct proc_fs_info *fs_infop;
@ -1286,7 +1286,13 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
mnt_flags |= MNT_NODEV; mnt_flags |= MNT_NODEV;
if (flags & MS_NOEXEC) if (flags & MS_NOEXEC)
mnt_flags |= MNT_NOEXEC; mnt_flags |= MNT_NOEXEC;
flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE); if (flags & MS_NOATIME)
mnt_flags |= MNT_NOATIME;
if (flags & MS_NODIRATIME)
mnt_flags |= MNT_NODIRATIME;
flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE |
MS_NOATIME | MS_NODIRATIME);
/* ... and get the mountpoint */ /* ... and get the mountpoint */
retval = path_lookup(dir_name, LOOKUP_FOLLOW, &nd); retval = path_lookup(dir_name, LOOKUP_FOLLOW, &nd);

View File

@ -950,11 +950,20 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
/* Flush out writes to the server in order to update c/mtime */ /* Flush out writes to the server in order to update c/mtime */
nfs_sync_inode(inode, 0, 0, FLUSH_WAIT|FLUSH_NOCOMMIT); nfs_sync_inode(inode, 0, 0, FLUSH_WAIT|FLUSH_NOCOMMIT);
if (__IS_FLG(inode, MS_NOATIME))
/*
* We may force a getattr if the user cares about atime.
*
* Note that we only have to check the vfsmount flags here:
* - NFS always sets S_NOATIME by so checking it would give a
* bogus result
* - NFS never sets MS_NOATIME or MS_NODIRATIME so there is
* no point in checking those.
*/
if ((mnt->mnt_flags & MNT_NOATIME) ||
((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode)))
need_atime = 0; need_atime = 0;
else if (__IS_FLG(inode, MS_NODIRATIME) && S_ISDIR(inode->i_mode))
need_atime = 0;
/* We may force a getattr if the user cares about atime */
if (need_atime) if (need_atime)
err = __nfs_revalidate_inode(NFS_SERVER(inode), inode); err = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
else else

View File

@ -54,6 +54,9 @@
#include <linux/xattr.h> #include <linux/xattr.h>
#include <linux/namei.h> #include <linux/namei.h>
#define IS_NOATIME(inode) ((inode->i_sb->s_flags & MS_NOATIME) || \
(S_ISDIR(inode->i_mode) && inode->i_sb->s_flags & MS_NODIRATIME))
/* /*
* Change the requested timestamp in the given inode. * Change the requested timestamp in the given inode.
* We don't lock across timestamp updates, and we don't log them but * We don't lock across timestamp updates, and we don't log them but

View File

@ -114,8 +114,7 @@ extern int dir_notify_enable;
/* /*
* Superblock flags that can be altered by MS_REMOUNT * Superblock flags that can be altered by MS_REMOUNT
*/ */
#define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_NOATIME|\ #define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK)
MS_NODIRATIME)
/* /*
* Old magic mount flag and mask * Old magic mount flag and mask
@ -161,8 +160,6 @@ extern int dir_notify_enable;
#define IS_NOQUOTA(inode) ((inode)->i_flags & S_NOQUOTA) #define IS_NOQUOTA(inode) ((inode)->i_flags & S_NOQUOTA)
#define IS_APPEND(inode) ((inode)->i_flags & S_APPEND) #define IS_APPEND(inode) ((inode)->i_flags & S_APPEND)
#define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE) #define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE)
#define IS_NOATIME(inode) (__IS_FLG(inode, MS_NOATIME) || ((inode)->i_flags & S_NOATIME))
#define IS_NODIRATIME(inode) __IS_FLG(inode, MS_NODIRATIME)
#define IS_POSIXACL(inode) __IS_FLG(inode, MS_POSIXACL) #define IS_POSIXACL(inode) __IS_FLG(inode, MS_POSIXACL)
#define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD) #define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD)

View File

@ -20,10 +20,12 @@
#define MNT_NOSUID 0x01 #define MNT_NOSUID 0x01
#define MNT_NODEV 0x02 #define MNT_NODEV 0x02
#define MNT_NOEXEC 0x04 #define MNT_NOEXEC 0x04
#define MNT_SHARED 0x10 /* if the vfsmount is a shared mount */ #define MNT_NOATIME 0x08
#define MNT_UNBINDABLE 0x20 /* if the vfsmount is a unbindable mount */ #define MNT_NODIRATIME 0x10
#define MNT_PNODE_MASK (MNT_SHARED | MNT_UNBINDABLE) #define MNT_SHARED 0x1000 /* if the vfsmount is a shared mount */
#define MNT_UNBINDABLE 0x2000 /* if the vfsmount is a unbindable mount */
#define MNT_PNODE_MASK 0x3000 /* propogation flag mask */
struct vfsmount { struct vfsmount {
struct list_head mnt_hash; struct list_head mnt_hash;