Whamcloud - gitweb
LU-15728 llite: fix relatime support
authorAurelien Degremont <degremoa@amazon.com>
Thu, 7 Apr 2022 12:58:00 +0000 (12:58 +0000)
committerAndreas Dilger <adilger@whamcloud.com>
Mon, 21 Aug 2023 08:47:16 +0000 (08:47 +0000)
relatime behavior is properly managed by VFS, however
Lustre also stores acmtime on OST objects and atime
updates for OST objects should honor relatime behavior.

This patch updates 'ci_noatime' feature which was introduced to
properly honor noatime option for OST objects, to also support
'relatime'.
file_is_noatime() code already comes from upstream touch_atime().
Add missing parts from touch_atime() to also support relatime.

It also forces atime to disk on MDD if ondisk atime is older than
ondisk mtime/ctime to match relatime (even if relatime is not enabled)

Add a new test for relatime feature.

Lustre-change: https://review.whamcloud.com/47017
Lustre-commit: c10c6eeb37dd553166367b96369dca25183ace3b

Signed-off-by: Aurelien Degremont <degremoa@amazon.com>
Change-Id: I7a26f39841300a60c015944f9e544115b4446ead
Reviewed-by: Shaun Tancheff <shaun.tancheff@hpe.com>
Reviewed-by: Yang Sheng <ys@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
LU-15728 mdd: fix sanity-56oc failure

sanity 56oc starts failing since relatime patch was landed.
'relatime' patch introduced an atime behavior change.  It was forcing
atime uptime to disk on MDD if ondisk atime is older than ondisk
mtime/ctime to match relatime (even if relatime was not enabled).

This was an optimization, trying to have a slightly better atime value
cheaply. This is unfortunately causing regression in sanity-56oc.
Let's remove it for now until we understand that better.

Lustre-change: https://review.whamcloud.com/50009
Lustre-commit: 8beeec77c3b426a01e1f10ca51149c7ca7e01b7e

Fixes: c10c6ee ("LU-15728 llite: fix relatime support")
Change-Id: Ieed4d4c7523c26cfc5bc230986d96b2acf152dee
Signed-off-by: Aurelien Degremont <degremoa@amazon.com>
Reviewed-by: Alex Zhuravlev <bzzz@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/51858
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
lustre/llite/file.c
lustre/mdd/mdd_object.c
lustre/tests/sanity.sh

index 29ab6b3..0d0794e 100644 (file)
@@ -1578,12 +1578,47 @@ void ll_io_set_mirror(struct cl_io *io, const struct file *file)
               file->f_path.dentry->d_name.name, io->ci_designated_mirror);
 }
 
+/*
+ * This is relatime_need_update() from Linux 5.17, which is not exported.
+ */
+static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
+                               struct timespec64 now)
+{
+
+       if (!(mnt->mnt_flags & MNT_RELATIME))
+               return 1;
+       /*
+        * Is mtime younger than atime? If yes, update atime:
+        */
+       if (timespec64_compare(&inode->i_mtime, &inode->i_atime) >= 0)
+               return 1;
+       /*
+        * Is ctime younger than atime? If yes, update atime:
+        */
+       if (timespec64_compare(&inode->i_ctime, &inode->i_atime) >= 0)
+               return 1;
+
+       /*
+        * Is the previous atime value older than a day? If yes,
+        * update atime:
+        */
+       if ((long)(now.tv_sec - inode->i_atime.tv_sec) >= 24*60*60)
+               return 1;
+       /*
+        * Good, we can skip the atime update:
+        */
+       return 0;
+}
+
+/*
+ * Very similar to kernel function: !__atime_needs_update()
+ */
 static bool file_is_noatime(const struct file *file)
 {
-       const struct vfsmount *mnt = file->f_path.mnt;
-       const struct inode *inode = file_inode((struct file *)file);
+       struct vfsmount *mnt = file->f_path.mnt;
+       struct inode *inode = file_inode((struct file *)file);
+       struct timespec64 now;
 
-       /* Adapted from file_accessed() and touch_atime().*/
        if (file->f_flags & O_NOATIME)
                return true;
 
@@ -1602,6 +1637,11 @@ static bool file_is_noatime(const struct file *file)
        if ((inode->i_sb->s_flags & SB_NODIRATIME) && S_ISDIR(inode->i_mode))
                return true;
 
+       now = current_time(inode);
+
+       if (!relatime_need_update(mnt, inode, now))
+               return true;
+
        return false;
 }
 
index 3da4924..81d8131 100644 (file)
@@ -656,6 +656,11 @@ static bool is_project_state_change(const struct lu_attr *oattr,
  * chown_common and inode_setattr
  * utimes and inode_setattr
  * This API is ported from mds_fix_attr but remove some unnecesssary stuff.
+ *
+ * @param[in]     oattr  Original, current object attributes.
+ * @param[in,out] la     New attributes to be evaluated and potentially
+ *                       modified depending on oattr content and other rules.
+ * @param[in]     ma     md_attr to be evaluated for that object.
  */
 static int mdd_fix_attr(const struct lu_env *env, struct mdd_object *obj,
                        const struct lu_attr *oattr, struct lu_attr *la,
index 0b219ff..08d8f5f 100755 (executable)
@@ -4877,6 +4877,53 @@ test_39q() { # LU-8041
 }
 run_test 39q "close won't zero out atime"
 
+test_39s() {
+       local atime0
+       local atime1
+       local atime2
+       local atime3
+       local atime4
+
+       umount_client $MOUNT
+       mount_client $MOUNT relatime
+
+       dd if=/dev/zero of=$DIR/$tfile bs=4096 count=1 status=noxfer conv=fsync
+       atime0=$(stat -c %X $DIR/$tfile)
+
+       # First read updates atime
+       sleep 1
+       cat $DIR/$tfile >/dev/null
+       atime1=$(stat -c %X $DIR/$tfile) # (atime = atime0 + 1)
+
+       # Next reads do not update atime
+       sleep 1
+       cat $DIR/$tfile >/dev/null
+       atime2=$(stat -c %X $DIR/$tfile) # (atime = atime0 + 1)
+
+       # If mtime is greater than atime, atime is updated
+       sleep 1
+       touch -m $DIR/$tfile # (mtime = now)
+       sleep 1
+       cat $DIR/$tfile >/dev/null # (atime is updated because atime < mtime)
+       atime3=$(stat -c %X $DIR/$tfile) # (atime = mtime = atime0 + 3)
+
+       # Next reads do not update atime
+       sleep 1
+       cat $DIR/$tfile >/dev/null
+       atime4=$(stat -c %X $DIR/$tfile)
+
+       # Remount the client to clear 'relatime' option
+       remount_client $MOUNT
+
+       (( atime0 < atime1 )) ||
+               error "atime $atime0 should be smaller than $atime1"
+       (( atime1 == atime2 )) ||
+               error "atime $atime1 was updated to $atime2"
+       (( atime1 < atime3 )) || error "atime1 $atime1 != atime3 $atime3"
+       (( atime3 == atime4 )) || error "atime3 $atime3 != atime4 $atime4"
+}
+run_test 39s "relatime is supported"
+
 test_40() {
        dd if=/dev/zero of=$DIR/$tfile bs=4096 count=1
        $RUNAS $OPENFILE -f O_WRONLY:O_TRUNC $DIR/$tfile &&