Whamcloud - gitweb
LU-8041 mdd: increasing only atime update on close 32/19932/3
authorNiu Yawei <yawei.niu@intel.com>
Tue, 3 May 2016 07:18:17 +0000 (03:18 -0400)
committerOleg Drokin <oleg.drokin@intel.com>
Wed, 11 May 2016 16:37:34 +0000 (16:37 +0000)
The atime update on close should be increasing only, otherwise,
the atime could be overwritten by stale client's atime.

This patch also changed client to clear out the ATTR_ATIME
flag fro close RPC when atime == 0, so that patch client won't
overwrite the unpatched server with 0 atime.

A test case sanity 39p is added to verify that close won't
overwrite atime with zero, and sanity 39l is adjusted as well.

Signed-off-by: Niu Yawei <yawei.niu@intel.com>
Change-Id: I40d1103ddfea184d82170a6795f89ce303a5c14e
Reviewed-on: http://review.whamcloud.com/19932
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Tested-by: Jenkins
Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
lustre/mdc/mdc_lib.c
lustre/mdd/mdd_object.c
lustre/tests/sanity.sh

index 6f79627..62e1cf9 100644 (file)
@@ -486,13 +486,25 @@ void mdc_getattr_pack(struct ptlrpc_request *req, __u64 valid, __u32 flags,
 
 void mdc_close_pack(struct ptlrpc_request *req, struct md_op_data *op_data)
 {
-        struct mdt_ioepoch *epoch;
-        struct mdt_rec_setattr *rec;
+       struct mdt_ioepoch *epoch;
+       struct mdt_rec_setattr *rec;
 
-        epoch = req_capsule_client_get(&req->rq_pill, &RMF_MDT_EPOCH);
-        rec = req_capsule_client_get(&req->rq_pill, &RMF_REC_REINT);
+       epoch = req_capsule_client_get(&req->rq_pill, &RMF_MDT_EPOCH);
+       rec = req_capsule_client_get(&req->rq_pill, &RMF_REC_REINT);
 
-        mdc_setattr_pack_rec(rec, op_data);
-        mdc_ioepoch_pack(epoch, op_data);
+       mdc_setattr_pack_rec(rec, op_data);
+       /*
+        * The client will zero out local timestamps when losing the IBITS lock
+        * so any new RPC timestamps will update the client inode's timestamps.
+        * There was a defect on the server side which allowed the atime to be
+        * overwritten by a zeroed-out atime packed into the close RPC.
+        *
+        * Proactively clear the MDS_ATTR_ATIME flag in the RPC in this case
+        * to avoid zeroing the atime on old unpatched servers.  See LU-8041.
+        */
+       if (rec->sa_atime == 0)
+               rec->sa_valid &= ~MDS_ATTR_ATIME;
+
+       mdc_ioepoch_pack(epoch, op_data);
        mdc_intent_close_pack(req, op_data);
 }
index 58d51b7..4ad7174 100644 (file)
@@ -475,9 +475,8 @@ static int mdd_fix_attr(const struct lu_env *env, struct mdd_object *obj,
        }
 
        if (la->la_valid == LA_ATIME) {
-               /* This is atime only set for read atime update on close. */
-               if (la->la_atime >= oattr->la_atime &&
-                   la->la_atime < (oattr->la_atime +
+               /* This is an atime-only attribute update for close RPCs. */
+               if (la->la_atime < (oattr->la_atime +
                                mdd_obj2mdd_dev(obj)->mdd_atime_diff))
                        la->la_valid &= ~LA_ATIME;
                RETURN(0);
index f52a1cc..2174b5d 100644 (file)
@@ -3334,29 +3334,27 @@ test_39l() {
        # test setting directory atime to future
        touch -a -d @$TEST_39_ATIME $DIR/$tdir
        local atime=$(stat -c %X $DIR/$tdir)
-       [ "$atime" = $TEST_39_ATIME ] || \
+       [ "$atime" = $TEST_39_ATIME ] ||
                error "atime is not set to future: $atime, $TEST_39_ATIME"
 
        # test setting directory atime from future to now
-       local d1=$(date +%s)
-       ls $DIR/$tdir
-       local d2=$(date +%s)
+       local now=$(date +%s)
+       touch -a -d @$now $DIR/$tdir
 
-       cancel_lru_locks mdc
        atime=$(stat -c %X $DIR/$tdir)
-       [ "$atime" -ge "$d1" -a "$atime" -le "$d2" ] || \
-               error "atime is not updated from future: $atime, $d1<atime<$d2"
+       [ "$atime" -eq "$now"  ] ||
+               error "atime is not updated from future: $atime, $now"
 
        do_facet $SINGLEMDS lctl set_param -n mdd.*MDT0000*.atime_diff=2
        sleep 3
 
        # test setting directory atime when now > dir atime + atime_diff
-       d1=$(date +%s)
+       local d1=$(date +%s)
        ls $DIR/$tdir
-       d2=$(date +%s)
+       local d2=$(date +%s)
        cancel_lru_locks mdc
        atime=$(stat -c %X $DIR/$tdir)
-       [ "$atime" -ge "$d1" -a "$atime" -le "$d2" ] || \
+       [ "$atime" -ge "$d1" -a "$atime" -le "$d2" ] ||
                error "atime is not updated  : $atime, should be $d2"
 
        do_facet $SINGLEMDS lctl set_param -n mdd.*MDT0000*.atime_diff=60
@@ -3366,7 +3364,7 @@ test_39l() {
        ls $DIR/$tdir
        cancel_lru_locks mdc
        atime=$(stat -c %X $DIR/$tdir)
-       [ "$atime" -ge "$d1" -a "$atime" -le "$d2" ] || \
+       [ "$atime" -ge "$d1" -a "$atime" -le "$d2" ] ||
                error "atime is updated to $atime, should remain $d1<atime<$d2"
 
        do_facet $SINGLEMDS \
@@ -3470,6 +3468,18 @@ test_39p() {
 run_test 39p "remote directory cached attributes updated after create ========"
 
 
+test_39p() { # LU-8041
+       local testdir=$DIR/$tdir
+       mkdir -p $testdir
+       multiop_bg_pause $testdir D_c || error "multiop failed"
+       local multipid=$!
+       cancel_lru_locks mdc
+       kill -USR1 $multipid
+       local atime=$(stat -c %X $testdir)
+       [ "$atime" -ne 0 ] || error "atime is zero"
+}
+run_test 39p "close won't zero out atime"
+
 test_40() {
        dd if=/dev/zero of=$DIR/$tfile bs=4096 count=1
        $RUNAS $OPENFILE -f O_WRONLY:O_TRUNC $DIR/$tfile &&