From bcb954c1403fb1c0fed2ae1d4ed817e59a93a0b7 Mon Sep 17 00:00:00 2001 From: Vitaly Fertman Date: Tue, 19 Mar 2024 00:33:25 +0300 Subject: [PATCH] LU-13374 mdd: fix close time update race with set-in-past Do not update mtime on close if ctime is not increased. Save the time when atime was last changed, in case this is set-in-past, to not lose it on a later LSOM update on close. HPE-bug-id: LUS-12186 Fixes: d2f7cb7934a0 ("LU-12026 mdt: MDS stores atime|mtime|ctime") Signed-off-by: Vitaly Fertman Change-Id: I070578a30f9bf548eec18a34ba6a06f1cb16909e Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/54450 Reviewed-by: Andreas Dilger Reviewed-by: Nikitas Angelinas Reviewed-by: Oleg Drokin Tested-by: jenkins Tested-by: Maloo --- lustre/mdd/mdd_internal.h | 1 + lustre/mdd/mdd_object.c | 26 +++++++++++++++++--------- lustre/tests/sanityn.sh | 25 +++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/lustre/mdd/mdd_internal.h b/lustre/mdd/mdd_internal.h index e8e00f3..3e61fda 100644 --- a/lustre/mdd/mdd_internal.h +++ b/lustre/mdd/mdd_internal.h @@ -185,6 +185,7 @@ struct mdd_object { u32 mod_count; u32 mod_valid; ktime_t mod_cltime; + s64 mod_atime_set; unsigned long mod_flags; struct list_head mod_users; /**< unique user opens */ }; diff --git a/lustre/mdd/mdd_object.c b/lustre/mdd/mdd_object.c index f9f9147..130b4cb 100644 --- a/lustre/mdd/mdd_object.c +++ b/lustre/mdd/mdd_object.c @@ -721,20 +721,26 @@ static int mdd_fix_attr(const struct lu_env *env, struct mdd_object *obj, RETURN(rc); } - 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 (flags & MDS_CLOSE_UPDATE_TIMES) { + /* This is an atime/mtime/ctime update for close RPCs. */ + if (!(la->la_valid & LA_CTIME) || + (la->la_ctime <= oattr->la_ctime)) + la->la_valid &= ~(LA_MTIME | LA_CTIME); + if (la->la_valid & LA_ATIME && - la->la_atime <= (oattr->la_atime + - mdd_obj2mdd_dev(obj)->mdd_atime_diff)) + (la->la_atime <= obj->mod_atime_set || + 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; + else + obj->mod_atime_set = la->la_atime; if (la->la_valid & LA_MTIME && la->la_mtime <= oattr->la_mtime) la->la_valid &= ~LA_MTIME; RETURN(0); + } else if ((la->la_valid & LA_ATIME) && (la->la_valid & LA_CTIME)) { + /* save the time when atime was changed, in case this is + * set-in-past, to not lose it later on close. */ + obj->mod_atime_set = la->la_ctime; } /* Check if flags change. */ @@ -1273,7 +1279,9 @@ int mdd_attr_set(const struct lu_env *env, struct md_object *obj, RETURN(rc); *la_copy = ma->ma_attr; + mdd_write_lock(env, mdd_obj, DT_TGT_CHILD); rc = mdd_fix_attr(env, mdd_obj, attr, la_copy, ma); + mdd_write_unlock(env, mdd_obj); if (rc) RETURN(rc); diff --git a/lustre/tests/sanityn.sh b/lustre/tests/sanityn.sh index 1efffbc..1ff7369 100755 --- a/lustre/tests/sanityn.sh +++ b/lustre/tests/sanityn.sh @@ -1086,6 +1086,31 @@ test_26b() { } run_test 26b "sync mtime between ost and mds" +test_26c() { + (( $MDS1_VERSION >= $(version_code 2.15.61) )) || + skip "Need MDS version at least 2.15.61" + + multiop_bg_pause $DIR1/$tfile O_c || error "multiop failed" + MULTIPID=$! + touch -am -d @978261179 $DIR2/$tfile + kill -USR1 $MULTIPID + wait $MULTIPID || error "wait for PID $MULTIPID failed" + sleep 1 + + echo + stat $DIR/$tfile + local times="$(stat -c"%X %Y" $DIR/$tfile)" + [[ "$times" == "978261179 978261179" ]] || + error "[am]times are not set in past on $DIR: $times" + echo + stat $DIR2/$tfile + local times="$(stat -c"%X %Y" $DIR2/$tfile)" + [[ "$times" == "978261179 978261179" ]] || + error "[am]times are not set in past on $DIR2: $times" + echo +} +run_test 26c "set-in-past on open file is not lost on close" + test_27() { cancel_lru_locks $OSC lctl clear -- 1.8.3.1