per-mountpoint noatime/nodiratime
Subsystems (2)
PATCH 1/1 per-mountpoint noatime/nodiratime
New version of the per-mount noatime patch to address Al's dislike of the FS_NOATIME/FS_NODIRATIME flags and the nfs NULL vfsmount problem.
We now still obey MS_NOATIME/MS_NODIRATIME in s_flags, but the only way to set those is from ->get_sb / ->remount_fs. touch_atime deals with a NULL vfsmount fine now.
I'm currently on chistmas vacation and didn't want to run -mm on my laptop, so this patch is against current mainline plus the following patches from -mm that are requirements for this work:
replace-inode_update_time-with-file_update_time.patch replace-inode_update_time-with-file_update_time-comments.patch replace-inode_update_time-with-file_update_time-switch-ntfs-to-touch_atime.patch switch-autofs4-to-touch_atime.patch
remove-update_atime.patch ntfs-remove-superflous-ms_noatime-ms_nodiratime-assignments.patch 9p-remove-superflous-ms_nodiratime-assignment.patch
git-xfs.patch
remove-ms_noatime-mirroring-inside-xfs.patch
Andew, I think it should apply against -mm if you remove the following patches from the previous per-mountpoint no-atime series:
introduce-fs_noatime-and-fs_nodiratime-flags.patch fs_noatime-for-ocfs.patch per-mount-noatime-and-nodiratime.patch
And now the actual patch and changelog for git:
--
From: Christoph Hellwig <[email protected]>
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.
fs/inode.c +13 -4
@@ -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 @@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);
fs/namespace.c +9 -3
@@ -355,14 +355,14 @@ { 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 @@ 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);
fs/nfs/inode.c +12 -4
@@ -958,11 +958,19 @@int need_atime =NFS_I (inode)->cache_validity &NFS_INO_INVALID_ATIME ;int err; -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
include/linux/fs.h +1 -4
@@ -115,8 +115,7 @@/* * 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
@@ -162,8 +161,6 @@#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)
include/linux/mount.h +6 -3
@@ -20,9 +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_PNODE_MASK 0x30/* propogation flag mask */ +#define MNT_NOATIME 0x08 +#define MNT_NODIRATIME 0x10 + +#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;