summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/inode.c17
-rw-r--r--fs/namespace.c12
-rw-r--r--fs/nfs/inode.c17
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c3
-rw-r--r--include/linux/fs.h5
-rw-r--r--include/linux/mount.h8
6 files changed, 44 insertions, 18 deletions
diff --git a/fs/inode.c b/fs/inode.c
index 76980a9c92e7..108138d4e909 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -22,6 +22,7 @@
#include <linux/cdev.h>
#include <linux/bootmem.h>
#include <linux/inotify.h>
+#include <linux/mount.h>
/*
* This is needed for the following functions:
@@ -1189,12 +1190,20 @@ void touch_atime(struct vfsmount *mnt, struct dentry *dentry)
struct inode *inode = dentry->d_inode;
struct timespec now;
- /* per-mountpoint checks will go here */
- if (IS_NOATIME(inode))
+ if (IS_RDONLY(inode))
return;
- if (IS_NODIRATIME(inode) && S_ISDIR(inode->i_mode))
+
+ 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;
- if (IS_RDONLY(inode))
+
+ /*
+ * 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);
diff --git a/fs/namespace.c b/fs/namespace.c
index f0e353f5bc30..2ca6145f43d6 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -355,14 +355,14 @@ static int show_vfsmnt(struct seq_file *m, void *v)
{ MS_SYNCHRONOUS, ",sync" },
{ MS_DIRSYNC, ",dirsync" },
{ MS_MANDLOCK, ",mand" },
- { MS_NOATIME, ",noatime" },
- { MS_NODIRATIME, ",nodiratime" },
{ 0, NULL }
};
static struct proc_fs_info mnt_info[] = {
{ MNT_NOSUID, ",nosuid" },
{ MNT_NODEV, ",nodev" },
{ MNT_NOEXEC, ",noexec" },
+ { MNT_NOATIME, ",noatime" },
+ { MNT_NODIRATIME, ",nodiratime" },
{ 0, NULL }
};
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;
if (flags & MS_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 */
retval = path_lookup(dir_name, LOOKUP_FOLLOW, &nd);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 3e4ba9cb7f80..a77ee95b7efb 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -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 */
nfs_sync_inode(inode, 0, 0, FLUSH_WAIT|FLUSH_NOCOMMIT);
- if (__IS_FLG(inode, MS_NOATIME))
- need_atime = 0;
- else if (__IS_FLG(inode, MS_NODIRATIME) && S_ISDIR(inode->i_mode))
+
+ /*
+ * 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;
- /* We may force a getattr if the user cares about atime */
+
if (need_atime)
err = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
else
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 41c478bb1ffc..97fb1470cf28 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -54,6 +54,9 @@
#include <linux/xattr.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.
* We don't lock across timestamp updates, and we don't log them but
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 85c5656756b6..d1e370d25f7b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -114,8 +114,7 @@ extern int dir_notify_enable;
/*
* Superblock flags that can be altered by MS_REMOUNT
*/
-#define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_NOATIME|\
- MS_NODIRATIME)
+#define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK)
/*
* 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_APPEND(inode) ((inode)->i_flags & S_APPEND)
#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_DEADDIR(inode) ((inode)->i_flags & S_DEAD)
diff --git a/include/linux/mount.h b/include/linux/mount.h
index b98a709f1794..b7472ae91fa4 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -20,10 +20,12 @@
#define MNT_NOSUID 0x01
#define MNT_NODEV 0x02
#define MNT_NOEXEC 0x04
-#define MNT_SHARED 0x10 /* if the vfsmount is a shared mount */
-#define MNT_UNBINDABLE 0x20 /* if the vfsmount is a unbindable mount */
+#define MNT_NOATIME 0x08
+#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 list_head mnt_hash;