ldlm_resource.c

来自「lustre 1.6.5 source code」· C语言 代码 · 共 1,062 行 · 第 1/3 页

C
1,062
字号
/* Args: locked namespace * Returns: newly-allocated, referenced, unlocked resource */static struct ldlm_resource *ldlm_resource_add(struct ldlm_namespace *ns, struct ldlm_resource *parent,                  struct ldlm_res_id name, __u32 hash, ldlm_type_t type){        struct list_head *bucket;        struct ldlm_resource *res, *old_res;        ENTRY;        LASSERTF(type >= LDLM_MIN_TYPE && type < LDLM_MAX_TYPE,                 "type: %d\n", type);        res = ldlm_resource_new();        if (!res)                RETURN(NULL);        res->lr_name = name;        res->lr_namespace = ns;        res->lr_type = type;        res->lr_most_restr = LCK_NL;        spin_lock(&ns->ns_hash_lock);        old_res = ldlm_resource_find(ns, name, hash);        if (old_res) {                /* someone won the race and added the resource before */                ldlm_resource_getref(old_res);                spin_unlock(&ns->ns_hash_lock);                OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof *res);                /* synchronize WRT resource creation */                if (ns->ns_lvbo && ns->ns_lvbo->lvbo_init) {                        down(&old_res->lr_lvb_sem);                        up(&old_res->lr_lvb_sem);                }                RETURN(old_res);        }        /* we won! let's add the resource */        bucket = ns->ns_hash + hash;        list_add(&res->lr_hash, bucket);        ns->ns_resources++;        ldlm_namespace_get_nolock(ns);        if (parent == NULL) {                list_add(&res->lr_childof, &ns->ns_root_list);        } else {                res->lr_parent = parent;                list_add(&res->lr_childof, &parent->lr_children);        }        spin_unlock(&ns->ns_hash_lock);        if (ns->ns_lvbo && ns->ns_lvbo->lvbo_init) {                int rc;                OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CREATE_RESOURCE, 2);                rc = ns->ns_lvbo->lvbo_init(res);                if (rc)                        CERROR("lvbo_init failed for resource "                               LPU64": rc %d\n", name.name[0], rc);                /* we create resource with locked lr_lvb_sem */                up(&res->lr_lvb_sem);        }        RETURN(res);}/* Args: unlocked namespace * Locks: takes and releases ns->ns_lock and res->lr_lock * Returns: referenced, unlocked ldlm_resource or NULL */struct ldlm_resource *ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent,                  struct ldlm_res_id name, ldlm_type_t type, int create){        __u32 hash = ldlm_hash_fn(parent, name);        struct ldlm_resource *res = NULL;        ENTRY;        LASSERT(ns != NULL);        LASSERT(ns->ns_hash != NULL);        LASSERT(name.name[0] != 0);        spin_lock(&ns->ns_hash_lock);        res = ldlm_resource_find(ns, name, hash);        if (res) {                ldlm_resource_getref(res);                spin_unlock(&ns->ns_hash_lock);                /* synchronize WRT resource creation */                if (ns->ns_lvbo && ns->ns_lvbo->lvbo_init) {                        down(&res->lr_lvb_sem);                        up(&res->lr_lvb_sem);                }                RETURN(res);        }        spin_unlock(&ns->ns_hash_lock);        if (create == 0)                RETURN(NULL);        res = ldlm_resource_add(ns, parent, name, hash, type);        RETURN(res);}struct ldlm_resource *ldlm_resource_getref(struct ldlm_resource *res){        LASSERT(res != NULL);        LASSERT(res != LP_POISON);        atomic_inc(&res->lr_refcount);        CDEBUG(D_INFO, "getref res: %p count: %d\n", res,               atomic_read(&res->lr_refcount));        return res;}void __ldlm_resource_putref_final(struct ldlm_resource *res){        struct ldlm_namespace *ns = res->lr_namespace;        LASSERT_SPIN_LOCKED(&ns->ns_hash_lock);        if (!list_empty(&res->lr_granted)) {                ldlm_resource_dump(D_ERROR, res);                LBUG();        }        if (!list_empty(&res->lr_converting)) {                ldlm_resource_dump(D_ERROR, res);                LBUG();        }        if (!list_empty(&res->lr_waiting)) {                ldlm_resource_dump(D_ERROR, res);                LBUG();        }        if (!list_empty(&res->lr_children)) {                ldlm_resource_dump(D_ERROR, res);                LBUG();        }        /* Pass 0 as second argument to not wake up ->ns_waitq yet, will do it         * later. */        ldlm_namespace_put_nolock(ns, 0);        list_del_init(&res->lr_hash);        list_del_init(&res->lr_childof);        ns->ns_resources--;        if (ns->ns_resources == 0)                wake_up(&ns->ns_waitq);}/* Returns 1 if the resource was freed, 0 if it remains. */int ldlm_resource_putref(struct ldlm_resource *res){        struct ldlm_namespace *ns = res->lr_namespace;        int rc = 0;        ENTRY;        CDEBUG(D_INFO, "putref res: %p count: %d\n", res,               atomic_read(&res->lr_refcount) - 1);        LASSERTF(atomic_read(&res->lr_refcount) > 0, "%d",                 atomic_read(&res->lr_refcount));        LASSERTF(atomic_read(&res->lr_refcount) < LI_POISON, "%d",                 atomic_read(&res->lr_refcount));        if (atomic_dec_and_lock(&res->lr_refcount, &ns->ns_hash_lock)) {                __ldlm_resource_putref_final(res);                spin_unlock(&ns->ns_hash_lock);                if (res->lr_lvb_data)                        OBD_FREE(res->lr_lvb_data, res->lr_lvb_len);                OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof *res);                rc = 1;        }        RETURN(rc);}/* Returns 1 if the resource was freed, 0 if it remains. */int ldlm_resource_putref_locked(struct ldlm_resource *res){        int rc = 0;        ENTRY;        CDEBUG(D_INFO, "putref res: %p count: %d\n", res,               atomic_read(&res->lr_refcount) - 1);        LASSERT(atomic_read(&res->lr_refcount) > 0);        LASSERT(atomic_read(&res->lr_refcount) < LI_POISON);        LASSERT(atomic_read(&res->lr_refcount) >= 0);        if (atomic_dec_and_test(&res->lr_refcount)) {                __ldlm_resource_putref_final(res);                if (res->lr_lvb_data)                        OBD_FREE(res->lr_lvb_data, res->lr_lvb_len);                OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof *res);                rc = 1;        }        RETURN(rc);}void ldlm_resource_add_lock(struct ldlm_resource *res, struct list_head *head,                            struct ldlm_lock *lock){        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));        list_add_tail(&lock->l_res_link, head);}void ldlm_resource_insert_lock_after(struct ldlm_lock *original,                                     struct ldlm_lock *new){        struct ldlm_resource *res = original->l_resource;        check_res_locked(res);        ldlm_resource_dump(D_OTHER, res);        CDEBUG(D_OTHER, "About to insert this lock after %p:\n", original);        ldlm_lock_dump(D_OTHER, new, 0);        if (new->l_destroyed) {                CDEBUG(D_OTHER, "Lock destroyed, not adding to resource\n");                goto out;        }        LASSERT(list_empty(&new->l_res_link));        list_add(&new->l_res_link, &original->l_res_link); out:;}void ldlm_resource_unlink_lock(struct ldlm_lock *lock){        int type = lock->l_resource->lr_type;        check_res_locked(lock->l_resource);        if (type == LDLM_IBITS || type == LDLM_PLAIN)                ldlm_unlink_lock_skiplist(lock);        else if (type == LDLM_EXTENT)                ldlm_extent_unlink_lock(lock);        list_del_init(&lock->l_res_link);}void ldlm_res2desc(struct ldlm_resource *res, struct ldlm_resource_desc *desc){        desc->lr_type = res->lr_type;        desc->lr_name = res->lr_name;}void ldlm_dump_all_namespaces(ldlm_side_t client, int level){        struct list_head *tmp;        if (!((libcfs_debug | D_ERROR) & level))                return;        mutex_down(ldlm_namespace_lock(client));        list_for_each(tmp, ldlm_namespace_list(client)) {                struct ldlm_namespace *ns;                ns = list_entry(tmp, struct ldlm_namespace, ns_list_chain);                ldlm_namespace_dump(level, ns);        }        mutex_up(ldlm_namespace_lock(client));}void ldlm_namespace_dump(int level, struct ldlm_namespace *ns){        struct list_head *tmp;        if (!((libcfs_debug | D_ERROR) & level))                return;        CDEBUG(level, "--- Namespace: %s (rc: %d, side: %s)\n",                ns->ns_name, ns->ns_refcount,                ns_is_client(ns) ? "client" : "server");        if (cfs_time_before(cfs_time_current(), ns->ns_next_dump))                return;        spin_lock(&ns->ns_hash_lock);        tmp = ns->ns_root_list.next;        while (tmp != &ns->ns_root_list) {                struct ldlm_resource *res;                res = list_entry(tmp, struct ldlm_resource, lr_childof);                ldlm_resource_getref(res);                spin_unlock(&ns->ns_hash_lock);                lock_res(res);                ldlm_resource_dump(level, res);                unlock_res(res);                                spin_lock(&ns->ns_hash_lock);                tmp = tmp->next;                ldlm_resource_putref_locked(res);        }        ns->ns_next_dump = cfs_time_shift(10);        spin_unlock(&ns->ns_hash_lock);}void ldlm_resource_dump(int level, struct ldlm_resource *res){        struct list_head *tmp;        int pos;        CLASSERT(RES_NAME_SIZE == 4);        if (!((libcfs_debug | D_ERROR) & level))                return;        CDEBUG(level, "--- Resource: %p ("LPU64"/"LPU64"/"LPU64"/"LPU64               ") (rc: %d)\n", res, res->lr_name.name[0], res->lr_name.name[1],               res->lr_name.name[2], res->lr_name.name[3],               atomic_read(&res->lr_refcount));        if (!list_empty(&res->lr_granted)) {                pos = 0;                CDEBUG(level, "Granted locks:\n");                list_for_each(tmp, &res->lr_granted) {                        struct ldlm_lock *lock;                        lock = list_entry(tmp, struct ldlm_lock, l_res_link);                        ldlm_lock_dump(level, lock, ++pos);                }        }        if (!list_empty(&res->lr_converting)) {                pos = 0;                CDEBUG(level, "Converting locks:\n");                list_for_each(tmp, &res->lr_converting) {                        struct ldlm_lock *lock;                        lock = list_entry(tmp, struct ldlm_lock, l_res_link);                        ldlm_lock_dump(level, lock, ++pos);                }        }        if (!list_empty(&res->lr_waiting)) {                pos = 0;                CDEBUG(level, "Waiting locks:\n");                list_for_each(tmp, &res->lr_waiting) {                        struct ldlm_lock *lock;                        lock = list_entry(tmp, struct ldlm_lock, l_res_link);                        ldlm_lock_dump(level, lock, ++pos);                }        }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?