From: Alexey Lyashkov Date: Tue, 18 Aug 2020 13:24:04 +0000 (+0300) Subject: LU-13645 ldlm: don't use a locks without l_ast_data X-Git-Tag: 2.13.56~26 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=a6798c5806088dc1892dd752012a54f0ec8f1798 LU-13645 ldlm: don't use a locks without l_ast_data Partially initialized lock (without l_ast_data to be init) caused a fail with blocking ast, as discard from page cache skipped, and stale data will read later with fast read. Slow read have chance to attach this lock to right IO, but it don’t true always, so that should disabled, until lock will have l_ast_data set always for DoM and Lock Ahead locks. HPE-bugid: LUS-8750 Change-Id: I2c5180c8044a12d7bd8f5f1c871447ca8b47a8ff Signed-off-by: Alexey Lyashkov Reviewed-on: https://review.whamcloud.com/39318 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Vitaly Fertman Reviewed-by: Oleg Drokin --- diff --git a/lustre/include/lustre_dlm.h b/lustre/include/lustre_dlm.h index f38f36b..2c1e19c 100644 --- a/lustre/include/lustre_dlm.h +++ b/lustre/include/lustre_dlm.h @@ -978,6 +978,12 @@ struct ldlm_lock { struct list_head l_exp_list; }; +enum ldlm_match_flags { + LDLM_MATCH_UNREF = BIT(0), + LDLM_MATCH_AST = BIT(1), + LDLM_MATCH_AST_ANY = BIT(2), +}; + /** * Describe the overlap between two locks. itree_overlap_cb data. */ @@ -988,8 +994,7 @@ struct ldlm_match_data { union ldlm_policy_data *lmd_policy; __u64 lmd_flags; __u64 lmd_skip_flags; - int lmd_unref; - bool lmd_has_ast_data; + enum ldlm_match_flags lmd_match; }; /** For uncommitted cross-MDT lock, store transno this lock belongs to */ @@ -1549,6 +1554,7 @@ void ldlm_lock_fail_match_locked(struct ldlm_lock *lock); void ldlm_lock_fail_match(struct ldlm_lock *lock); void ldlm_lock_allow_match(struct ldlm_lock *lock); void ldlm_lock_allow_match_locked(struct ldlm_lock *lock); + enum ldlm_mode ldlm_lock_match_with_skip(struct ldlm_namespace *ns, __u64 flags, __u64 skip_flags, const struct ldlm_res_id *res_id, @@ -1556,18 +1562,17 @@ enum ldlm_mode ldlm_lock_match_with_skip(struct ldlm_namespace *ns, union ldlm_policy_data *policy, enum ldlm_mode mode, struct lustre_handle *lh, - int unref); + enum ldlm_match_flags match_flags); static inline enum ldlm_mode ldlm_lock_match(struct ldlm_namespace *ns, __u64 flags, const struct ldlm_res_id *res_id, enum ldlm_type type, union ldlm_policy_data *policy, enum ldlm_mode mode, - struct lustre_handle *lh, - int unref) + struct lustre_handle *lh) { return ldlm_lock_match_with_skip(ns, flags, 0, res_id, type, policy, - mode, lh, unref); + mode, lh, 0); } struct ldlm_lock *search_itree(struct ldlm_resource *res, struct ldlm_match_data *data); diff --git a/lustre/include/lustre_osc.h b/lustre/include/lustre_osc.h index 4072fbd..95edabc 100644 --- a/lustre/include/lustre_osc.h +++ b/lustre/include/lustre_osc.h @@ -227,6 +227,10 @@ enum osc_dap_flags { * Return the lock even if it is being canceled. */ OSC_DAP_FL_CANCELING = BIT(1), + /** + * check ast data is present, requested to cancel cb + */ + OSC_DAP_FL_AST = BIT(2), }; /* diff --git a/lustre/ldlm/ldlm_lock.c b/lustre/ldlm/ldlm_lock.c index cf84a20..f1482c0 100644 --- a/lustre/ldlm/ldlm_lock.c +++ b/lustre/ldlm/ldlm_lock.c @@ -1179,7 +1179,7 @@ static int lock_matches(struct ldlm_lock *lock, struct ldlm_match_data *data) if (ldlm_is_cbpending(lock) && !(data->lmd_flags & LDLM_FL_CBPENDING)) return INTERVAL_ITER_CONT; - if (!data->lmd_unref && ldlm_is_cbpending(lock) && + if (!(data->lmd_match & LDLM_MATCH_UNREF) && ldlm_is_cbpending(lock) && lock->l_readers == 0 && lock->l_writers == 0) return INTERVAL_ITER_CONT; @@ -1189,11 +1189,12 @@ static int lock_matches(struct ldlm_lock *lock, struct ldlm_match_data *data) /* When we search for ast_data, we are not doing a traditional match, * so we don't worry about IBITS or extent matching. */ - if (data->lmd_has_ast_data) { + if (data->lmd_match & (LDLM_MATCH_AST | LDLM_MATCH_AST_ANY)) { if (!lock->l_ast_data) return INTERVAL_ITER_CONT; - goto matched; + if (data->lmd_match & LDLM_MATCH_AST_ANY) + goto matched; } match = lock->l_req_mode; @@ -1223,7 +1224,7 @@ static int lock_matches(struct ldlm_lock *lock, struct ldlm_match_data *data) /* We match if we have existing lock with same or wider set of bits. */ - if (!data->lmd_unref && LDLM_HAVE_MASK(lock, GONE)) + if (!(data->lmd_match & LDLM_MATCH_UNREF) && LDLM_HAVE_MASK(lock, GONE)) return INTERVAL_ITER_CONT; if (!equi(data->lmd_flags & LDLM_FL_LOCAL_ONLY, ldlm_is_local(lock))) @@ -1404,7 +1405,8 @@ enum ldlm_mode ldlm_lock_match_with_skip(struct ldlm_namespace *ns, enum ldlm_type type, union ldlm_policy_data *policy, enum ldlm_mode mode, - struct lustre_handle *lockh, int unref) + struct lustre_handle *lockh, + enum ldlm_match_flags match_flags) { struct ldlm_match_data data = { .lmd_old = NULL, @@ -1413,8 +1415,7 @@ enum ldlm_mode ldlm_lock_match_with_skip(struct ldlm_namespace *ns, .lmd_policy = policy, .lmd_flags = flags, .lmd_skip_flags = skip_flags, - .lmd_unref = unref, - .lmd_has_ast_data = false, + .lmd_match = match_flags, }; struct ldlm_resource *res; struct ldlm_lock *lock; diff --git a/lustre/mdc/mdc_dev.c b/lustre/mdc/mdc_dev.c index 72cf45c..3edd170 100644 --- a/lustre/mdc/mdc_dev.c +++ b/lustre/mdc/mdc_dev.c @@ -91,7 +91,8 @@ int mdc_dom_lock_match(const struct lu_env *env, struct obd_export *exp, struct ldlm_res_id *res_id, enum ldlm_type type, union ldlm_policy_data *policy, enum ldlm_mode mode, __u64 *flags, struct osc_object *obj, - struct lustre_handle *lockh, int unref) + struct lustre_handle *lockh, + enum ldlm_match_flags match_flags) { struct obd_device *obd = exp->exp_obd; __u64 lflags = *flags; @@ -99,8 +100,9 @@ int mdc_dom_lock_match(const struct lu_env *env, struct obd_export *exp, ENTRY; - rc = ldlm_lock_match(obd->obd_namespace, lflags, - res_id, type, policy, mode, lockh, unref); + rc = ldlm_lock_match_with_skip(obd->obd_namespace, lflags, 0, + res_id, type, policy, mode, lockh, match_flags); + if (rc == 0 || lflags & LDLM_FL_TEST_LOCK) RETURN(rc); @@ -140,6 +142,7 @@ struct ldlm_lock *mdc_dlmlock_at_pgoff(const struct lu_env *env, struct ldlm_lock *lock = NULL; enum ldlm_mode mode; __u64 flags; + enum ldlm_match_flags match_flags = 0; ENTRY; @@ -150,6 +153,12 @@ struct ldlm_lock *mdc_dlmlock_at_pgoff(const struct lu_env *env, if (dap_flags & OSC_DAP_FL_TEST_LOCK) flags |= LDLM_FL_TEST_LOCK; + if (dap_flags & OSC_DAP_FL_AST) + match_flags |= LDLM_MATCH_AST; + + if (dap_flags & OSC_DAP_FL_CANCELING) + match_flags |= LDLM_MATCH_UNREF; + again: /* Next, search for already existing extent locks that will cover us */ /* If we're trying to read, we also search for an existing PW lock. The @@ -157,8 +166,7 @@ again: * writers can share a single PW lock. */ mode = mdc_dom_lock_match(env, osc_export(obj), resname, LDLM_IBITS, policy, LCK_PR | LCK_PW | LCK_GROUP, &flags, - obj, &lockh, - dap_flags & OSC_DAP_FL_CANCELING); + obj, &lockh, match_flags); if (mode != 0) { lock = ldlm_handle2lock(&lockh); /* RACE: the lock is cancelled so let's try again */ @@ -186,7 +194,7 @@ static bool mdc_check_and_discard_cb(const struct lu_env *env, struct cl_io *io, /* refresh non-overlapped index */ tmp = mdc_dlmlock_at_pgoff(env, osc, index, - OSC_DAP_FL_TEST_LOCK); + OSC_DAP_FL_TEST_LOCK | OSC_DAP_FL_AST); if (tmp != NULL) { info->oti_fn_index = CL_PAGE_EOF; LDLM_LOCK_PUT(tmp); @@ -709,7 +717,7 @@ int mdc_enqueue_send(const struct lu_env *env, struct obd_export *exp, * such locks should be skipped. */ mode = ldlm_lock_match(obd->obd_namespace, match_flags, res_id, - einfo->ei_type, policy, mode, &lockh, 0); + einfo->ei_type, policy, mode, &lockh); if (mode) { struct ldlm_lock *matched; diff --git a/lustre/mdc/mdc_locks.c b/lustre/mdc/mdc_locks.c index a1887ea..788a301 100644 --- a/lustre/mdc/mdc_locks.c +++ b/lustre/mdc/mdc_locks.c @@ -146,7 +146,7 @@ enum ldlm_mode mdc_lock_match(struct obd_export *exp, __u64 flags, /* LU-4405: Clear bits not supported by server */ policy->l_inodebits.bits &= exp_connect_ibits(exp); rc = ldlm_lock_match(class_exp2obd(exp)->obd_namespace, flags, - &res_id, type, policy, mode, lockh, 0); + &res_id, type, policy, mode, lockh); RETURN(rc); } @@ -1189,7 +1189,7 @@ static int mdc_finish_intent_lock(struct obd_export *exp, memcpy(&old_lock, lockh, sizeof(*lockh)); if (ldlm_lock_match(NULL, LDLM_FL_BLOCK_GRANTED, NULL, - LDLM_IBITS, &policy, LCK_NL, &old_lock, 0)) { + LDLM_IBITS, &policy, LCK_NL, &old_lock)) { ldlm_lock_decref_and_cancel(lockh, it->it_lock_mode); memcpy(lockh, &old_lock, sizeof(old_lock)); it->it_lock_handle = lockh->cookie; diff --git a/lustre/mdt/mdt_io.c b/lustre/mdt/mdt_io.c index ba4c372..0ffee16 100644 --- a/lustre/mdt/mdt_io.c +++ b/lustre/mdt/mdt_io.c @@ -979,7 +979,7 @@ int mdt_do_glimpse(const struct lu_env *env, struct ldlm_namespace *ns, policy.l_inodebits.bits = MDS_INODELOCK_DOM; mode = ldlm_lock_match(ns, LDLM_FL_TEST_LOCK, &res->lr_name, LDLM_IBITS, &policy, - LCK_PW, &lockh, 0); + LCK_PW, &lockh); /* There is no PW lock on this object; finished. */ if (mode == 0) @@ -1281,7 +1281,7 @@ bool mdt_dom_client_has_lock(struct mdt_thread_info *info, lm = (open_flags & MDS_FMODE_WRITE) ? LCK_PW : LCK_PR | LCK_PW; mode = ldlm_lock_match(mdt->mdt_namespace, LDLM_FL_BLOCK_GRANTED | LDLM_FL_TEST_LOCK, res_id, LDLM_IBITS, policy, - lm, &lockh, 0); + lm, &lockh); /* There is no other PW lock on this object; finished. */ if (mode == 0) diff --git a/lustre/osc/osc_cache.c b/lustre/osc/osc_cache.c index 2888530..a477ebd 100644 --- a/lustre/osc/osc_cache.c +++ b/lustre/osc/osc_cache.c @@ -3126,7 +3126,7 @@ static bool check_and_discard_cb(const struct lu_env *env, struct cl_io *io, /* refresh non-overlapped index */ tmp = osc_dlmlock_at_pgoff(env, osc, index, - OSC_DAP_FL_TEST_LOCK); + OSC_DAP_FL_TEST_LOCK | OSC_DAP_FL_AST); if (tmp != NULL) { __u64 end = tmp->l_policy_data.l_extent.end; /* Cache the first-non-overlapped index so as to skip diff --git a/lustre/osc/osc_internal.h b/lustre/osc/osc_internal.h index 1c38522..8b54535 100644 --- a/lustre/osc/osc_internal.h +++ b/lustre/osc/osc_internal.h @@ -68,7 +68,7 @@ int osc_match_base(const struct lu_env *env, struct obd_export *exp, struct ldlm_res_id *res_id, enum ldlm_type type, union ldlm_policy_data *policy, enum ldlm_mode mode, __u64 *flags, struct osc_object *obj, - struct lustre_handle *lockh, int unref); + struct lustre_handle *lockh, enum ldlm_match_flags match_flags); int osc_setattr_async(struct obd_export *exp, struct obdo *oa, obd_enqueue_update_f upcall, void *cookie, diff --git a/lustre/osc/osc_lock.c b/lustre/osc/osc_lock.c index 3370386..4c76e52 100644 --- a/lustre/osc/osc_lock.c +++ b/lustre/osc/osc_lock.c @@ -582,8 +582,7 @@ int osc_ldlm_glimpse_ast(struct ldlm_lock *dlmlock, void *data) matchdata.lmd_mode = &mode; matchdata.lmd_policy = &policy; matchdata.lmd_flags = LDLM_FL_TEST_LOCK | LDLM_FL_CBPENDING; - matchdata.lmd_unref = 1; - matchdata.lmd_has_ast_data = true; + matchdata.lmd_match = LDLM_MATCH_UNREF | LDLM_MATCH_AST_ANY; LDLM_LOCK_GET(dlmlock); @@ -1277,6 +1276,7 @@ struct ldlm_lock *osc_obj_dlmlock_at_pgoff(const struct lu_env *env, struct ldlm_lock *lock = NULL; enum ldlm_mode mode; __u64 flags; + enum ldlm_match_flags match_flags = 0; ENTRY; @@ -1287,6 +1287,13 @@ struct ldlm_lock *osc_obj_dlmlock_at_pgoff(const struct lu_env *env, flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_CBPENDING; if (dap_flags & OSC_DAP_FL_TEST_LOCK) flags |= LDLM_FL_TEST_LOCK; + + if (dap_flags & OSC_DAP_FL_AST) + match_flags |= LDLM_MATCH_AST; + + if (dap_flags & OSC_DAP_FL_CANCELING) + match_flags |= LDLM_MATCH_UNREF; + /* * It is fine to match any group lock since there could be only one * with a uniq gid and it conflicts with all other lock modes too @@ -1294,7 +1301,7 @@ struct ldlm_lock *osc_obj_dlmlock_at_pgoff(const struct lu_env *env, again: mode = osc_match_base(env, osc_export(obj), resname, LDLM_EXTENT, policy, LCK_PR | LCK_PW | LCK_GROUP, &flags, - obj, &lockh, dap_flags & OSC_DAP_FL_CANCELING); + obj, &lockh, match_flags); if (mode != 0) { lock = ldlm_handle2lock(&lockh); /* RACE: the lock is cancelled so let's try again */ diff --git a/lustre/osc/osc_object.c b/lustre/osc/osc_object.c index a2f840f..ccb5bad 100644 --- a/lustre/osc/osc_object.c +++ b/lustre/osc/osc_object.c @@ -280,7 +280,7 @@ static int osc_object_fiemap(const struct lu_env *env, struct cl_object *obj, mode = ldlm_lock_match(exp->exp_obd->obd_namespace, LDLM_FL_BLOCK_GRANTED | LDLM_FL_LVB_READY, &resid, LDLM_EXTENT, &policy, - LCK_PR | LCK_PW, &lockh, 0); + LCK_PR | LCK_PW, &lockh); if (mode) { /* lock is cached on client */ if (mode != LCK_PR) { ldlm_lock_addref(&lockh, LCK_PR); diff --git a/lustre/osc/osc_request.c b/lustre/osc/osc_request.c index 290f26f..4bebfaa 100644 --- a/lustre/osc/osc_request.c +++ b/lustre/osc/osc_request.c @@ -2735,7 +2735,7 @@ int osc_enqueue_base(struct obd_export *exp, struct ldlm_res_id *res_id, if (intent != 0) match_flags |= LDLM_FL_BLOCK_GRANTED; mode = ldlm_lock_match(obd->obd_namespace, match_flags, res_id, - einfo->ei_type, policy, mode, &lockh, 0); + einfo->ei_type, policy, mode, &lockh); if (mode) { struct ldlm_lock *matched; @@ -2841,7 +2841,7 @@ int osc_match_base(const struct lu_env *env, struct obd_export *exp, struct ldlm_res_id *res_id, enum ldlm_type type, union ldlm_policy_data *policy, enum ldlm_mode mode, __u64 *flags, struct osc_object *obj, - struct lustre_handle *lockh, int unref) + struct lustre_handle *lockh, enum ldlm_match_flags match_flags) { struct obd_device *obd = exp->exp_obd; __u64 lflags = *flags; @@ -2856,15 +2856,17 @@ int osc_match_base(const struct lu_env *env, struct obd_export *exp, policy->l_extent.start -= policy->l_extent.start & ~PAGE_MASK; policy->l_extent.end |= ~PAGE_MASK; - /* Next, search for already existing extent locks that will cover us */ - /* If we're trying to read, we also search for an existing PW lock. The - * VFS and page cache already protect us locally, so lots of readers/ + /* Next, search for already existing extent locks that will cover us */ + /* If we're trying to read, we also search for an existing PW lock. The + * VFS and page cache already protect us locally, so lots of readers/ * writers can share a single PW lock. */ - rc = mode; - if (mode == LCK_PR) - rc |= LCK_PW; - rc = ldlm_lock_match(obd->obd_namespace, lflags, - res_id, type, policy, rc, lockh, unref); + rc = mode; + if (mode == LCK_PR) + rc |= LCK_PW; + + rc = ldlm_lock_match_with_skip(obd->obd_namespace, lflags, 0, + res_id, type, policy, rc, lockh, + match_flags); if (rc == 0 || lflags & LDLM_FL_TEST_LOCK) RETURN(rc);