return;
                if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))
                        return;
+
+               if (mnt->mnt_flags & MNT_RELATIME) {
+                       /*
+                        * With relative atime, only update atime if the
+                        * previous atime is earlier than either the ctime or
+                        * mtime.
+                        */
+                       if (timespec_compare(&inode->i_mtime,
+                                               &inode->i_atime) < 0 &&
+                           timespec_compare(&inode->i_ctime,
+                                               &inode->i_atime) < 0)
+                               return;
+               }
        }
 
        now = current_fs_time(inode->i_sb);
-       if (!timespec_equal(&inode->i_atime, &now)) {
-               inode->i_atime = now;
-               mark_inode_dirty_sync(inode);
-       }
+       if (timespec_equal(&inode->i_atime, &now))
+               return;
+
+       inode->i_atime = now;
+       mark_inode_dirty_sync(inode);
 }
 EXPORT_SYMBOL(touch_atime);
 
 
                { MNT_NOEXEC, ",noexec" },
                { MNT_NOATIME, ",noatime" },
                { MNT_NODIRATIME, ",nodiratime" },
+               { MNT_RELATIME, ",relatime" },
                { 0, NULL }
        };
        struct proc_fs_info *fs_infop;
                mnt_flags |= MNT_NOATIME;
        if (flags & MS_NODIRATIME)
                mnt_flags |= MNT_NODIRATIME;
+       if (flags & MS_RELATIME)
+               mnt_flags |= MNT_RELATIME;
 
        flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE |
-                  MS_NOATIME | MS_NODIRATIME);
+                  MS_NOATIME | MS_NODIRATIME | MS_RELATIME);
 
        /* ... and get the mountpoint */
        retval = path_lookup(dir_name, LOOKUP_FOLLOW, &nd);
 
 #define MS_PRIVATE     (1<<18) /* change to private */
 #define MS_SLAVE       (1<<19) /* change to slave */
 #define MS_SHARED      (1<<20) /* change to shared */
+#define MS_RELATIME    (1<<21) /* Update atime relative to mtime/ctime. */
 #define MS_ACTIVE      (1<<30)
 #define MS_NOUSER      (1<<31)
 
 
 #define MNT_NOEXEC     0x04
 #define MNT_NOATIME    0x08
 #define MNT_NODIRATIME 0x10
+#define MNT_RELATIME   0x20
 
 #define MNT_SHRINKABLE 0x100