From 3db5b0e044a2b2c8c4e49b296e020446f44b2955 Mon Sep 17 00:00:00 2001 From: Alex Zhuravlev Date: Wed, 16 Mar 2022 12:10:38 +0300 Subject: [PATCH] LU-15645 obdclass: llog to handle gaps due to old errors an update llog can contaain gaps in index. this shouldn't block llog processing and recovery. actual gaps in transaction sequence should be catched by VBR. Lustre-change: https://review.whamcloud.com/46837 Lustre-commit: TBD (from b3de0d57bd0f7cd2e918aa9d3f08be1c69697b80) Signed-off-by: Alex Zhuravlev Change-Id: I11ec817e356f9658118c34706ef3a533e7faba83 Signed-off-by: Mikhail Pershin --- lustre/include/obd_support.h | 2 ++ lustre/obdclass/llog.c | 26 +++++++++----------------- lustre/obdclass/llog_osd.c | 2 ++ lustre/osp/osp_trans.c | 1 + lustre/target/update_trans.c | 3 +++ lustre/tests/replay-dual.sh | 33 +++++++++++++++++++++++++++++++++ 6 files changed, 50 insertions(+), 17 deletions(-) diff --git a/lustre/include/obd_support.h b/lustre/include/obd_support.h index 9867c8d..268f62a 100644 --- a/lustre/include/obd_support.h +++ b/lustre/include/obd_support.h @@ -493,6 +493,7 @@ extern char obd_jobid_var[]; #define OBD_FAIL_TGT_RECOVERY_REQ_RACE 0x721 #define OBD_FAIL_TGT_REPLY_DATA_RACE 0x722 #define OBD_FAIL_TGT_NO_GRANT 0x725 +#define OBD_FAIL_TGT_TXN_NO_CANCEL 0x726 #define OBD_FAIL_MDC_REVALIDATE_PAUSE 0x800 #define OBD_FAIL_MDC_ENQUEUE_PAUSE 0x801 @@ -563,6 +564,7 @@ extern char obd_jobid_var[]; #define OBD_FAIL_LLOG_PURGE_DELAY 0x1318 #define OBD_FAIL_CATLIST 0x131b #define OBD_FAIL_LLOG_PAUSE_AFTER_PAD 0x131c +#define OBD_FAIL_LLOG_ADD_GAP 0x131d #define OBD_FAIL_LLITE 0x1400 #define OBD_FAIL_LLITE_FAULT_TRUNC_RACE 0x1401 diff --git a/lustre/obdclass/llog.c b/lustre/obdclass/llog.c index 010b5f3..2f224d6 100644 --- a/lustre/obdclass/llog.c +++ b/lustre/obdclass/llog.c @@ -663,23 +663,15 @@ repeat: continue; } - if (rec->lrh_index != index) { - /* - * the last time we couldn't parse the block due - * to corruption, thus has no idea about the - * next index, take it from the block, once. - */ - if (refresh_idx) { - refresh_idx = false; - index = rec->lrh_index; - } else { - CERROR("%s: "DFID" Invalid record: index" - " %u but expected %u\n", - loghandle2name(loghandle), - PFID(&loghandle->lgh_id.lgl_oi.oi_fid), - rec->lrh_index, index); - GOTO(out, rc = -ERANGE); - } + if (rec->lrh_index > index) { + /* the record itself looks good, but we met a + * gap which can be result of old bugs, just + * keep going */ + CERROR("%s: "DFID" index %u, expected %u\n", + loghandle2name(loghandle), + PFID(&loghandle->lgh_id.lgl_oi.oi_fid), + rec->lrh_index, index); + index = rec->lrh_index; } CDEBUG(D_OTHER, diff --git a/lustre/obdclass/llog_osd.c b/lustre/obdclass/llog_osd.c index 4525e44..5917337 100644 --- a/lustre/obdclass/llog_osd.c +++ b/lustre/obdclass/llog_osd.c @@ -604,6 +604,8 @@ static int llog_osd_write_rec(const struct lu_env *env, down_write(&loghandle->lgh_last_sem); /* increment the last_idx along with llh_tail index, they should * be equal for a llog lifetime */ + if (OBD_FAIL_CHECK(OBD_FAIL_LLOG_ADD_GAP) && --cfs_fail_val == 0) + loghandle->lgh_last_idx++; loghandle->lgh_last_idx++; index = loghandle->lgh_last_idx; LLOG_HDR_TAIL(llh)->lrt_index = index; diff --git a/lustre/osp/osp_trans.c b/lustre/osp/osp_trans.c index d08beb4..803cacb 100644 --- a/lustre/osp/osp_trans.c +++ b/lustre/osp/osp_trans.c @@ -1112,6 +1112,7 @@ static int osp_send_update_req(const struct lu_env *env, ENTRY; LASSERT(oth != NULL); + LASSERT(osp->opd_obd); if (ou && ou->ou_generation != our->our_generation) { const struct lnet_process_id *peer = diff --git a/lustre/target/update_trans.c b/lustre/target/update_trans.c index 40def43..5183fe5 100644 --- a/lustre/target/update_trans.c +++ b/lustre/target/update_trans.c @@ -1296,6 +1296,9 @@ static int distribute_txn_cancel_records(const struct lu_env *env, struct sub_thandle *st; ENTRY; + if (OBD_FAIL_CHECK(OBD_FAIL_TGT_TXN_NO_CANCEL)) + RETURN(0); + top_multiple_thandle_dump(tmt, D_INFO); /* Cancel update logs on other MDTs */ list_for_each_entry(st, &tmt->tmt_sub_thandle_list, st_sub_list) { diff --git a/lustre/tests/replay-dual.sh b/lustre/tests/replay-dual.sh index 6b06078..b93a24b 100755 --- a/lustre/tests/replay-dual.sh +++ b/lustre/tests/replay-dual.sh @@ -1028,6 +1028,39 @@ test_28() { } run_test 28 "lock replay should be ordered: waiting after granted" +test_32() { + (( $MDSCOUNT < 2 )) && skip_env "needs >= 2 MDTs" + + # inject a gap with 10th transaction +#define OBD_FAIL_LLOG_ADD_GAP 0x131d + do_facet $SINGLEMDS $LCTL set_param fail_loc=0x0000131d fail_val=10 + for ((i=0; i < 20; i++)); do + $LFS setdirstripe -i1 $DIR/$tdir-$i || + error "can't mkdir $DIR/$tdir-$i" + done + + # prevent update llog cancellation, so next boot MDS has + # process the update llog with gap injected +#define OBD_FAIL_TGT_TXN_NO_CANCEL 0x726 + $LCTL set_param fail_loc=0x726 + + stop mds2 + stop mds1 + + $LCTL set_param fail_loc=0 + + mount_facet mds1 + mount_facet mds2 + + $LFS df $DIR + + local testid=$(echo $TESTNAME | tr '_' ' ') + dmesg | tac | sed "/$testid/,$ d" | grep "This client was evicted" && + error "client got evicted due to aborted recovery" + return 0 +} +run_test 32 "gap in update llog shouldn't break recovery" + complete $SECONDS SLEEP=$((SECONDS - $NOW)) [ $SLEEP -lt $TIMEOUT ] && sleep $SLEEP -- 1.8.3.1