Whamcloud - gitweb
LU-17309 llog: set timestamp on llog objects at creation time 91/56691/7
authorKeguang Xu <squalfof@gmail.com>
Tue, 15 Oct 2024 06:28:58 +0000 (14:28 +0800)
committerOleg Drokin <green@whamcloud.com>
Mon, 16 Dec 2024 08:16:40 +0000 (08:16 +0000)
To facilitate debugging, this commit introduces the storage of the
creation time (ctime) for llog objects upon creation. Additionally,
the modification time (mtime) will be updated when the catalog is
modified.

- For llog creation, la_ctime/mtime/atime are set within
 llog_osd_create().
- For update, there are 2 entries leading to the modification of
 llog: 1) direct usage over plain-log?, dt_attr_set() is added with
 la_mtime set in llog.c; 2) update through catalog, dt_attr_set() is
 added in llog_cat.c

Performance Considerations:
- Catalog modifications are infrequent, minimizing the performance
impact.
- Updating the mtime incurs no additional overhead when new records
are added to an llog file, as the new inode size/ blocks must be
written regardless.

Signed-off-by: Keguang Xu <squalfof@gmail.com>
Change-Id: I13c260cc576e35a811a9d33cacfdd0bdf8492962
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/56691
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Alexander Boyko <alexander.boyko@hpe.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/obdclass/llog.c
lustre/obdclass/llog_cat.c
lustre/obdclass/llog_osd.c
lustre/tests/sanity.sh

index f1a8a79..e59e723 100644 (file)
@@ -253,6 +253,8 @@ int llog_cancel_arr_rec(const struct lu_env *env, struct llog_handle *loghandle,
                if (rc < 0)
                        GOTO(out_trans, rc);
        }
+       if (llh->llh_flags & LLOG_F_IS_CAT)
+               dt_declare_attr_set(env, loghandle->lgh_obj, NULL, th);
 
        th->th_wait_submit = 1;
        rc = dt_trans_start_local(env, dt, th);
@@ -313,6 +315,13 @@ int llog_cancel_arr_rec(const struct lu_env *env, struct llog_handle *loghandle,
                rc = LLOG_DEL_PLAIN;
        }
 
