Whamcloud - gitweb
LU-3832 clio: honor O_NOATIME 42/7442/4
authorJohn L. Hammond <john.hammond@intel.com>
Fri, 23 Aug 2013 19:50:17 +0000 (14:50 -0500)
committerOleg Drokin <oleg.drokin@intel.com>
Fri, 30 Aug 2013 19:08:03 +0000 (19:08 +0000)
Add a ci_noatime bit to struct cl_io. In ll_io_init() set this bit if
O_NOATIME is set in f_flags. Ensure that this bit is propagated down
to lower layers. In osc_io_read_start() don't update atime if this bit
is set. Add sanity test 39n to check that passing O_NOATIME to open()
is honored.

Signed-off-by: John L. Hammond <john.hammond@intel.com>
Change-Id: I3e7ab1d777e897ce7840ad6b1b067a571fa2bff4
Reviewed-on: http://review.whamcloud.com/7442
Tested-by: Hudson
Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com>
Reviewed-by: Lai Siyao <lai.siyao@intel.com>
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/include/cl_object.h
lustre/llite/file.c
lustre/lov/lov_io.c
lustre/osc/osc_io.c
lustre/tests/multiop.c
lustre/tests/sanity.sh

index db81fb1..03ee887 100644 (file)
@@ -2394,11 +2394,15 @@ struct cl_io {
        /**
         * file is released, restore has to to be triggered by vvp layer
         */
        /**
         * file is released, restore has to to be triggered by vvp layer
         */
-                            ci_restore_needed:1;
-        /**
-         * Number of pages owned by this IO. For invariant checking.
-         */
-        unsigned             ci_owned_nr;
+                            ci_restore_needed:1,
+       /**
+        * O_NOATIME
+        */
+                            ci_noatime:1;
+       /**
+        * Number of pages owned by this IO. For invariant checking.
+        */
+       unsigned             ci_owned_nr;
 };
 
 /** @} cl_io */
 };
 
 /** @} cl_io */
index 6d94033..0179dd0 100644 (file)
@@ -1055,6 +1055,33 @@ int ll_glimpse_ioctl(struct ll_sb_info *sbi, struct lov_stripe_md *lsm,
         return rc;
 }
 
         return rc;
 }
 
+static bool file_is_noatime(const struct file *file)
+{
+       const struct vfsmount *mnt = file->f_path.mnt;
+       const struct inode *inode = file->f_path.dentry->d_inode;
+
+       /* Adapted from file_accessed() and touch_atime().*/
+       if (file->f_flags & O_NOATIME)
+               return true;
+
+       if (inode->i_flags & S_NOATIME)
+               return true;
+
+       if (IS_NOATIME(inode))
+               return true;
+
+       if (mnt->mnt_flags & (MNT_NOATIME | MNT_READONLY))
+               return true;
+
+       if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))
+               return true;
+
+       if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode))
+               return true;
+
+       return false;
+}
+
 void ll_io_init(struct cl_io *io, const struct file *file, int write)
 {
         struct inode *inode = file->f_dentry->d_inode;
 void ll_io_init(struct cl_io *io, const struct file *file, int write)
 {
         struct inode *inode = file->f_dentry->d_inode;
@@ -1074,6 +1101,8 @@ void ll_io_init(struct cl_io *io, const struct file *file, int write)
         } else if (file->f_flags & O_APPEND) {
                 io->ci_lockreq = CILR_MANDATORY;
         }
         } else if (file->f_flags & O_APPEND) {
                 io->ci_lockreq = CILR_MANDATORY;
         }
+
+       io->ci_noatime = file_is_noatime(file);
 }
 
 static ssize_t
 }
 
 static ssize_t
