Whamcloud - gitweb
LU-12026 mdt: MDS stores atime|mtime|ctime during close 86/36286/9
authorQian Yingjin <qian@ddn.com>
Wed, 25 Sep 2019 09:14:12 +0000 (17:14 +0800)
committerOleg Drokin <green@whamcloud.com>
Tue, 22 Oct 2019 23:57:39 +0000 (23:57 +0000)
In order to make direct inode scanning on the MDT useful, in
addition to storing the file size/blocks via LSOM on the MDT, we
also need to store the atime/mtime/ctime on the MDT inodes.

Currently the atime is already lazily updated on the MDS (at
close time). In this patch, the final mtime/ctime are sent to the
MDS at close time and updated on the MDT inode, and make MDT-only
scanning workable.

Signed-off-by: Qian Yingjin <qian@ddn.com>
Change-Id: I4465281a03d70919c388cb241c16eebcb03e850f
Reviewed-on: https://review.whamcloud.com/36286
Tested-by: jenkins <devops@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Li Xi <lixi@ddn.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/uapi/linux/lustre/lustre_idl.h
lustre/mdd/mdd_object.c
lustre/mdt/mdt_open.c
lustre/tests/sanityn.sh

index 0cca401..db941b2 100644 (file)
@@ -1963,6 +1963,7 @@ enum mds_op_bias {
        MDS_CLOSE_LAYOUT_SPLIT  = 1 << 17,
        MDS_TRUNC_KEEP_LEASE    = 1 << 18,
        MDS_PCC_ATTACH          = 1 << 19,
+       MDS_CLOSE_UPDATE_TIMES  = 1 << 20,
 };
 
 #define MDS_CLOSE_INTENT (MDS_HSM_RELEASE | MDS_CLOSE_LAYOUT_SWAP |         \
index 22355ab..0d83356 100644 (file)
@@ -680,11 +680,19 @@ static int mdd_fix_attr(const struct lu_env *env, struct mdd_object *obj,
                RETURN(rc);
        }
 
