ldlm_lock.c
来自「lustre 1.6.5 source code」· C语言 代码 · 共 1,767 行 · 第 1/5 页
C
1,767 行
struct ldlm_lock **lockp){ struct list_head *tmp, *tmp_tail; struct ldlm_lock *lock, *mode_head_lock; int rc = LDLM_JOIN_NONE; ENTRY; list_for_each(tmp, queue) { lock = list_entry(tmp, struct ldlm_lock, l_res_link); if (lock->l_req_mode != req->l_req_mode) { if (LDLM_SL_HEAD(&lock->l_sl_mode)) tmp = &list_entry(lock->l_sl_mode.next, struct ldlm_lock, l_sl_mode)->l_res_link; continue; } /* found the same mode group */ if (lock->l_resource->lr_type == LDLM_PLAIN) { *lockp = lock; rc = LDLM_MODE_JOIN_RIGHT; GOTO(out, rc); } else if (lock->l_resource->lr_type == LDLM_IBITS) { tmp_tail = tmp; if (LDLM_SL_HEAD(&lock->l_sl_mode)) tmp_tail = &list_entry(lock->l_sl_mode.next, struct ldlm_lock, l_sl_mode)->l_res_link; mode_head_lock = lock; for (;;) { if (lock->l_policy_data.l_inodebits.bits == req->l_policy_data.l_inodebits.bits) { /* matched policy lock is found */ *lockp = lock; rc |= LDLM_POLICY_JOIN_RIGHT; /* if the policy group head is also a * mode group head or a single mode * group lock */ if (LDLM_SL_HEAD(&lock->l_sl_mode) || (tmp == tmp_tail && LDLM_SL_EMPTY(&lock->l_sl_mode))) rc |= LDLM_MODE_JOIN_RIGHT; GOTO(out, rc); } if (LDLM_SL_HEAD(&lock->l_sl_policy)) tmp = &list_entry(lock->l_sl_policy.next, struct ldlm_lock, l_sl_policy)->l_res_link; if (tmp == tmp_tail) break; else tmp = tmp->next; lock = list_entry(tmp, struct ldlm_lock, l_res_link); } /* for all locks in the matched mode group */ /* no matched policy group is found, insert before * the mode group head lock */ *lockp = mode_head_lock; rc = LDLM_MODE_JOIN_RIGHT; GOTO(out, rc); } else { LDLM_ERROR(lock, "is not LDLM_PLAIN or LDLM_IBITS lock"); LBUG(); } } /* no matched mode group is found, append to the end */ *lockp = NULL; rc = LDLM_JOIN_NONE; EXIT;out: return rc;}static void ldlm_granted_list_add_lock(struct ldlm_lock *lock, struct ldlm_lock *lockp, int join){ struct ldlm_resource *res = lock->l_resource; ENTRY; LASSERT(lockp || join == LDLM_JOIN_NONE); check_res_locked(res); ldlm_resource_dump(D_OTHER, res); CDEBUG(D_OTHER, "About to add this lock:\n"); ldlm_lock_dump(D_OTHER, lock, 0); if (lock->l_destroyed) { CDEBUG(D_OTHER, "Lock destroyed, not adding to resource\n"); return; } LASSERT(list_empty(&lock->l_res_link)); if (!lockp) list_add_tail(&lock->l_res_link, &lock->l_resource->lr_granted); else if ((join & LDLM_MODE_JOIN_LEFT) || (join & LDLM_POLICY_JOIN_LEFT)) list_add(&lock->l_res_link, &lockp->l_res_link); else list_add_tail(&lock->l_res_link, &lockp->l_res_link); /* fix skip lists */ if (join & LDLM_MODE_JOIN_RIGHT) { LASSERT(! LDLM_SL_TAIL(&lockp->l_sl_mode)); if (LDLM_SL_EMPTY(&lockp->l_sl_mode)) { lock->l_sl_mode.next = &lockp->l_sl_mode; lockp->l_sl_mode.prev = &lock->l_sl_mode; } else if (LDLM_SL_HEAD(&lockp->l_sl_mode)) { lock->l_sl_mode.next = lockp->l_sl_mode.next; lockp->l_sl_mode.next = NULL; lock->l_sl_mode.next->prev = &lock->l_sl_mode; } } else if (join & LDLM_MODE_JOIN_LEFT) { LASSERT(! LDLM_SL_HEAD(&lockp->l_sl_mode)); if (LDLM_SL_EMPTY(&lockp->l_sl_mode)) { lock->l_sl_mode.prev = &lockp->l_sl_mode; lockp->l_sl_mode.next = &lock->l_sl_mode; } else if (LDLM_SL_TAIL(&lockp->l_sl_mode)) { lock->l_sl_mode.prev = lockp->l_sl_mode.prev; lockp->l_sl_mode.prev = NULL; lock->l_sl_mode.prev->next = &lock->l_sl_mode; } } if (join & LDLM_POLICY_JOIN_RIGHT) { LASSERT(! LDLM_SL_TAIL(&lockp->l_sl_policy)); if (LDLM_SL_EMPTY(&lockp->l_sl_policy)) { lock->l_sl_policy.next = &lockp->l_sl_policy; lockp->l_sl_policy.prev = &lock->l_sl_policy; } else if (LDLM_SL_HEAD(&lockp->l_sl_policy)) { lock->l_sl_policy.next = lockp->l_sl_policy.next; lockp->l_sl_policy.next = NULL; lock->l_sl_policy.next->prev = &lock->l_sl_policy; } } else if (join & LDLM_POLICY_JOIN_LEFT) { LASSERT(! LDLM_SL_HEAD(&lockp->l_sl_policy)); if (LDLM_SL_EMPTY(&lockp->l_sl_policy)) { lock->l_sl_policy.prev = &lockp->l_sl_policy; lockp->l_sl_policy.next = &lock->l_sl_policy; } else if (LDLM_SL_TAIL(&lockp->l_sl_policy)) { lock->l_sl_policy.prev = lockp->l_sl_policy.prev; lockp->l_sl_policy.prev = NULL; lock->l_sl_policy.prev->next = &lock->l_sl_policy; } } EXIT;}static void ldlm_grant_lock_with_skiplist(struct ldlm_lock *lock){ int join = LDLM_JOIN_NONE; struct ldlm_lock *lockp = NULL; ENTRY; LASSERT(lock->l_req_mode == lock->l_granted_mode); join = search_granted_lock(&lock->l_resource->lr_granted, lock, &lockp); ldlm_granted_list_add_lock(lock, lockp, join); EXIT;}/* NOTE: called by * - ldlm_lock_enqueue * - ldlm_reprocess_queue * - ldlm_lock_convert * * must be called with lr_lock held */void ldlm_grant_lock(struct ldlm_lock *lock, struct list_head *work_list){ struct ldlm_resource *res = lock->l_resource; ENTRY; check_res_locked(res); lock->l_granted_mode = lock->l_req_mode; if (res->lr_type == LDLM_PLAIN || res->lr_type == LDLM_IBITS) ldlm_grant_lock_with_skiplist(lock); else if (res->lr_type == LDLM_EXTENT) ldlm_extent_add_lock(res, lock); else ldlm_resource_add_lock(res, &res->lr_granted, lock); if (lock->l_granted_mode < res->lr_most_restr) res->lr_most_restr = lock->l_granted_mode; if (work_list && lock->l_completion_ast != NULL) ldlm_add_ast_work_item(lock, NULL, work_list); ldlm_pool_add(&res->lr_namespace->ns_pool, lock); EXIT;}/* returns a referenced lock or NULL. See the flag descriptions below, in the * comment above ldlm_lock_match */static struct ldlm_lock *search_queue(struct list_head *queue, ldlm_mode_t *mode, ldlm_policy_data_t *policy, struct ldlm_lock *old_lock, int flags){ struct ldlm_lock *lock; struct list_head *tmp; list_for_each(tmp, queue) { ldlm_mode_t match; lock = list_entry(tmp, struct ldlm_lock, l_res_link); if (lock == old_lock) continue; /* llite sometimes wants to match locks that will be * canceled when their users drop, but we allow it to match * if it passes in CBPENDING and the lock still has users. * this is generally only going to be used by children * whose parents already hold a lock so forward progress * can still happen. */ if (lock->l_flags & LDLM_FL_CBPENDING && !(flags & LDLM_FL_CBPENDING)) continue; if (lock->l_flags & LDLM_FL_CBPENDING && lock->l_readers == 0 && lock->l_writers == 0) continue; if (!(lock->l_req_mode & *mode)) continue; match = lock->l_req_mode; if (lock->l_resource->lr_type == LDLM_EXTENT && (lock->l_policy_data.l_extent.start > policy->l_extent.start || lock->l_policy_data.l_extent.end < policy->l_extent.end)) continue; if (unlikely(match == LCK_GROUP) && lock->l_resource->lr_type == LDLM_EXTENT && lock->l_policy_data.l_extent.gid != policy->l_extent.gid) continue; /* We match if we have existing lock with same or wider set of bits. */ if (lock->l_resource->lr_type == LDLM_IBITS && ((lock->l_policy_data.l_inodebits.bits & policy->l_inodebits.bits) != policy->l_inodebits.bits)) continue; if (lock->l_destroyed || (lock->l_flags & LDLM_FL_FAILED)) continue; if ((flags & LDLM_FL_LOCAL_ONLY) && !(lock->l_flags & LDLM_FL_LOCAL)) continue; if (flags & LDLM_FL_TEST_LOCK) { LDLM_LOCK_GET(lock); ldlm_lock_touch_in_lru(lock); } else { ldlm_lock_addref_internal_nolock(lock, match); } *mode = match; return lock; } return NULL;}void ldlm_lock_allow_match(struct ldlm_lock *lock){ lock_res_and_lock(lock); lock->l_flags |= LDLM_FL_LVB_READY; cfs_waitq_signal(&lock->l_waitq); unlock_res_and_lock(lock);}/* Can be called in two ways: * * If 'ns' is NULL, then lockh describes an existing lock that we want to look * for a duplicate of. * * Otherwise, all of the fields must be filled in, to match against. * * If 'flags' contains LDLM_FL_LOCAL_ONLY, then only match local locks on the * server (ie, connh is NULL) * If 'flags' contains LDLM_FL_BLOCK_GRANTED, then only locks on the granted * list will be considered * If 'flags' contains LDLM_FL_CBPENDING, then locks that have been marked * to be canceled can still be matched as long as they still have reader * or writer refernces * If 'flags' contains LDLM_FL_TEST_LOCK, then don't actually reference a lock, * just tell us if we would have matched. * * Returns 1 if it finds an already-existing lock that is compatible; in this * case, lockh is filled in with a addref()ed lock */ldlm_mode_t ldlm_lock_match(struct ldlm_namespace *ns, int flags, struct ldlm_res_id *res_id, ldlm_type_t type, ldlm_policy_data_t *policy, ldlm_mode_t mode, struct lustre_handle *lockh){ struct ldlm_resource *res; struct ldlm_lock *lock, *old_lock = NULL; int rc = 0; ENTRY; if (ns == NULL) { old_lock = ldlm_handle2lock(lockh); LASSERT(old_lock); ns = old_lock->l_resource->lr_namespace; res_id = &old_lock->l_resource->lr_name; type = old_lock->l_resource->lr_type; mode = old_lock->l_req_mode; } res = ldlm_resource_get(ns, NULL, *res_id, type, 0); if (res == NULL) { LASSERT(old_lock == NULL); RETURN(0); } lock_res(res); lock = search_queue(&res->lr_granted, &mode, policy, old_lock, flags); if (lock != NULL) GOTO(out, rc = 1); if (flags & LDLM_FL_BLOCK_GRANTED) GOTO(out, rc = 0); lock = search_queue(&res->lr_converting, &mode, policy, old_lock, flags); if (lock != NULL) GOTO(out, rc = 1); lock = search_queue(&res->lr_waiting, &mode, policy, old_lock, flags); if (lock != NULL) GOTO(out, rc = 1); EXIT; out: unlock_res(res); ldlm_resource_putref(res); if (lock) { ldlm_lock2handle(lock, lockh); if ((flags & LDLM_FL_LVB_READY) && (!(lock->l_flags & LDLM_FL_LVB_READY))) { struct l_wait_info lwi; if (lock->l_completion_ast) { int err = lock->l_completion_ast(lock,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?