From b9d7f8e07ad68a51b4fcc09babe48a68fcbd6041 Mon Sep 17 00:00:00 2001 From: Nikitas Angelinas Date: Mon, 22 Jun 2020 13:40:38 -0700 Subject: [PATCH] LU-13151 mdt: add parent FID to Changelog recordss Use the link EA to add the parent FID to ChangeLog records, including MTIME, TRUNC, and SATTR. Some tools that maintain copies of filesystem metadata in an external database monitor changelogs for changes to the filesystem, in order to determine files that need to be rescanned. This can result in a large number of small updates to the external database that can reduce the tool's ingest performance. It might be beneficial to instead track and scan complete directories that contain modified files and update the external database using bulk operations. Adding the parent FID to MTIME changelogs allows to more efficiently determine the parent directories for some types of file data modifications, by issuing OBD_IOC_FID2PATH once for each parent FID, instead of once for each file FID. Signed-off-by: Nikitas Angelinas Cray-bug-id: LUS-7986 Change-Id: I0c88271e706ef8202910e9461e5ae9f6dcbe0bdd Reviewed-on: https://review.whamcloud.com/37264 Tested-by: jenkins Reviewed-by: Andreas Dilger Tested-by: Maloo Reviewed-by: Nathan Rutman Reviewed-by: Sebastien Buisson Reviewed-by: Oleg Drokin --- lustre/mdd/mdd_dir.c | 3 ++- lustre/mdd/mdd_internal.h | 3 ++- lustre/mdd/mdd_object.c | 54 ++++++++++++++++++++++++--------------- lustre/mdt/mdt_open.c | 7 +++++ lustre/mdt/mdt_reint.c | 9 ++++++- lustre/tests/sanity.sh | 65 +++++++++++++++++++++++++++++++++++++++++++++++ lustre/utils/lfs.c | 6 +++-- 7 files changed, 122 insertions(+), 25 deletions(-) diff --git a/lustre/mdd/mdd_dir.c b/lustre/mdd/mdd_dir.c index 76b54e3..134982d 100644 --- a/lustre/mdd/mdd_dir.c +++ b/lustre/mdd/mdd_dir.c @@ -1937,7 +1937,8 @@ static int mdd_create_data(const struct lu_env *env, if (rc) GOTO(stop, rc); - rc = mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, son, handle); + rc = mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, son, handle, + NULL); stop: rc = mdd_trans_stop(env, mdd, rc, handle); diff --git a/lustre/mdd/mdd_internal.h b/lustre/mdd/mdd_internal.h index 1f590af..9081de1 100644 --- a/lustre/mdd/mdd_internal.h +++ b/lustre/mdd/mdd_internal.h @@ -353,7 +353,8 @@ int mdd_changelog_data_store(const struct lu_env *env, struct mdd_device *mdd, enum changelog_rec_type type, enum changelog_rec_flags clf_flags, struct mdd_object *mdd_obj, - struct thandle *handle); + struct thandle *handle, + const struct lu_fid *pfid); int mdd_changelog_ns_store(const struct lu_env *env, struct mdd_device *mdd, enum changelog_rec_type type, enum changelog_rec_flags clf_flags, diff --git a/lustre/mdd/mdd_object.c b/lustre/mdd/mdd_object.c index d30599a..6c6afbf 100644 --- a/lustre/mdd/mdd_object.c +++ b/lustre/mdd/mdd_object.c @@ -72,6 +72,7 @@ static int mdd_changelog_data_store_by_fid(const struct lu_env *env, enum changelog_rec_type type, enum changelog_rec_flags clf_flags, const struct lu_fid *fid, + const struct lu_fid *pfid, const char *xattr_name, struct thandle *handle); @@ -449,7 +450,7 @@ static int mdd_xattr_get(const struct lu_env *env, rc2 = mdd_changelog_data_store_by_fid(env, mdd, CL_GETXATTR, 0, mdd_object_fid(mdd_obj), - name, handle); + NULL, name, handle); stop: rc2 = mdd_trans_stop(env, mdd, rc2, handle); @@ -884,6 +885,7 @@ static int mdd_changelog_data_store_by_fid(const struct lu_env *env, enum changelog_rec_type type, enum changelog_rec_flags clf_flags, const struct lu_fid *fid, + const struct lu_fid *pfid, const char *xattr_name, struct thandle *handle) { @@ -919,6 +921,8 @@ static int mdd_changelog_data_store_by_fid(const struct lu_env *env, rec->cr.cr_flags = clf_flags; rec->cr.cr_type = (__u32)type; rec->cr.cr_tfid = *fid; + if (pfid) + rec->cr.cr_pfid = *pfid; rec->cr.cr_namelen = 0; if (clf_flags & CLF_JOBID) @@ -950,11 +954,13 @@ static int mdd_changelog_data_store_by_fid(const struct lu_env *env, * want the change to commit without the log entry. * \param mdd_obj - mdd_object of change * \param handle - transaction handle + * \param pfid - parent FID for CL_MTIME changelogs */ int mdd_changelog_data_store(const struct lu_env *env, struct mdd_device *mdd, enum changelog_rec_type type, enum changelog_rec_flags clf_flags, - struct mdd_object *mdd_obj, struct thandle *handle) + struct mdd_object *mdd_obj, struct thandle *handle, + const struct lu_fid *pfid) { int rc; @@ -976,7 +982,7 @@ int mdd_changelog_data_store(const struct lu_env *env, struct mdd_device *mdd, } rc = mdd_changelog_data_store_by_fid(env, mdd, type, clf_flags, - mdd_object_fid(mdd_obj), + mdd_object_fid(mdd_obj), pfid, NULL, handle); if (rc == 0) mdd_obj->mod_cltime = ktime_get(); @@ -1013,7 +1019,7 @@ int mdd_changelog_data_store_xattr(const struct lu_env *env, } rc = mdd_changelog_data_store_by_fid(env, mdd, type, clf_flags, - mdd_object_fid(mdd_obj), + mdd_object_fid(mdd_obj), NULL, xattr_name, handle); if (rc == 0) mdd_obj->mod_cltime = ktime_get(); @@ -1052,7 +1058,7 @@ static int mdd_changelog(const struct lu_env *env, enum changelog_rec_type type, GOTO(stop, rc); rc = mdd_changelog_data_store_by_fid(env, mdd, type, clf_flags, - fid, NULL, handle); + fid, NULL, NULL, handle); stop: rc = mdd_trans_stop(env, mdd, rc, handle); @@ -1073,7 +1079,7 @@ stop: * atime and ctime are independent.) */ static int mdd_attr_set_changelog(const struct lu_env *env, struct md_object *obj, struct thandle *handle, - __u64 valid) + const struct lu_fid *pfid, __u64 valid) { struct mdd_device *mdd = mdo2mdd(obj); int bits, type = 0; @@ -1093,8 +1099,8 @@ static int mdd_attr_set_changelog(const struct lu_env *env, type = __ffs(bits); /* XXX: we only store the low CLF_FLAGMASK bits of la_valid */ - return mdd_changelog_data_store(env, mdd, type, valid, - md2mdd_obj(obj), handle); + return mdd_changelog_data_store(env, mdd, type, valid, md2mdd_obj(obj), + handle, pfid); } static int mdd_declare_attr_set(const struct lu_env *env, @@ -1320,7 +1326,7 @@ int mdd_attr_set(const struct lu_env *env, struct md_object *obj, out: if (rc == 0) - rc = mdd_attr_set_changelog(env, obj, handle, + rc = mdd_attr_set_changelog(env, obj, handle, &ma->ma_pfid, la_copy->la_valid); if (handle != NULL) @@ -1601,8 +1607,10 @@ static int mdd_xattr_merge(const struct lu_env *env, struct md_object *md_obj, if (rc) /* wtf? */ GOTO(out_restore, rc); - (void)mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, obj, handle); - (void)mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, vic, handle); + (void)mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, obj, handle, + NULL); + (void)mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, vic, handle, + NULL); EXIT; out_restore: @@ -1834,11 +1842,13 @@ static int mdd_xattr_split(const struct lu_env *env, struct md_object *md_obj, if (rc) GOTO(out_restore, rc); - rc = mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, obj, handle); + rc = mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, obj, handle, + NULL); if (rc) GOTO(out, rc); - rc = mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, vic, handle); + rc = mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, vic, handle, + NULL); if (rc) GOTO(out, rc); EXIT; @@ -2135,7 +2145,7 @@ static int mdd_xattr_hsm_replace(const struct lu_env *env, /* Add a changelog record for release. */ hsm_set_cl_event(&clf_flags, HE_RELEASE); rc = mdd_changelog_data_store(env, mdo2mdd(&o->mod_obj), CL_HSM, - clf_flags, o, handle); + clf_flags, o, handle, NULL); RETURN(rc); } @@ -2571,11 +2581,13 @@ static int mdd_swap_layouts(const struct lu_env *env, struct md_object *obj1, GOTO(out_restore, rc); /* Issue one changelog record per file */ - rc = mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, fst_o, handle); + rc = mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, fst_o, handle, + NULL); if (rc) GOTO(stop, rc); - rc = mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, snd_o, handle); + rc = mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, snd_o, handle, + NULL); if (rc) GOTO(stop, rc); EXIT; @@ -2691,7 +2703,8 @@ mdd_layout_instantiate_component(const struct lu_env *env, if (rc) RETURN(rc); - rc = mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, obj, handle); + rc = mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, obj, handle, + NULL); RETURN(rc); } @@ -2775,7 +2788,7 @@ mdd_layout_update_rdonly(const struct lu_env *env, struct mdd_object *obj, if (rc) GOTO(out, rc); - rc = mdd_changelog_data_store(env, mdd, CL_FLRW, 0, obj, handle); + rc = mdd_changelog_data_store(env, mdd, CL_FLRW, 0, obj, handle, NULL); if (rc) GOTO(out, rc); @@ -2925,7 +2938,8 @@ mdd_object_update_sync_pending(const struct lu_env *env, struct mdd_object *obj, GOTO(out, rc); } - rc = mdd_changelog_data_store(env, mdd, CL_RESYNC, 0, obj, handle); + rc = mdd_changelog_data_store(env, mdd, CL_RESYNC, 0, obj, handle, + NULL); if (rc) GOTO(out, rc); EXIT; @@ -3407,7 +3421,7 @@ out: /* FYI, only the bottom 32 bits of open_flags are recorded */ mdd_changelog_data_store(env, mdd, CL_CLOSE, open_flags, - mdd_obj, handle); + mdd_obj, handle, NULL); } stop: diff --git a/lustre/mdt/mdt_open.c b/lustre/mdt/mdt_open.c index 9f10fc6..b2c7536 100644 --- a/lustre/mdt/mdt_open.c +++ b/lustre/mdt/mdt_open.c @@ -2393,6 +2393,13 @@ int mdt_mfd_close(struct mdt_thread_info *info, struct mdt_file_data *mfd) ma->ma_valid = MA_INODE; ma->ma_attr_flags |= MDS_CLOSE_UPDATE_TIMES; ma->ma_attr.la_valid &= (LA_ATIME | LA_MTIME | LA_CTIME); + + if (ma->ma_attr.la_valid & LA_MTIME) { + rc = mdt_attr_get_pfid(info, o, &ma->ma_pfid); + if (!rc) + ma->ma_valid |= MA_PFID; + } + rc = mo_attr_set(info->mti_env, next, ma); } diff --git a/lustre/mdt/mdt_reint.c b/lustre/mdt/mdt_reint.c index 5d37de3..ad225ae 100644 --- a/lustre/mdt/mdt_reint.c +++ b/lustre/mdt/mdt_reint.c @@ -878,10 +878,17 @@ static int mdt_reint_setattr(struct mdt_thread_info *info, /* MDT supports FMD for regular files due to Data-on-MDT */ if (S_ISREG(lu_object_attr(&mo->mot_obj)) && - ma->ma_attr.la_valid & (LA_ATIME | LA_MTIME | LA_CTIME)) + ma->ma_attr.la_valid & (LA_ATIME | LA_MTIME | LA_CTIME)) { tgt_fmd_update(info->mti_exp, mdt_object_fid(mo), req->rq_xid); + if (ma->ma_attr.la_valid & LA_MTIME) { + rc = mdt_attr_get_pfid(info, mo, &ma->ma_pfid); + if (!rc) + ma->ma_valid |= MA_PFID; + } + } + rc = mdt_attr_set(info, mo, ma); if (rc) GOTO(out_put, rc); diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index f50c83a..335c536 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -14981,6 +14981,71 @@ test_160k() { } run_test 160k "Verify that changelog records are not lost" +# Verifies that a file passed as a parameter has recently had an operation +# performed on it that has generated an MTIME changelog which contains the +# correct parent FID. As files might reside on a different MDT from the +# parent directory in DNE configurations, the FIDs are translated to paths +# before being compared, which should be identical +compare_mtime_changelog() { + local file="${1}" + local mdtidx + local mtime + local cl_fid + local pdir + local dir + + mdtidx=$($LFS getstripe --mdt-index $file) + mdtidx=$(printf "%04x" $mdtidx) + + # Obtain the parent FID from the MTIME changelog + mtime=$($LFS changelog $FSNAME-MDT$mdtidx | tail -n 1 | grep MTIME) + [ -z "$mtime" ] && error "MTIME changelog not recorded" + + cl_fid=$(sed -e 's/.* p=//' -e 's/ .*//' <<<$mtime) + [ -z "$cl_fid" ] && error "parent FID not present" + + # Verify that the path for the parent FID is the same as the path for + # the test directory + pdir=$($LFS fid2path $MOUNT "$cl_fid") + + dir=$(dirname $1) + + [[ "${pdir%/}" == "$dir" ]] || + error "MTIME changelog parent FID is wrong, expected $dir, got $pdir" +} + +test_160l() { + [ $PARALLEL == "yes" ] && skip "skip parallel run" + + remote_mds_nodsh && skip "remote MDS with nodsh" + [[ $MDS1_VERSION -ge $(version_code 2.13.55) ]] || + skip "Need MDS version at least 2.13.55" + + local cl_user + + changelog_register || error "changelog_register failed" + cl_user="${CL_USERS[$SINGLEMDS]%% *}" + + changelog_users $SINGLEMDS | grep -q $cl_user || + error "User '$cl_user' not found in changelog_users" + + # Clear some types so that MTIME changelogs are generated + changelog_chmask "-CREAT" + changelog_chmask "-CLOSE" + + test_mkdir $DIR/$tdir || error "failed to mkdir $DIR/$tdir" + + # Test CL_MTIME during setattr + touch $DIR/$tdir/$tfile + compare_mtime_changelog $DIR/$tdir/$tfile + + # Test CL_MTIME during close + dd if=/dev/urandom of=$DIR/$tdir/${tfile}_2 bs=1M count=64 || + error "cannot create file $DIR/$tdir/${tfile}_2" + compare_mtime_changelog $DIR/$tdir/${tfile}_2 +} +run_test 160l "Verify that MTIME changelog records contain the parent FID" + test_161a() { [ $PARALLEL == "yes" ] && skip "skip parallel run" diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index 64d5f88..f3bbf0e 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -8110,9 +8110,11 @@ static int lfs_changelog(int argc, char **argv) } } + if (!fid_is_zero(&rec->cr_pfid)) + printf(" p="DFID, PFID(&rec->cr_pfid)); if (rec->cr_namelen) - printf(" p="DFID" %.*s", PFID(&rec->cr_pfid), - rec->cr_namelen, changelog_rec_name(rec)); + printf(" %.*s", rec->cr_namelen, + changelog_rec_name(rec)); if (rec->cr_flags & CLF_RENAME) { struct changelog_ext_rename *rnm = -- 1.8.3.1