+       /* update for catalog which doesn't happen very often */
+       if (llh->llh_flags & LLOG_F_IS_CAT) {
+               lgi->lgi_attr.la_valid = LA_MTIME;
+               lgi->lgi_attr.la_mtime = ktime_get_real_seconds();
+               dt_attr_set(env, loghandle->lgh_obj, &lgi->lgi_attr, th);
+       }
+
 out_unlock:
        if (rc < 0) {
                /* restore bitmap while holding a mutex */
@@ -1319,8 +1328,10 @@ int llog_write(const struct lu_env *env, struct llog_handle *loghandle,
 {
        struct dt_device        *dt;
        struct thandle          *th;
-       bool                    need_cookie;
-       int                     rc;
+       struct llog_thread_info *lgi = llog_info(env);
+       bool need_cookie;
+       bool update_attr;
+       int rc;
 
        ENTRY;
 
@@ -1341,6 +1352,17 @@ int llog_write(const struct lu_env *env, struct llog_handle *loghandle,
        if (rc)
                GOTO(out_trans, rc);
 
+       /*
+        * update mtime given 1) append mode, no overhead since inode
+        * size/block needs to be written anyway; 2) update for catalog
+        * since this doesn't happen very often
+        */
+       update_attr = (idx == LLOG_NEXT_IDX ||
+                       (loghandle->lgh_hdr &&
+                        loghandle->lgh_hdr->llh_flags & LLOG_F_IS_CAT));
+       if (update_attr)
+               dt_declare_attr_set(env, loghandle->lgh_obj, NULL, th);
+
        th->th_wait_submit = 1;
        rc = dt_trans_start_local(env, dt, th);
        if (rc)
@@ -1360,6 +1382,11 @@ int llog_write(const struct lu_env *env, struct llog_handle *loghandle,
        } else {
                rc = llog_write_rec(env, loghandle, rec, NULL, idx, th);
        }
+       if (rc == 0 && update_attr) {
+               lgi->lgi_attr.la_valid = LA_MTIME;
+               lgi->lgi_attr.la_mtime = ktime_get_real_seconds();
+               dt_attr_set(env, loghandle->lgh_obj, &lgi->lgi_attr, th);
+       }
 
        up_write(&loghandle->lgh_lock);
 out_trans:
index 334de1b..a0da211 100644 (file)
@@ -141,6 +141,7 @@ static int llog_cat_new_log(const struct lu_env *env,
                                            handle);
                if (rc != 0)
                        GOTO(out, rc);
+               dt_declare_attr_set(env, cathandle->lgh_obj, NULL, handle);
 
                rc = dt_trans_start_local(env, dt, handle);
                if (rc != 0)
@@ -176,6 +177,10 @@ static int llog_cat_new_log(const struct lu_env *env,
                            &loghandle->u.phd.phd_cookie, LLOG_NEXT_IDX, th);
        if (rc < 0)
                GOTO(out_destroy, rc);
+       /* update for catalog which doesn't happen very often */
+       lgi->lgi_attr.la_valid = LA_MTIME;
+       lgi->lgi_attr.la_mtime = ktime_get_real_seconds();
+       dt_attr_set(env, cathandle->lgh_obj, &lgi->lgi_attr, th);
 
        CDEBUG(D_OTHER, "new plain log "DFID".%u of catalog "DFID"\n",
               PLOGID(&loghandle->lgh_id), rec->lid_hdr.lrh_index,
@@ -343,6 +348,7 @@ start:
                lirec->lid_hdr.lrh_len = sizeof(*lirec);
                rc = llog_declare_write_rec(env, cathandle, &lirec->lid_hdr, -1,
                                            th);
+               dt_declare_attr_set(env, cathandle->lgh_obj, NULL, th);
        }
 
 out:
@@ -560,7 +566,8 @@ int llog_cat_add_rec(const struct lu_env *env, struct llog_handle *cathandle,
                     struct llog_rec_hdr *rec, struct llog_cookie *reccookie,
                     struct thandle *th)
 {
-        struct llog_handle *loghandle;
+       struct llog_handle *loghandle;
+       struct llog_thread_info *lgi = llog_info(env);
        int rc, retried = 0;
        ENTRY;
 
@@ -597,7 +604,13 @@ retry:
                 * actual cause here */
                if (rc == -ENOSPC && llog_is_full(loghandle))
                        rc = -ENOBUFS;
+       } else {
+               /* no overhead since inode size needs to be written anyway */
+               lgi->lgi_attr.la_valid = LA_MTIME;
+               lgi->lgi_attr.la_mtime = ktime_get_real_seconds();
+               dt_attr_set(env, loghandle->lgh_obj, &lgi->lgi_attr, th);
        }
+
        up_write(&loghandle->lgh_lock);
 
        if (rc == -ENOBUFS) {
@@ -640,6 +653,8 @@ start:
                        RETURN(rc);
                goto start;
        }
+       dt_declare_attr_set(env, cathandle->u.chd.chd_current_log->lgh_obj,
+                           NULL, th);
 
 #if 0
        /*
index 76bd90d..9151cb4 100644 (file)
@@ -104,8 +104,10 @@ static int llog_osd_create_new_object(const struct lu_env *env,
 {
        struct llog_thread_info *lgi = llog_info(env);
 
-       lgi->lgi_attr.la_valid = LA_MODE;
+       lgi->lgi_attr.la_valid = LA_MODE | LA_CTIME | LA_MTIME | LA_ATIME;
        lgi->lgi_attr.la_mode = S_IFREG | S_IRUGO | S_IWUSR;
+       lgi->lgi_attr.la_ctime = lgi->lgi_attr.la_mtime =
+               lgi->lgi_attr.la_atime = ktime_get_real_seconds();
        lgi->lgi_dof.dof_type = dt_mode_to_dft(S_IFREG);
 
        return local_object_create(env, los, o, &lgi->lgi_attr,
@@ -1822,9 +1824,12 @@ static int llog_osd_create(const struct lu_env *env, struct llog_handle *res,
        if (res->lgh_ctxt->loc_flags & LLOG_CTXT_FLAG_NORMAL_FID) {
                struct llog_thread_info *lgi = llog_info(env);
 
-               lgi->lgi_attr.la_valid = LA_MODE | LA_SIZE | LA_TYPE;
+               lgi->lgi_attr.la_valid = LA_MODE | LA_SIZE | LA_TYPE |
+                       LA_CTIME | LA_MTIME | LA_ATIME;
                lgi->lgi_attr.la_size = 0;
                lgi->lgi_attr.la_mode = S_IFREG | S_IRUGO | S_IWUSR;
+               lgi->lgi_attr.la_ctime = lgi->lgi_attr.la_mtime =
+                       lgi->lgi_attr.la_atime = ktime_get_real_seconds();
                lgi->lgi_dof.dof_type = dt_mode_to_dft(S_IFREG);
 
                dt_write_lock(env, o, 0);
index c6a054d..7291756 100755 (executable)
@@ -34163,6 +34163,61 @@ test_907() {
 }
 run_test 907 "write rpc error during unlink"
 
+test_908a() {
+       (( MDS1_VERSION >= $(version_code 2.16.0) )) ||
+               skip "need MDS >= 2.16.0 for llog timestamps"
+       [[ "$mds1_FSTYPE" == ldiskfs ]] || skip "ldiskfs only test"
+
+       local dev=$(mdsdevname 1)
+       local cmd="debugfs -c -R \\\"stat CONFIGS/params\\\" $dev"
+
+       # ctime_mds value is in hex
+       local base_time=`date -d "24 hours ago" +%s`
+       local ctime_mds=$(do_facet mds1 "$cmd" |&
+                         awk -F'[: ]' '/ctime:/ { print $4 }')
+       ctime_mds=$((ctime_mds))
+       echo "ctime_mds=$ctime_mds, base_time=$base_time"
+       (( "$ctime_mds" > "$base_time" )) ||
+               error "invalid ctime $ctime_mds <= $base_time"
+}
+run_test 908a "llog created with valid ctime"
+
+test_908b() {
+       (( MDS1_VERSION >= $(version_code 2.16.0) )) ||
+               skip "need MDS >= 2.16.0 for llog timestamps"
+       [[ "$mds1_FSTYPE" == ldiskfs ]] || skip "ldiskfs only test"
+
+       local dev=$(mdsdevname 1)
+
+       changelog_register || error "cannot register changelog user"
+       # set changelog_mask to ALL
+       changelog_chmask "ALL"
+       changelog_clear
+
+       for ((i=0; i<100; i++)); do
+               echo "$i" > $DIR/$tfile${i}
+               rm $DIR/$tfile${i}
+       done
+       sleep 5
+
+       changelog_deregister || error "changelog_deregister failed"
+
+       local cmd="debugfs -c -R \\\"stat changelog_catalog\\\" $dev"
+
+       # ctime_mdt value is in hex
+       local ctime_mds=$(do_facet mds1 "$cmd" |&
+                         awk -F'[: ]' '/ctime:/ { print $4 }')
+       ctime_mds=$((ctime_mds))
+       local mtime_mds=$(do_facet mds1 "$cmd" |&
+                         awk -F'[: ]' '/mtime:/ { print $4 }')
+       mtime_mds=$((mtime_mds))
+
+       echo "ctime_mds=$ctime_mds, mtime_mds=$mtime_mds"
+       (( "$mtime_mds" > "$ctime_mds" )) ||
+               error "invalid mtime $mtime_mds <= $ctime_mds"
+}
+run_test 908b "changelog stores valid mtime"
+
 complete_test $SECONDS
 [ -f $EXT2_DEV ] && rm $EXT2_DEV || true
 check_and_cleanup_lustre