Add lock match flag LDLM_MATCH_SKIP_UNUSED to skip match unused lock.
Signed-off-by: Bobi Jam <bobijam@whamcloud.com>
Change-Id: I31d8f051b837a5b00cee6f2bc1ad9782acc62892
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/55508
Reviewed-by: Sebastien Buisson <sbuisson@ddn.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
LDLM_MATCH_AST_ANY = BIT(2),
LDLM_MATCH_RIGHT = BIT(3),
LDLM_MATCH_GROUP = BIT(4),
+ LDLM_MATCH_SKIP_UNUSED = BIT(5),
};
#ifdef HAVE_INTERVAL_TREE_CACHED
enum ldlm_type type,
union ldlm_policy_data *policy,
enum ldlm_mode mode,
- struct lustre_handle *lh,
- enum ldlm_match_flags match_flags);
+ enum ldlm_match_flags match_flags,
+ struct lustre_handle *lh);
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,
+ enum ldlm_match_flags m_flags,
struct lustre_handle *lh)
{
return ldlm_lock_match_with_skip(ns, flags, 0, res_id, type, policy,
- mode, lh, 0);
+ mode, m_flags, lh);
}
struct ldlm_lock *search_itree(struct ldlm_resource *res,
struct ldlm_match_data *data);
enum ldlm_type type,
union ldlm_policy_data *policy,
enum ldlm_mode mode,
+ enum ldlm_match_flags match_flags,
struct lustre_handle *lockh);
int (*m_cancel_unused)(struct obd_export *exp, const struct lu_fid *fid,
enum ldlm_type type,
union ldlm_policy_data *policy,
enum ldlm_mode mode,
+ enum ldlm_match_flags match_flags,
struct lustre_handle *lockh)
{
int rc;
return exp->exp_obd->obd_type->typ_md_ops->m_lock_match(exp, flags,
fid, type,
policy, mode,
+ match_flags,
lockh);
}
lock->l_readers == 0 && lock->l_writers == 0)
return false;
+ if (data->lmd_match & LDLM_MATCH_SKIP_UNUSED &&
+ lock->l_readers == 0 && lock->l_writers == 0)
+ return false;
+
if (!(lock->l_req_mode & *data->lmd_mode))
return false;
* If 'flags' contains LDLM_FL_TEST_LOCK, then don't actually reference a lock,
* just tell us if we would have matched.
*
+ * If @match_flags contains LDLM_MATCH_UNREF, then we don't match unreferenced
+ * locks
+ * If @match_flags contains LDLM_MATCH_AST, then we don't match lock without
+ * ast_data
+ * If @match_flags contains LDLM_MATCH_AST_ANY, then we'd match lock with
+ * ast_data
+ * If @match_flags contains LDLM_MATCH_RIGHT, then we'd match extent lock at
+ * the right region for the desired lock
+ * If @match_flags contains LDLM_MATCH_GROUP, then we'd match group lock
+ * If @match_flags contains LDLM_MATCH_SKIP_UNUSED, then we don't match any
+ * unused locks
+ *
* \retval 1 if it finds an already-existing lock that is compatible; in this
* case, lockh is filled in with a addref()ed lock
*
enum ldlm_type type,
union ldlm_policy_data *policy,
enum ldlm_mode mode,
- struct lustre_handle *lockh,
- enum ldlm_match_flags match_flags)
+ enum ldlm_match_flags match_flags,
+ struct lustre_handle *lockh)
{
struct ldlm_match_data data = {
.lmd_old = NULL,
struct obd_export *exp = ll_i2mdexp(i_dir);
enum mds_ibits_locks ibits = MDS_INODELOCK_LOOKUP;
- if (ll_have_md_lock(exp, i_dir, &ibits, LCK_MINMODE))
+ if (ll_have_md_lock(exp, i_dir, &ibits, LCK_MINMODE, 0))
pfid = *ll_inode2fid(i_dir);
}
dput(parent);
/* LU-4398: do not cache write open lock if the file has exec bit */
if ((lockmode == LCK_CW && inode->i_mode & 0111) ||
!md_lock_match(ll_i2mdexp(inode), flags, ll_inode2fid(inode),
- LDLM_IBITS, &policy, lockmode, &lockh))
+ LDLM_IBITS, &policy, lockmode, 0, &lockh))
rc = ll_md_real_close(inode, lfd->fd_omode);
out:
* - if found clear the common lock bits in *bits
* - the bits not found, are kept in *bits
* \param inode [IN]
- * \param bits [IN] searched lock bits [IN]
- * \param l_req_mode [IN] searched lock mode
+ * \param bits [IN] searched lock bits [IN]
+ * \param l_req_mode [IN] searched lock mode
+ * \param match_flags [IN] match flags
* \retval boolean, true iff all bits are found
*/
int ll_have_md_lock(struct obd_export *exp, struct inode *inode,
- enum mds_ibits_locks *bits, enum ldlm_mode l_req_mode)
+ enum mds_ibits_locks *bits, enum ldlm_mode l_req_mode,
+ enum ldlm_match_flags match_flags)
{
struct lustre_handle lockh;
union ldlm_policy_data policy;
continue;
if (md_lock_match(exp, flags, fid, LDLM_IBITS, &policy, mode,
- &lockh)) {
+ match_flags, &lockh)) {
struct ldlm_lock *lock;
lock = ldlm_handle2lock(&lockh);
CDEBUG(D_INFO, "trying to match res "DFID"\n", PFID(fid));
rc = md_lock_match(ll_i2mdexp(inode), LDLM_FL_BLOCK_GRANTED|flags,
- fid, LDLM_IBITS, &policy, mode, lockh);
+ fid, LDLM_IBITS, &policy, mode, 0, lockh);
RETURN(rc);
}
const struct file_operations *ll_select_file_operations(struct ll_sb_info *sbi);
extern int ll_have_md_lock(struct obd_export *exp, struct inode *inode,
enum mds_ibits_locks *bits,
- enum ldlm_mode l_req_mode);
+ enum ldlm_mode l_req_mode,
+ enum ldlm_match_flags match_flags);
extern enum ldlm_mode ll_take_md_lock(struct inode *inode, __u64 bits,
struct lustre_handle *lockh, __u64 flags,
enum ldlm_mode mode);
*/
if (bits & MDS_INODELOCK_OPEN)
ll_have_md_lock(lock->l_conn_export, inode, &bits,
- lock->l_req_mode);
+ lock->l_req_mode, 0);
if (bits & MDS_INODELOCK_OPEN) {
fmode_t fmode;
if (bits & (MDS_INODELOCK_LOOKUP | MDS_INODELOCK_UPDATE |
MDS_INODELOCK_LAYOUT | MDS_INODELOCK_PERM |
MDS_INODELOCK_DOM))
- ll_have_md_lock(lock->l_conn_export, inode, &bits, LCK_MINMODE);
+ ll_have_md_lock(lock->l_conn_export, inode, &bits, LCK_MINMODE,
+ 0);
if (bits & MDS_INODELOCK_DOM) {
rc = ll_dom_lock_cancel(inode, lock);
unlock_res_and_lock(lock);
inode = ll_inode_from_resource_lock(lock);
- ll_have_md_lock(lock->l_conn_export, inode, &bits, mode);
+ ll_have_md_lock(lock->l_conn_export, inode, &bits, mode, 0);
iput(inode);
return !!(bits);
}
lmv_lock_match(struct obd_export *exp, __u64 flags,
const struct lu_fid *fid, enum ldlm_type type,
union ldlm_policy_data *policy,
- enum ldlm_mode mode, struct lustre_handle *lockh)
+ enum ldlm_mode mode, enum ldlm_match_flags match_flags,
+ struct lustre_handle *lockh)
{
struct obd_device *obd = exp->exp_obd;
struct lmv_obd *lmv = &obd->u.lmv;
if (!tgt || !tgt->ltd_exp || !tgt->ltd_active)
continue;
rc = md_lock_match(tgt->ltd_exp, flags, fid, type,
- policy, mode, lockh);
+ policy, mode, match_flags, lockh);
if (rc)
break;
}
tgt = lmv_fid2tgt(lmv, fid);
if (!IS_ERR(tgt) && tgt->ltd_exp && tgt->ltd_active)
rc = md_lock_match(tgt->ltd_exp, flags, fid, type,
- policy, mode, lockh);
+ policy, mode, match_flags, lockh);
}
CDEBUG(D_INODE, "Lock match for "DFID": %d\n", PFID(fid), rc);
union ldlm_policy_data *policy,
enum ldlm_mode mode, __u64 *flags,
struct osc_object *obj,
- struct lustre_handle *lockh,
- enum ldlm_match_flags match_flags)
+ enum ldlm_match_flags match_flags,
+ struct lustre_handle *lockh)
{
struct obd_device *obd = exp->exp_obd;
__u64 lflags = *flags;
ENTRY;
rc = ldlm_lock_match_with_skip(obd->obd_namespace, lflags, 0,
- res_id, type, policy, mode, lockh, match_flags);
+ res_id, type, policy, mode, match_flags, lockh);
if (rc == 0 || lflags & LDLM_FL_TEST_LOCK)
RETURN(rc);
* 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, match_flags);
+ obj, match_flags, &lockh);
if (mode != 0) {
lock = ldlm_handle2lock(&lockh);
/* RACE: the lock is cancelled so let's try again */
match_flags = LDLM_MATCH_GROUP;
mode = ldlm_lock_match_with_skip(obd->obd_namespace, search_flags, 0,
res_id, einfo->ei_type, policy, mode,
- &lockh, match_flags);
+ match_flags, &lockh);
if (mode) {
struct ldlm_lock *matched;
flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_LVB_READY;
mode = mdc_dom_lock_match(env, exp, resid, LDLM_IBITS, policy,
LCK_PR | LCK_PW | LCK_GROUP,
- &flags, osc, &lockh, 0);
+ &flags, osc, 0, &lockh);
fmkey->lfik_oa.o_valid |= OBD_MD_FLFLAGS;
if (mode) { /* lock is cached on client */
fmkey->lfik_oa.o_flags &= ~OBD_FL_SRVLOCK;
enum ldlm_mode mdc_lock_match(struct obd_export *exp, __u64 flags,
const struct lu_fid *fid, enum ldlm_type type,
union ldlm_policy_data *policy,
- enum ldlm_mode mode, struct lustre_handle *lockh);
+ enum ldlm_mode mode,
+ enum ldlm_match_flags match_flags,
+ struct lustre_handle *lockh);
#define MDC_CHANGELOG_DEV_COUNT LMV_MAX_STRIPE_COUNT
enum ldlm_mode mdc_lock_match(struct obd_export *exp, __u64 flags,
const struct lu_fid *fid, enum ldlm_type type,
union ldlm_policy_data *policy,
- enum ldlm_mode mode, struct lustre_handle *lockh)
+ enum ldlm_mode mode,
+ enum ldlm_match_flags match_flags,
+ struct lustre_handle *lockh)
{
struct ldlm_res_id res_id;
enum ldlm_mode rc;
/* 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);
+ &res_id, type, policy, mode, match_flags, lockh);
RETURN(rc);
}
memcpy(&old_lock, lockh, sizeof(*lockh));
if (ldlm_lock_match(NULL, LDLM_FL_BLOCK_GRANTED, NULL,
- LDLM_IBITS, &policy, LCK_NL, &old_lock)) {
+ LDLM_IBITS, &policy, LCK_NL, 0, &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;
mode = mdc_lock_match(exp, LDLM_FL_BLOCK_GRANTED, fid,
LDLM_IBITS, &policy,
- LCK_CR | LCK_CW | LCK_PR | LCK_PW,
+ LCK_CR | LCK_CW | LCK_PR | LCK_PW, 0,
&lockh);
}
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);
+ LCK_PW, 0, &lockh);
/* There is no PW lock on this object; finished. */
if (mode == 0)
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);
+ lm, 0, &lockh);
/* There is no other PW lock on this object; finished. */
if (mode == 0)
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);
+ LCK_PR | LCK_PW, 0, &lockh);
fmkey->lfik_oa.o_valid |= OBD_MD_FLFLAGS;
if (mode) { /* lock is cached on client */
fmkey->lfik_oa.o_flags &= ~OBD_FL_SRVLOCK;
match_flags = LDLM_MATCH_GROUP;
mode = ldlm_lock_match_with_skip(obd->obd_namespace, search_flags, 0,
res_id, einfo->ei_type, policy, mode,
- &lockh, match_flags);
+ match_flags, &lockh);
if (mode) {
struct ldlm_lock *matched;
/* Next, search for already existing extent locks that will cover us */
rc = ldlm_lock_match_with_skip(obd->obd_namespace, lflags, 0,
- res_id, type, policy, mode, lockh,
- match_flags);
+ res_id, type, policy, mode,
+ match_flags, lockh);
if (rc == 0 || lflags & LDLM_FL_TEST_LOCK)
RETURN(rc);