From 06740440363424bff6cfdb467fcc5544e42cabc1 Mon Sep 17 00:00:00 2001 From: Vitaly Fertman Date: Tue, 4 Aug 2020 15:12:04 +0300 Subject: [PATCH] LU-13645 ldlm: group locks for DOM IBIT lock Group lock is supposed to be taken on such operations as layout swap used for e.g. HSM, and is to be taken for DOM locks as well. HPE-bug-id: LUS-8987 Signed-off-by: Vitaly Fertman Change-Id: I97888e1aee853d7fe04548681b2ed6805cb494ae Reviewed-on: https://review.whamcloud.com/39406 Reviewed-by: Andreas Dilger Reviewed-by: Mike Pershin Tested-by: jenkins Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/include/uapi/linux/lustre/lustre_idl.h | 1 + lustre/ldlm/ldlm_inodebits.c | 128 +++++++++++++++++++++----- lustre/ldlm/ldlm_internal.h | 2 +- lustre/ldlm/ldlm_lock.c | 12 ++- lustre/ldlm/ldlm_resource.c | 7 +- lustre/mdc/mdc_dev.c | 11 ++- lustre/mdt/mdt_handler.c | 13 ++- lustre/mdt/mdt_internal.h | 2 + lustre/mdt/mdt_io.c | 3 +- lustre/ptlrpc/wiretest.c | 7 +- lustre/tests/sanity-dom.sh | 2 +- lustre/tests/sanityn.sh | 54 ++++++++++- lustre/utils/wirecheck.c | 1 + lustre/utils/wiretest.c | 7 +- 14 files changed, 211 insertions(+), 39 deletions(-) diff --git a/lustre/include/uapi/linux/lustre/lustre_idl.h b/lustre/include/uapi/linux/lustre/lustre_idl.h index cf9b359..375bd88 100644 --- a/lustre/include/uapi/linux/lustre/lustre_idl.h +++ b/lustre/include/uapi/linux/lustre/lustre_idl.h @@ -2438,6 +2438,7 @@ struct ldlm_inodebits { __u64 try_bits; /* optional bits to try */ __u64 cancel_bits; /* for lock convert */ }; + __u64 li_gid; }; struct ldlm_flock_wire { diff --git a/lustre/ldlm/ldlm_inodebits.c b/lustre/ldlm/ldlm_inodebits.c index 7dd78d0..68914d9 100644 --- a/lustre/ldlm/ldlm_inodebits.c +++ b/lustre/ldlm/ldlm_inodebits.c @@ -157,8 +157,9 @@ restart: */ static int ldlm_inodebits_compat_queue(struct list_head *queue, struct ldlm_lock *req, - struct list_head *work_list) + __u64 *ldlm_flags, struct list_head *work_list) { + enum ldlm_mode req_mode = req->l_req_mode; struct list_head *tmp; struct ldlm_lock *lock; __u64 req_bits = req->l_policy_data.l_inodebits.bits; @@ -167,6 +168,8 @@ ldlm_inodebits_compat_queue(struct list_head *queue, struct ldlm_lock *req, ENTRY; + lockmode_verify(req_mode); + /* There is no sense in lock with no bits set. Also such a lock * would be compatible with any other bit lock. * Meanwhile that can be true if there were just try_bits and all @@ -201,10 +204,41 @@ ldlm_inodebits_compat_queue(struct list_head *queue, struct ldlm_lock *req, continue; } - /* locks' mode are compatible, bits don't matter */ - if (lockmode_compat(lock->l_req_mode, req->l_req_mode)) { - /* jump to last lock in mode group */ - tmp = mode_tail; + if (lockmode_compat(lock->l_req_mode, req_mode)) { + /* non group locks are compatible, bits don't matter */ + if (likely(req_mode != LCK_GROUP)) { + /* jump to last lock in mode group */ + tmp = mode_tail; + continue; + } + + if (req->l_policy_data.l_inodebits.li_gid == + lock->l_policy_data.l_inodebits.li_gid) { + if (ldlm_is_granted(lock)) + RETURN(2); + + if (*ldlm_flags & LDLM_FL_BLOCK_NOWAIT) + RETURN(-EWOULDBLOCK); + + /* Place the same group together */ + ldlm_resource_insert_lock_after(lock, req); + RETURN(0); + } + } + + /* GROUP locks are placed to a head of the waiting list, but + * grouped by gid. */ + if (unlikely(req_mode == LCK_GROUP && !ldlm_is_granted(lock))) { + compat = 0; + if (lock->l_req_mode != LCK_GROUP) { + /* Already not a GROUP lock, insert before. */ + ldlm_resource_insert_lock_before(lock, req); + break; + } + /* Still GROUP but a different gid(the same gid would + * be handled above). Keep searching for the same gid */ + LASSERT(req->l_policy_data.l_inodebits.li_gid != + lock->l_policy_data.l_inodebits.li_gid); continue; } @@ -241,14 +275,23 @@ ldlm_inodebits_compat_queue(struct list_head *queue, struct ldlm_lock *req, !ldlm_is_cos_incompat(req) && ldlm_is_cos_enabled(req) && lock->l_client_cookie == req->l_client_cookie) - goto not_conflicting; + goto skip_work_list; + + compat = 0; + + if (unlikely(lock->l_req_mode == LCK_GROUP)) { + LASSERT(ldlm_has_dom(lock)); + + if (*ldlm_flags & LDLM_FL_BLOCK_NOWAIT) + RETURN(-EWOULDBLOCK); + + goto skip_work_list; + } /* Found a conflicting policy group. */ if (!work_list) RETURN(0); - compat = 0; - /* Add locks of the policy group to @work_list * as blocking locks for @req */ if (lock->l_blocking_ast) @@ -260,7 +303,7 @@ ldlm_inodebits_compat_queue(struct list_head *queue, struct ldlm_lock *req, ldlm_add_ast_work_item(lock, req, work_list); } -not_conflicting: +skip_work_list: if (tmp == mode_tail) break; @@ -280,7 +323,7 @@ not_conflicting: * waiting queues. The lock is granted if no conflicts are found in * either queue. */ -int ldlm_process_inodebits_lock(struct ldlm_lock *lock, __u64 *flags, +int ldlm_process_inodebits_lock(struct ldlm_lock *lock, __u64 *ldlm_flags, enum ldlm_process_intention intention, enum ldlm_error *err, struct list_head *work_list) @@ -288,7 +331,7 @@ int ldlm_process_inodebits_lock(struct ldlm_lock *lock, __u64 *flags, struct ldlm_resource *res = lock->l_resource; struct list_head *grant_work = intention == LDLM_PROCESS_ENQUEUE ? NULL : work_list; - int rc; + int rc, rc2 = 0; ENTRY; *err = ELDLM_LOCK_ABORTED; @@ -297,7 +340,7 @@ int ldlm_process_inodebits_lock(struct ldlm_lock *lock, __u64 *flags, if (intention == LDLM_PROCESS_RESCAN) { struct list_head *bl_list = - *flags & LDLM_FL_BLOCK_NOWAIT ? NULL : work_list; + *ldlm_flags & LDLM_FL_BLOCK_NOWAIT ? NULL : work_list; LASSERT(lock->l_policy_data.l_inodebits.bits != 0); @@ -320,11 +363,13 @@ int ldlm_process_inodebits_lock(struct ldlm_lock *lock, __u64 *flags, * any blocked locks from granted queue during every reprocess * and bl_ast will be sent if needed. */ + *ldlm_flags = 0; rc = ldlm_inodebits_compat_queue(&res->lr_granted, lock, - bl_list); + ldlm_flags, bl_list); if (!rc) RETURN(LDLM_ITER_STOP); - rc = ldlm_inodebits_compat_queue(&res->lr_waiting, lock, NULL); + rc = ldlm_inodebits_compat_queue(&res->lr_waiting, lock, + ldlm_flags, NULL); if (!rc) RETURN(LDLM_ITER_STOP); @@ -333,7 +378,7 @@ int ldlm_process_inodebits_lock(struct ldlm_lock *lock, __u64 *flags, lock->l_policy_data.l_inodebits.bits |= lock->l_policy_data.l_inodebits.try_bits; lock->l_policy_data.l_inodebits.try_bits = 0; - *flags |= LDLM_FL_LOCK_CHANGED; + *ldlm_flags |= LDLM_FL_LOCK_CHANGED; } ldlm_resource_unlink_lock(lock); ldlm_grant_lock(lock, grant_work); @@ -342,16 +387,26 @@ int ldlm_process_inodebits_lock(struct ldlm_lock *lock, __u64 *flags, RETURN(LDLM_ITER_CONTINUE); } - rc = ldlm_inodebits_compat_queue(&res->lr_granted, lock, work_list); - rc += ldlm_inodebits_compat_queue(&res->lr_waiting, lock, work_list); + rc = ldlm_inodebits_compat_queue(&res->lr_granted, lock, + ldlm_flags, work_list); + if (rc < 0) + GOTO(out, *err = rc); if (rc != 2) { + rc2 = ldlm_inodebits_compat_queue(&res->lr_waiting, lock, + ldlm_flags, work_list); + if (rc2 < 0) + GOTO(out, *err = rc = rc2); + } + + if (rc + rc2 != 2) { /* if there were only bits to try and all are conflicting */ if ((lock->l_policy_data.l_inodebits.bits | lock->l_policy_data.l_inodebits.try_bits)) { - /* There is no sense to set LDLM_FL_NO_TIMEOUT to @flags - * for DOM lock while they are enqueued through intents, - * i.e. @lock here is local which does not timeout. */ + /* There is no sense to set LDLM_FL_NO_TIMEOUT to + * @ldlm_flags for DOM lock while they are enqueued + * through intents, i.e. @lock here is local which does + * not timeout. */ *err = ELDLM_OK; } } else { @@ -360,7 +415,7 @@ int ldlm_process_inodebits_lock(struct ldlm_lock *lock, __u64 *flags, lock->l_policy_data.l_inodebits.bits |= lock->l_policy_data.l_inodebits.try_bits; lock->l_policy_data.l_inodebits.try_bits = 0; - *flags |= LDLM_FL_LOCK_CHANGED; + *ldlm_flags |= LDLM_FL_LOCK_CHANGED; } LASSERT(lock->l_policy_data.l_inodebits.bits); ldlm_resource_unlink_lock(lock); @@ -369,6 +424,8 @@ int ldlm_process_inodebits_lock(struct ldlm_lock *lock, __u64 *flags, } RETURN(LDLM_ITER_CONTINUE); +out: + return rc; } #endif /* HAVE_SERVER_SUPPORT */ @@ -376,6 +433,7 @@ void ldlm_ibits_policy_wire_to_local(const union ldlm_wire_policy_data *wpolicy, union ldlm_policy_data *lpolicy) { lpolicy->l_inodebits.bits = wpolicy->l_inodebits.bits; + lpolicy->l_inodebits.li_gid = wpolicy->l_inodebits.li_gid; /** * try_bits are to be handled outside of generic write_to_local due * to different behavior on a server and client. @@ -388,6 +446,7 @@ void ldlm_ibits_policy_local_to_wire(const union ldlm_policy_data *lpolicy, memset(wpolicy, 0, sizeof(*wpolicy)); wpolicy->l_inodebits.bits = lpolicy->l_inodebits.bits; wpolicy->l_inodebits.try_bits = lpolicy->l_inodebits.try_bits; + wpolicy->l_inodebits.li_gid = lpolicy->l_inodebits.li_gid; } /** @@ -535,7 +594,7 @@ int ldlm_inodebits_alloc_lock(struct ldlm_lock *lock) } void ldlm_inodebits_add_lock(struct ldlm_resource *res, struct list_head *head, - struct ldlm_lock *lock) + struct ldlm_lock *lock, bool tail) { int i; @@ -544,15 +603,36 @@ void ldlm_inodebits_add_lock(struct ldlm_resource *res, struct list_head *head, if (head == &res->lr_waiting) { for (i = 0; i < MDS_INODELOCK_NUMBITS; i++) { - if (lock->l_policy_data.l_inodebits.bits & BIT(i)) + if (!(lock->l_policy_data.l_inodebits.bits & BIT(i))) + continue; + if (tail) list_add_tail(&lock->l_ibits_node->lin_link[i], - &res->lr_ibits_queues->liq_waiting[i]); + &res->lr_ibits_queues->liq_waiting[i]); + else + list_add(&lock->l_ibits_node->lin_link[i], + &res->lr_ibits_queues->liq_waiting[i]); } } else if (head == &res->lr_granted && lock->l_ibits_node != NULL) { for (i = 0; i < MDS_INODELOCK_NUMBITS; i++) LASSERT(list_empty(&lock->l_ibits_node->lin_link[i])); OBD_SLAB_FREE_PTR(lock->l_ibits_node, ldlm_inodebits_slab); lock->l_ibits_node = NULL; + } else if (head != &res->lr_granted) { + /* we are inserting in a middle of a list, after @head */ + struct ldlm_lock *orig = list_entry(head, struct ldlm_lock, + l_res_link); + LASSERT(orig->l_policy_data.l_inodebits.bits == + lock->l_policy_data.l_inodebits.bits); + /* The is no a use case to insert before with exactly matched + * set of bits */ + LASSERT(tail == false); + + for (i = 0; i < MDS_INODELOCK_NUMBITS; i++) { + if (!(lock->l_policy_data.l_inodebits.bits & (1 << i))) + continue; + list_add(&lock->l_ibits_node->lin_link[i], + &orig->l_ibits_node->lin_link[i]); + } } } diff --git a/lustre/ldlm/ldlm_internal.h b/lustre/ldlm/ldlm_internal.h index 58b2db6..84c3182 100644 --- a/lustre/ldlm/ldlm_internal.h +++ b/lustre/ldlm/ldlm_internal.h @@ -208,7 +208,7 @@ void ldlm_extent_unlink_lock(struct ldlm_lock *lock); int ldlm_inodebits_alloc_lock(struct ldlm_lock *lock); void ldlm_inodebits_add_lock(struct ldlm_resource *res, struct list_head *head, - struct ldlm_lock *lock); + struct ldlm_lock *lock, bool tail); void ldlm_inodebits_unlink_lock(struct ldlm_lock *lock); /* ldlm_flock.c */ diff --git a/lustre/ldlm/ldlm_lock.c b/lustre/ldlm/ldlm_lock.c index 00d4f43..546f351 100644 --- a/lustre/ldlm/ldlm_lock.c +++ b/lustre/ldlm/ldlm_lock.c @@ -1215,6 +1215,12 @@ static int lock_matches(struct ldlm_lock *lock, struct ldlm_match_data *data) data->lmd_policy->l_inodebits.bits) != data->lmd_policy->l_inodebits.bits) return INTERVAL_ITER_CONT; + + if (unlikely(match == LCK_GROUP) && + data->lmd_policy->l_inodebits.li_gid != LDLM_GID_ANY && + lpol->l_inodebits.li_gid != + data->lmd_policy->l_inodebits.li_gid) + return INTERVAL_ITER_CONT; break; default: ; @@ -2799,7 +2805,7 @@ void _ldlm_lock_debug(struct ldlm_lock *lock, switch (resource->lr_type) { case LDLM_EXTENT: libcfs_debug_msg(msgdata, - "%pV ns: %s lock: %p/%#llx lrc: %d/%d,%d mode: %s/%s res: " DLDLMRES " rrc: %d type: %s [%llu->%llu] (req %llu->%llu) flags: %#llx nid: %s remote: %#llx expref: %d pid: %u timeout: %lld lvb_type: %d\n", + "%pV ns: %s lock: %p/%#llx lrc: %d/%d,%d mode: %s/%s res: " DLDLMRES " rrc: %d type: %s [%llu->%llu] (req %llu->%llu) gid %llu flags: %#llx nid: %s remote: %#llx expref: %d pid: %u timeout: %lld lvb_type: %d\n", &vaf, ldlm_lock_to_ns_name(lock), lock, lock->l_handle.h_cookie, @@ -2813,6 +2819,7 @@ void _ldlm_lock_debug(struct ldlm_lock *lock, lock->l_policy_data.l_extent.start, lock->l_policy_data.l_extent.end, lock->l_req_extent.start, lock->l_req_extent.end, + lock->l_req_extent.gid, lock->l_flags, nid, lock->l_remote_handle.cookie, exp ? refcount_read(&exp->exp_handle.h_ref) : -99, @@ -2844,7 +2851,7 @@ void _ldlm_lock_debug(struct ldlm_lock *lock, case LDLM_IBITS: libcfs_debug_msg(msgdata, - "%pV ns: %s lock: %p/%#llx lrc: %d/%d,%d mode: %s/%s res: " DLDLMRES " bits %#llx/%#llx rrc: %d type: %s flags: %#llx nid: %s remote: %#llx expref: %d pid: %u timeout: %lld lvb_type: %d\n", + "%pV ns: %s lock: %p/%#llx lrc: %d/%d,%d mode: %s/%s res: " DLDLMRES " bits %#llx/%#llx rrc: %d type: %s gid %llu flags: %#llx nid: %s remote: %#llx expref: %d pid: %u timeout: %lld lvb_type: %d\n", &vaf, ldlm_lock_to_ns_name(lock), lock, lock->l_handle.h_cookie, @@ -2857,6 +2864,7 @@ void _ldlm_lock_debug(struct ldlm_lock *lock, lock->l_policy_data.l_inodebits.try_bits, atomic_read(&resource->lr_refcount), ldlm_typename[resource->lr_type], + lock->l_policy_data.l_inodebits.li_gid, lock->l_flags, nid, lock->l_remote_handle.cookie, exp ? refcount_read(&exp->exp_handle.h_ref) : -99, diff --git a/lustre/ldlm/ldlm_resource.c b/lustre/ldlm/ldlm_resource.c index a18daa8..0f4c9d4 100644 --- a/lustre/ldlm/ldlm_resource.c +++ b/lustre/ldlm/ldlm_resource.c @@ -1623,7 +1623,7 @@ static void __ldlm_resource_add_lock(struct ldlm_resource *res, list_add(&lock->l_res_link, head); if (res->lr_type == LDLM_IBITS) - ldlm_inodebits_add_lock(res, head, lock); + ldlm_inodebits_add_lock(res, head, lock, tail); ldlm_resource_dump(D_INFO, res); } @@ -1655,6 +1655,11 @@ void ldlm_resource_insert_lock_after(struct ldlm_lock *original, /** * Insert a lock into resource before the specified lock. + * + * IBITS waiting locks are to be inserted to the ibit lists as well, and only + * the insert-after operation is supported for them, because the set of bits + * of the previous and the new locks must match. Therefore, get the previous + * lock and insert after. */ void ldlm_resource_insert_lock_before(struct ldlm_lock *original, struct ldlm_lock *new) diff --git a/lustre/mdc/mdc_dev.c b/lustre/mdc/mdc_dev.c index 3edd170..eddfdda 100644 --- a/lustre/mdc/mdc_dev.c +++ b/lustre/mdc/mdc_dev.c @@ -39,10 +39,14 @@ #include "mdc_internal.h" static void mdc_lock_build_policy(const struct lu_env *env, + const struct cl_lock *lock, union ldlm_policy_data *policy) { memset(policy, 0, sizeof *policy); policy->l_inodebits.bits = MDS_INODELOCK_DOM; + if (lock) { + policy->l_inodebits.li_gid = lock->cll_descr.cld_gid; + } } int mdc_ldlm_glimpse_ast(struct ldlm_lock *dlmlock, void *data) @@ -147,7 +151,8 @@ struct ldlm_lock *mdc_dlmlock_at_pgoff(const struct lu_env *env, ENTRY; fid_build_reg_res_name(lu_object_fid(osc2lu(obj)), resname); - mdc_lock_build_policy(env, policy); + mdc_lock_build_policy(env, NULL, policy); + policy->l_inodebits.li_gid = LDLM_GID_ANY; flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_CBPENDING; if (dap_flags & OSC_DAP_FL_TEST_LOCK) @@ -885,7 +890,7 @@ enqueue_base: * osc_lock. */ fid_build_reg_res_name(lu_object_fid(osc2lu(osc)), resname); - mdc_lock_build_policy(env, policy); + mdc_lock_build_policy(env, lock, policy); LASSERT(!oscl->ols_speculative); result = mdc_enqueue_send(env, osc_export(osc), resname, &oscl->ols_flags, policy, @@ -951,6 +956,8 @@ int mdc_lock_init(const struct lu_env *env, struct cl_object *obj, ols->ols_flags = flags; ols->ols_speculative = !!(enqflags & CEF_SPECULATIVE); + if (lock->cll_descr.cld_mode == CLM_GROUP) + ols->ols_flags |= LDLM_FL_ATOMIC_CB; if (ols->ols_flags & LDLM_FL_HAS_INTENT) { ols->ols_flags |= LDLM_FL_BLOCK_GRANTED; diff --git a/lustre/mdt/mdt_handler.c b/lustre/mdt/mdt_handler.c index 68f98d0..2a0c36f 100644 --- a/lustre/mdt/mdt_handler.c +++ b/lustre/mdt/mdt_handler.c @@ -164,6 +164,13 @@ void mdt_lock_reg_init(struct mdt_lock_handle *lh, enum ldlm_mode lm) lh->mlh_type = MDT_REG_LOCK; } +void mdt_lh_reg_init(struct mdt_lock_handle *lh, struct ldlm_lock *lock) +{ + mdt_lock_reg_init(lh, lock->l_req_mode); + if (lock->l_req_mode == LCK_GROUP) + lh->mlh_gid = lock->l_policy_data.l_inodebits.li_gid; +} + void mdt_lock_pdo_init(struct mdt_lock_handle *lh, enum ldlm_mode lock_mode, const struct lu_name *lname) { @@ -3528,6 +3535,7 @@ int mdt_object_local_lock(struct mdt_thread_info *info, struct mdt_object *o, policy->l_inodebits.bits = *ibits; policy->l_inodebits.try_bits = trybits; + policy->l_inodebits.li_gid = lh->mlh_gid; /* * Use LDLM_FL_LOCAL_ONLY for this lock. We do not know yet if it is @@ -5654,8 +5662,9 @@ static int mdt_init0(const struct lu_env *env, struct mdt_device *m, m->mdt_skip_lfsck = 1; } - /* DoM files get IO lock at open optionally by default */ - m->mdt_opts.mo_dom_lock = ALWAYS_DOM_LOCK_ON_OPEN; + /* Just try to get a DoM lock by default. Otherwise, having a group + * lock granted, it may get blocked for a long time. */ + m->mdt_opts.mo_dom_lock = TRYLOCK_DOM_ON_OPEN; /* DoM files are read at open and data is packed in the reply */ m->mdt_opts.mo_dom_read_open = 1; diff --git a/lustre/mdt/mdt_internal.h b/lustre/mdt/mdt_internal.h index 8e22408..e1b12aa 100644 --- a/lustre/mdt/mdt_internal.h +++ b/lustre/mdt/mdt_internal.h @@ -371,6 +371,7 @@ struct mdt_lock_handle { /* Regular lock */ struct lustre_handle mlh_reg_lh; enum ldlm_mode mlh_reg_mode; + __u64 mlh_gid; /* Pdirops lock */ struct lustre_handle mlh_pdo_lh; @@ -780,6 +781,7 @@ void mdt_lock_pdo_init(struct mdt_lock_handle *lh, enum ldlm_mode lock_mode, const struct lu_name *lname); void mdt_lock_reg_init(struct mdt_lock_handle *lh, enum ldlm_mode lm); +void mdt_lh_reg_init(struct mdt_lock_handle *lh, struct ldlm_lock *lock); int mdt_lock_setup(struct mdt_thread_info *info, struct mdt_object *mo, struct mdt_lock_handle *lh); diff --git a/lustre/mdt/mdt_io.c b/lustre/mdt/mdt_io.c index 0ffee16..2115c0a 100644 --- a/lustre/mdt/mdt_io.c +++ b/lustre/mdt/mdt_io.c @@ -1225,7 +1225,8 @@ int mdt_brw_enqueue(struct mdt_thread_info *mti, struct ldlm_namespace *ns, /* resent case */ if (!lustre_handle_is_used(&lhc->mlh_reg_lh)) { mdt_lock_handle_init(lhc); - mdt_lock_reg_init(lhc, (*lockp)->l_req_mode); + mdt_lh_reg_init(lhc, *lockp); + /* This will block MDT thread but it should be fine until * client caches small amount of data for DoM, which should be * smaller than one BRW RPC and should be able to be diff --git a/lustre/ptlrpc/wiretest.c b/lustre/ptlrpc/wiretest.c index 46a692c..4c1557f4 100644 --- a/lustre/ptlrpc/wiretest.c +++ b/lustre/ptlrpc/wiretest.c @@ -3533,7 +3533,7 @@ void lustre_assert_wire_constants(void) (long long)(int)sizeof(((struct ldlm_extent *)0)->gid)); /* Checks for struct ldlm_inodebits */ - LASSERTF((int)sizeof(struct ldlm_inodebits) == 16, "found %lld\n", + LASSERTF((int)sizeof(struct ldlm_inodebits) == 24, "found %lld\n", (long long)(int)sizeof(struct ldlm_inodebits)); LASSERTF((int)offsetof(struct ldlm_inodebits, bits) == 0, "found %lld\n", (long long)(int)offsetof(struct ldlm_inodebits, bits)); @@ -3543,6 +3543,11 @@ void lustre_assert_wire_constants(void) (long long)(int)offsetof(struct ldlm_inodebits, try_bits)); LASSERTF((int)sizeof(((struct ldlm_inodebits *)0)->try_bits) == 8, "found %lld\n", (long long)(int)sizeof(((struct ldlm_inodebits *)0)->try_bits)); + LASSERTF((int)offsetof(struct ldlm_inodebits, li_gid) == 16, "found %lld\n", + (long long)(int)offsetof(struct ldlm_inodebits, li_gid)); + + LASSERTF((int)sizeof(((struct ldlm_inodebits *)0)->li_gid) == 8, "found %lld\n", + (long long)(int)sizeof(((struct ldlm_inodebits *)0)->li_gid)); /* Checks for struct ldlm_flock_wire */ LASSERTF((int)sizeof(struct ldlm_flock_wire) == 32, "found %lld\n", diff --git a/lustre/tests/sanity-dom.sh b/lustre/tests/sanity-dom.sh index 783d45c..ffff7db 100644 --- a/lustre/tests/sanity-dom.sh +++ b/lustre/tests/sanity-dom.sh @@ -194,7 +194,7 @@ run_test sanity "Run sanity with Data-on-MDT files" test_sanityn() { SANITYN_ONLY=${SANITYN_ONLY:-"1 2 4 5 6 7 8 9 10 11 12 14 17 19 20 \ - 23 27 39 51a 51c 51d"} + 23 27 39 51a 51c 51d 107"} SANITYN_REPEAT=${SANITYN_REPEAT:-1} # XXX: to fix 60 ONLY=$SANITYN_ONLY ONLY_REPEAT=$SANITYN_REPEAT OSC="mdc" DOM="yes" \ diff --git a/lustre/tests/sanityn.sh b/lustre/tests/sanityn.sh index 5a70f3b..58081b4 100755 --- a/lustre/tests/sanityn.sh +++ b/lustre/tests/sanityn.sh @@ -5295,7 +5295,7 @@ test_106c() { } run_test 106c "Verify statx attributes mask" -test_107() { # LU-1031 +test_107a() { # LU-1031 dd if=/dev/zero of=$DIR1/$tfile bs=1M count=10 local gid1=14091995 local gid2=16022000 @@ -5308,7 +5308,7 @@ test_107() { # LU-1031 local MULTIPID2=$! kill -USR1 $MULTIPID2 sleep 2 - if [[ `ps h -o comm -p $MULTIPID2` == "" ]]; then + if [[ $(ps h -o comm -p $MULTIPID2) == "" ]]; then error "First grouplock does not block second one" else echo "First grouplock blocks second one" @@ -5317,7 +5317,55 @@ test_107() { # LU-1031 wait $MULTIPID1 wait $MULTIPID2 } -run_test 107 "Basic grouplock conflict" +run_test 107a "Basic grouplock conflict" + +test_107b() { + dd if=/dev/zero of=$DIR1/$tfile bs=1M count=10 + local gid1=14091995 + local gid2=16022000 + + $LFS getstripe $DIR1/$tfile + + multiop_bg_pause $DIR1/$tfile OG${gid1}_g${gid1}c || return 1 + local MULTIPID1=$! + multiop $DIR2/$tfile Or10c & + local MULTIPID2=$! + sleep 2 + + if [[ $(ps h -o comm -p $MULTIPID2) == "" ]]; then + error "Grouplock does not block IO" + else + echo "Grouplock blocks IO" + fi + + multiop $DIR2/$tfile OG${gid2}_g${gid2}c & + local MULTIPID3=$! + sleep 2 + if [[ $(ps h -o comm -p $MULTIPID3) == "" ]]; then + error "First grouplock does not block second one" + else + echo "First grouplock blocks second one" + fi + + kill -USR1 $MULTIPID1 + sleep 2 + + if [[ $(ps h -o comm -p $MULTIPID3) == "" ]]; then + error "Second grouplock thread disappeared" + fi + + if [[ $(ps h -o comm -p $MULTIPID2) == "" ]]; then + error "Second grouplock does not block IO" + else + echo "Second grouplock blocks IO" + fi + + kill -USR1 $MULTIPID3 + wait $MULTIPID1 + wait $MULTIPID2 + wait $MULTIPID3 +} +run_test 107b "Grouplock is added to the head of waiting list" log "cleanup: ======================================================" diff --git a/lustre/utils/wirecheck.c b/lustre/utils/wirecheck.c index 189f136..1ec105c 100644 --- a/lustre/utils/wirecheck.c +++ b/lustre/utils/wirecheck.c @@ -1513,6 +1513,7 @@ check_ldlm_inodebits(void) CHECK_STRUCT(ldlm_inodebits); CHECK_MEMBER(ldlm_inodebits, bits); CHECK_MEMBER(ldlm_inodebits, try_bits); + CHECK_MEMBER(ldlm_inodebits, li_gid); } static void diff --git a/lustre/utils/wiretest.c b/lustre/utils/wiretest.c index d266c04..5084d96 100644 --- a/lustre/utils/wiretest.c +++ b/lustre/utils/wiretest.c @@ -3559,7 +3559,7 @@ void lustre_assert_wire_constants(void) (long long)(int)sizeof(((struct ldlm_extent *)0)->gid)); /* Checks for struct ldlm_inodebits */ - LASSERTF((int)sizeof(struct ldlm_inodebits) == 16, "found %lld\n", + LASSERTF((int)sizeof(struct ldlm_inodebits) == 24, "found %lld\n", (long long)(int)sizeof(struct ldlm_inodebits)); LASSERTF((int)offsetof(struct ldlm_inodebits, bits) == 0, "found %lld\n", (long long)(int)offsetof(struct ldlm_inodebits, bits)); @@ -3569,6 +3569,11 @@ void lustre_assert_wire_constants(void) (long long)(int)offsetof(struct ldlm_inodebits, try_bits)); LASSERTF((int)sizeof(((struct ldlm_inodebits *)0)->try_bits) == 8, "found %lld\n", (long long)(int)sizeof(((struct ldlm_inodebits *)0)->try_bits)); + LASSERTF((int)offsetof(struct ldlm_inodebits, li_gid) == 16, "found %lld\n", + (long long)(int)offsetof(struct ldlm_inodebits, li_gid)); + LASSERTF((int)sizeof(((struct ldlm_inodebits *)0)->li_gid) == 8, "found %lld\n", + (long long)(int)sizeof(((struct ldlm_inodebits *)0)->li_gid)); + /* Checks for struct ldlm_flock_wire */ LASSERTF((int)sizeof(struct ldlm_flock_wire) == 32, "found %lld\n", -- 1.8.3.1