From 1b7ea3444bf877b4f000c413de1f5473ddf56689 Mon Sep 17 00:00:00 2001 From: Qian Yingjin Date: Wed, 5 Jul 2023 23:41:46 -0400 Subject: [PATCH] LU-14361 statahead: return ENOENT for batched statahead When stat on a non-existing file in a batched statahead context, MDT should return -ENOENT immediately and stop the statahead work. Otherwise, the client may cache the parent inode with UPDATE lock and the non-existing dentry under the protection of the parent's UPDATE lock wrongly. Add sanity/test_123j to verify it. Test-Parameters: clientdistro=el9.2 testlist=sanity env=ONLY=123i,ONLY_REPEAT=10 Signed-off-by: Qian Yingjin Change-Id: Ia4618f605d2f38ce712e421bcd7b96688bbfbb32 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/51587 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Lai Siyao Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin --- lustre/mdc/mdc_batch.c | 7 +++++++ lustre/mdt/mdt_batch.c | 5 +++-- lustre/mdt/mdt_handler.c | 4 +++- lustre/tests/sanity.sh | 32 +++++++++++++++++++++++++++++++- 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/lustre/mdc/mdc_batch.c b/lustre/mdc/mdc_batch.c index c2ebd17..82dff48 100644 --- a/lustre/mdc/mdc_batch.c +++ b/lustre/mdc/mdc_batch.c @@ -185,6 +185,7 @@ static int mdc_batch_getattr_interpret(struct ptlrpc_request *req, struct batch_update_head *head = ouc->ouc_head; struct obd_export *exp = head->buh_exp; struct req_capsule *pill = item->mop_pill; + struct ldlm_reply *lockrep; req_capsule_subreq_init(pill, &RQF_BUT_GETATTR, req, NULL, repmsg, RCL_CLIENT); @@ -194,6 +195,12 @@ static int mdc_batch_getattr_interpret(struct ptlrpc_request *req, if (rc) GOTO(out, rc); + lockrep = req_capsule_server_get(pill, &RMF_DLM_REP); + LASSERT(lockrep != NULL); + + lockrep->lock_policy_res2 = + ptlrpc_status_ntoh(lockrep->lock_policy_res2); + rc = mdc_finish_enqueue(exp, pill, einfo, &item->mop_it, &item->mop_lockh, rc); out: diff --git a/lustre/mdt/mdt_batch.c b/lustre/mdt/mdt_batch.c index 2dff768..27b17ef 100644 --- a/lustre/mdt/mdt_batch.c +++ b/lustre/mdt/mdt_batch.c @@ -320,8 +320,6 @@ int mdt_batch(struct tgt_session_info *tsi) tsi->tsi_batch_idx = handled_update_count; rc = h->th_act(tsi); - if (rc) - GOTO(out, rc); next: /* * As @repmsg may be changed if the reply buffer is @@ -332,6 +330,9 @@ next: grown = true; } + if (rc) + GOTO(out, rc); + repmsg->lm_result = rc; mdt_thread_info_reset(info); diff --git a/lustre/mdt/mdt_handler.c b/lustre/mdt/mdt_handler.c index 059bd4f..ab01713 100644 --- a/lustre/mdt/mdt_handler.c +++ b/lustre/mdt/mdt_handler.c @@ -4849,7 +4849,9 @@ static int mdt_intent_getattr(enum ldlm_intent_flags it_opc, if (!mdt_get_disposition(ldlm_rep, DISP_LOOKUP_POS) || ldlm_rep->lock_policy_res2) { lhc->mlh_reg_lh.cookie = 0ull; - GOTO(out_ucred, rc = ELDLM_LOCK_ABORTED); + /* Return error code immediately to stop batched statahead. */ + GOTO(out_ucred, rc = info->mti_batch_env ? rc : + ELDLM_LOCK_ABORTED); } rc = mdt_intent_lock_replace(info, lockp, lhc, flags, rc); diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 039a6e8..d0ba156 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -14824,7 +14824,7 @@ test_123i_base() { $LCTL set_param mdc.*.batch_stats=0 echo "statahead_stats (Pre):" - lctl get_param -n llite.*.statahead_stats + $LCTL get_param -n llite.*.statahead_stats eval $iocmd || error "$iocmd failed" echo "statahead_stats (Post):" $LCTL get_param -n llite.*.statahead_stats @@ -14876,6 +14876,36 @@ test_123i() { } run_test 123i "Verify statahead work with the fname indexing pattern" +test_123j() { + (( $MDSCOUNT > 1 )) || skip_env "needs >= 2 MDTs" + + $LCTL get_param -n mdc.*.connect_flags | grep -q batch_rpc || + skip "Server does not support batch RPC" + + local enabled + + enabled=$($LCTL get_param -n llite.*.enable_statahead_fname | head -n 1) + stack_trap "$LCTL set_param llite.*.enable_statahead_fname=$enabled" + $LCTL set_param llite.*.enable_statahead_fname=1 + + stack_trap "rm -rf $DIR/${tdir}.{1..11}" + + mkdir $DIR/${tdir}.{1..10} || + error "failed to mkdir $DIR/${tdir}.{1..10}" + cancel_lru_locks mdc + + for i in $(seq 1 10); do + stat $DIR/${tdir}.$i || error "failed to stat $DIR/${tdir}.$i" + done + + stat $DIR/${tdir}.11 + $LFS mkdir -i $((MDSCOUNT - 1)) -c 2 -H all_char $DIR/${tdir}.11 || + error "failed to mkdir $DIR/${tdir}.11" + touch $DIR/${tdir}.11/$tfile || + error "failed to create file $DIR/${tdir}.11/$tfile" +} +run_test 123j "-ENOENT error from batched statahead be handled correctly" + test_124a() { [ $PARALLEL == "yes" ] && skip "skip parallel run" $LCTL get_param -n mdc.*.connect_flags | grep -q lru_resize || -- 1.8.3.1