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 + -
显示快捷键?