-       if (la->la_valid == LA_ATIME) {
-               /* This is an atime-only attribute update for close RPCs. */
-               if (la->la_atime < (oattr->la_atime +
+       if (flags & MDS_CLOSE_UPDATE_TIMES &&
+           la->la_valid & (LA_ATIME | LA_MTIME | LA_CTIME)) {
+               /* This is an atime/mtime/ctime attribute update for
+                * close RPCs.
+                */
+               if (la->la_valid & LA_ATIME &&
+                   la->la_atime <= (oattr->la_atime +
                                mdd_obj2mdd_dev(obj)->mdd_atime_diff))
                        la->la_valid &= ~LA_ATIME;
+               if (la->la_valid & LA_CTIME && la->la_ctime <= oattr->la_ctime)
+                       la->la_valid &= ~LA_CTIME;
+               if (la->la_valid & LA_MTIME && la->la_mtime <= oattr->la_mtime)
+                       la->la_valid &= ~LA_MTIME;
                RETURN(0);
        }
 
index c7cfc1a..b89abc9 100644 (file)
@@ -2389,15 +2389,17 @@ int mdt_mfd_close(struct mdt_thread_info *info, struct mdt_file_data *mfd)
        else if (open_flags & MDS_FMODE_EXEC)
                mdt_write_allow(o);
 
-        /* Update atime on close only. */
+       /* Update atime|mtime|ctime on close. */
        if ((open_flags & MDS_FMODE_EXEC || open_flags & MDS_FMODE_READ ||
             open_flags & MDS_FMODE_WRITE) && (ma->ma_valid & MA_INODE) &&
-           (ma->ma_attr.la_valid & LA_ATIME)) {
-                /* Set the atime only. */
-                ma->ma_valid = MA_INODE;
-                ma->ma_attr.la_valid = LA_ATIME;
-                rc = mo_attr_set(info->mti_env, next, ma);
-        }
+           (ma->ma_attr.la_valid & LA_ATIME ||
+            ma->ma_attr.la_valid & LA_MTIME ||
+            ma->ma_attr.la_valid & LA_CTIME)) {
+               ma->ma_valid = MA_INODE;
+               ma->ma_attr_flags |= MDS_CLOSE_UPDATE_TIMES;
+               ma->ma_attr.la_valid &= (LA_ATIME | LA_MTIME | LA_CTIME);
+               rc = mo_attr_set(info->mti_env, next, ma);
+       }
 
        /* If file data is modified, add the dirty flag. */
        if (ma->ma_attr_flags & MDS_DATA_MODIFIED)
index 736b742..f1d9b97 100755 (executable)
@@ -4793,6 +4793,101 @@ test_103() {
 }
 run_test 103 "Test size correctness with lockahead"
 
+get_stat_xtimes()
+{
+       local xtimes
+
+       xtimes=$(stat -c "%X %Y %Z" $DIR/$tfile)
+
+       echo ${xtimes[*]}
+}
+
+get_mdt_xtimes()
+{
+       local mdtdev=$1
+       local output
+       local xtimes
+
+       output=$(do_facet mds1 "$DEBUGFS -c -R 'stat ROOT/$tfile' $mdtdev")
+       ((xtimes[0]=$(awk -F ':' /atime/'{ print $2 }' <<< "$output")))
+       ((xtimes[1]=$(awk -F ':' /mtime/'{ print $2 }' <<< "$output")))
+       ((xtimes[2]=$(awk -F ':' /ctime/'{ print $2 }' <<< "$output")))
+
+       echo ${xtimes[*]}
+}
+
+check_mdt_xtimes()
+{
+       local mdtdev=$1
+       local xtimes=($(get_stat_xtimes))
+       local mdt_xtimes=($(get_mdt_xtimes $mdtdev))
+
+       echo "STAT a|m|ctime ${xtimes[*]}"
+       echo "MDT a|m|ctime ${xtimes[*]}"
+       [[ ${xtimes[0]} == ${mdt_xtimes[0]} ]] ||
+               error "$DIR/$tfile atime (${xtimes[0]}:${mdt_xtimes[0]}) diff"
+       [[ ${xtimes[1]} == ${mdt_xtimes[1]} ]] ||
+               error "$DIR/$tfile mtime (${xtimes[1]}:${mdt_xtimes[1]}) diff"
+       [[ ${xtimes[2]} == ${mdt_xtimes[2]} ]] ||
+               error "$DIR/$tfile ctime (${xtimes[2]}:${mdt_xtimes[2]}) diff"
+}
+
+test_104() {
+       [ "$mds1_FSTYPE" == "ldiskfs" ] || skip_env "ldiskfs only test"
+
+       local pid
+       local mdtdev=$(mdsdevname ${SINGLEMDS//mds/})
+       local atime_diff=$(do_facet $SINGLEMDS \
+               lctl get_param -n mdd.*MDT0000*.atime_diff)
+
+       do_facet $SINGLEMDS \
+               lctl set_param -n mdd.*MDT0000*.atime_diff=0
+
+       stack_trap "do_facet $SINGLEMDS \
+               lctl set_param -n mdd.*MDT0000*.atime_diff=$atime_diff" EXIT
+
+       dd if=/dev/zero of=$DIR/$tfile bs=1k count=1 conv=notrunc
+       check_mdt_xtimes $mdtdev
+       sleep 2
+
+       dd if=/dev/zero of=$DIR/$tfile bs=1k count=1 conv=notrunc
+       check_mdt_xtimes $mdtdev
+       sleep 2
+       $MULTIOP $DIR2/$tfile Oz8192w8192_c &
+       pid=$!
+       sleep 2
+       dd if=/dev/zero of=$DIR/$tfile bs=1k count=1 conv=notrunc
+       sleep 2
+       kill -USR1 $pid && wait $pid || error "multiop failure"
+       check_mdt_xtimes $mdtdev
+
+       local xtimes
+       local mdt_xtimes
+
+       # Verify mtime/ctime is NOT upated on MDS when there is no modification
+       # on the client side
+       xtimes=($(get_stat_xtimes))
+       $MULTIOP $DIR/$tfile O_c &
+       pid=$!
+       sleep 2
+       kill -USR1 $pid && wait $pid || error "multiop failure"
+       mdt_xtimes=($(get_mdt_xtimes $mdtdev))
+       [[ ${xtimes[1]} == ${mdt_xtimes[1]} ]] ||
+               error "$DIR/$tfile mtime (${xtimes[1]}:${mdt_xtimes[1]}) diff"
+       [[ ${xtimes[2]} == ${mdt_xtimes[2]} ]] ||
+               error "$DIR/$tfile ctime (${xtimes[2]}:${mdt_xtimes[2]}) diff"
+       check_mdt_xtimes $mdtdev
+
+       sleep 2
+       # Change ctime via chmod
+       $MULTIOP $DIR/$tfile o_tc &
+       pid=$!
+       sleep 2
+       kill -USR1 $pid && wait $pid || error "multiop failure"
+       check_mdt_xtimes $mdtdev
+}
+run_test 104 "Verify that MDS stores atime/mtime/ctime during close"
+
 log "cleanup: ======================================================"
 
 # kill and wait in each test only guarentee script finish, but command in script