index 3a0222b..21e7da7 100644 (file)
@@ -197,6 +197,7 @@ static int lov_io_sub_init(const struct lu_env *env, struct lov_io *lio,
                 sub_io->ci_lockreq = io->ci_lockreq;
                 sub_io->ci_type    = io->ci_type;
                 sub_io->ci_no_srvlock = io->ci_no_srvlock;
                 sub_io->ci_lockreq = io->ci_lockreq;
                 sub_io->ci_type    = io->ci_type;
                 sub_io->ci_no_srvlock = io->ci_no_srvlock;
+               sub_io->ci_noatime = io->ci_noatime;
 
                 lov_sub_enter(sub);
                 result = cl_io_sub_init(sub->sub_env, sub_io,
 
                 lov_sub_enter(sub);
                 result = cl_io_sub_init(sub->sub_env, sub_io,
index 3535bbe..110704c 100644 (file)
@@ -523,23 +523,20 @@ static void osc_io_setattr_end(const struct lu_env *env,
 static int osc_io_read_start(const struct lu_env *env,
                              const struct cl_io_slice *slice)
 {
 static int osc_io_read_start(const struct lu_env *env,
                              const struct cl_io_slice *slice)
 {
-        struct osc_io    *oio   = cl2osc_io(env, slice);
-        struct cl_object *obj   = slice->cis_obj;
-        struct cl_attr   *attr  = &osc_env_info(env)->oti_attr;
-        int              result = 0;
-        ENTRY;
+       struct osc_io    *oio  = cl2osc_io(env, slice);
+       struct cl_object *obj  = slice->cis_obj;
+       struct cl_attr   *attr = &osc_env_info(env)->oti_attr;
+       int rc = 0;
+       ENTRY;
 
 
-        if (oio->oi_lockless == 0) {
-                cl_object_attr_lock(obj);
-                result = cl_object_attr_get(env, obj, attr);
-                if (result == 0) {
-                        attr->cat_atime = LTIME_S(CFS_CURRENT_TIME);
-                        result = cl_object_attr_set(env, obj, attr,
-                                                    CAT_ATIME);
-                }
-                cl_object_attr_unlock(obj);
-        }
-        RETURN(result);
+       if (oio->oi_lockless == 0 && !slice->cis_io->ci_noatime) {
+               cl_object_attr_lock(obj);
+               attr->cat_atime = LTIME_S(CFS_CURRENT_TIME);
+               rc = cl_object_attr_set(env, obj, attr, CAT_ATIME);
+               cl_object_attr_unlock(obj);
+       }
+
+       RETURN(rc);
 }
 
 static int osc_io_write_start(const struct lu_env *env,
 }
 
 static int osc_io_write_start(const struct lu_env *env,
index 519e77f..0bb9826 100644 (file)
@@ -150,6 +150,9 @@ struct flag_mapping {
 #ifdef O_DIRECT
        {"O_DIRECT", O_DIRECT},
 #endif
 #ifdef O_DIRECT
        {"O_DIRECT", O_DIRECT},
 #endif
+#ifdef O_NOATIME
+       {"O_NOATIME", O_NOATIME},
+#endif
        {"O_LARGEFILE", O_LARGEFILE},
        {"O_DIRECTORY", O_DIRECTORY},
        {"O_NOFOLLOW", O_NOFOLLOW},
        {"O_LARGEFILE", O_LARGEFILE},
        {"O_DIRECTORY", O_DIRECTORY},
        {"O_NOFOLLOW", O_NOFOLLOW},
index 2312176..f046122 100644 (file)
@@ -3093,6 +3093,37 @@ test_39m() {
 }
 run_test 39m "test atime and mtime before 1970"
 
 }
 run_test 39m "test atime and mtime before 1970"
 
+test_39n() { # LU-3832
+       local atime_diff=$(do_facet $SINGLEMDS \
+               lctl get_param -n mdd.*MDT0000*.atime_diff)
+       local atime0
+       local atime1
+       local atime2
+
+       do_facet $SINGLEMDS lctl set_param -n mdd.*MDT0000*.atime_diff=1
+
+       rm -rf $DIR/$tfile
+       dd if=/dev/zero of=$DIR/$tfile bs=4096 count=1 status=noxfer
+       atime0=$(stat -c %X $DIR/$tfile)
+
+       sleep 5
+       $MULTIOP $DIR/$tfile oO_RDONLY:O_NOATIME:r4096c
+       atime1=$(stat -c %X $DIR/$tfile)
+
+       sleep 5
+       cancel_lru_locks mdc
+       cancel_lru_locks osc
+       $MULTIOP $DIR/$tfile oO_RDONLY:O_NOATIME:r4096c
+       atime2=$(stat -c %X $DIR/$tfile)
+
+       do_facet $SINGLEMDS \
+               lctl set_param -n mdd.*MDT0000*.atime_diff=$atime_diff
+
+       [ "$atime0" -eq "$atime1" ] || error "atime0 $atime0 != atime1 $atime1"
+       [ "$atime1" -eq "$atime2" ] || error "atime0 $atime0 != atime1 $atime1"
+}
+run_test 39n "check that O_NOATIME is honored"
+
 test_40() {
        dd if=/dev/zero of=$DIR/$tfile bs=4096 count=1
        $RUNAS $OPENFILE -f O_WRONLY:O_TRUNC $DIR/$tfile &&
 test_40() {
        dd if=/dev/zero of=$DIR/$tfile bs=4096 count=1
        $RUNAS $OPENFILE -f O_WRONLY:O_TRUNC $DIR/$tfile &&