ldlm_lock.c

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

C
1,767
字号
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * *  Copyright (c) 2002, 2003 Cluster File Systems, Inc. *   Author: Peter Braam <braam@clusterfs.com> *   Author: Phil Schwan <phil@clusterfs.com> * *   This file is part of the Lustre file system, http://www.lustre.org *   Lustre is a trademark of Cluster File Systems, Inc. * *   You may have signed or agreed to another license before downloading *   this software.  If so, you are bound by the terms and conditions *   of that agreement, and the following does not apply to you.  See the *   LICENSE file included with this distribution for more information. * *   If you did not agree to a different license, then this copy of Lustre *   is open source software; you can redistribute it and/or modify it *   under the terms of version 2 of the GNU General Public License as *   published by the Free Software Foundation. * *   In either case, Lustre is distributed in the hope that it will be *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   license text for more details. */#define DEBUG_SUBSYSTEM S_LDLM#ifdef __KERNEL__# include <libcfs/libcfs.h># include <linux/lustre_intent.h>#else# include <liblustre.h># include <libcfs/kp30.h>#endif#include <obd_class.h>#include "ldlm_internal.h"//struct lustre_lock ldlm_everything_lock;/* lock's skip list pointers fix mode */#define LDLM_JOIN_NONE          0#define LDLM_MODE_JOIN_RIGHT    1#define LDLM_MODE_JOIN_LEFT     (1 << 1)#define LDLM_POLICY_JOIN_RIGHT  (1 << 2)#define LDLM_POLICY_JOIN_LEFT   (1 << 3)/* lock types */char *ldlm_lockname[] = {        [0] "--",        [LCK_EX] "EX",        [LCK_PW] "PW",        [LCK_PR] "PR",        [LCK_CW] "CW",        [LCK_CR] "CR",        [LCK_NL] "NL",        [LCK_GROUP] "GROUP"};char *ldlm_typename[] = {        [LDLM_PLAIN] "PLN",        [LDLM_EXTENT] "EXT",        [LDLM_FLOCK] "FLK",        [LDLM_IBITS] "IBT",};char *ldlm_it2str(int it){        switch (it) {        case IT_OPEN:                return "open";        case IT_CREAT:                return "creat";        case (IT_OPEN | IT_CREAT):                return "open|creat";        case IT_READDIR:                return "readdir";        case IT_GETATTR:                return "getattr";        case IT_LOOKUP:                return "lookup";        case IT_UNLINK:                return "unlink";        case IT_GETXATTR:                return "getxattr";        default:                CERROR("Unknown intent %d\n", it);                return "UNKNOWN";        }}extern cfs_mem_cache_t *ldlm_lock_slab;static ldlm_processing_policy ldlm_processing_policy_table[] = {        [LDLM_PLAIN] ldlm_process_plain_lock,        [LDLM_EXTENT] ldlm_process_extent_lock,#ifdef __KERNEL__        [LDLM_FLOCK] ldlm_process_flock_lock,#endif        [LDLM_IBITS] ldlm_process_inodebits_lock,};ldlm_processing_policy ldlm_get_processing_policy(struct ldlm_resource *res){        return ldlm_processing_policy_table[res->lr_type];}void ldlm_register_intent(struct ldlm_namespace *ns, ldlm_res_policy arg){        ns->ns_policy = arg;}/* * REFCOUNTED LOCK OBJECTS *//* * Lock refcounts, during creation: *   - one special one for allocation, dec'd only once in destroy *   - one for being a lock that's in-use *   - one for the addref associated with a new lock */struct ldlm_lock *ldlm_lock_get(struct ldlm_lock *lock){        atomic_inc(&lock->l_refc);        return lock;}static void ldlm_lock_free(struct ldlm_lock *lock, size_t size){        LASSERT(size == sizeof(*lock));        OBD_SLAB_FREE(lock, ldlm_lock_slab, sizeof(*lock));}void ldlm_lock_put(struct ldlm_lock *lock){        ENTRY;        LASSERT(lock->l_resource != LP_POISON);        LASSERT(atomic_read(&lock->l_refc) > 0);        if (atomic_dec_and_test(&lock->l_refc)) {                struct ldlm_resource *res;                LDLM_DEBUG(lock, "final lock_put on destroyed lock, freeing it.");                res = lock->l_resource;                LASSERT(lock->l_destroyed);                LASSERT(list_empty(&lock->l_res_link));                LASSERT(list_empty(&lock->l_pending_chain));                atomic_dec(&res->lr_namespace->ns_locks);                ldlm_resource_putref(res);                lock->l_resource = NULL;                if (lock->l_export) {                        class_export_put(lock->l_export);                        lock->l_export = NULL;                }                if (lock->l_lvb_data != NULL)                        OBD_FREE(lock->l_lvb_data, lock->l_lvb_len);                ldlm_interval_free(ldlm_interval_detach(lock));                OBD_FREE_RCU_CB(lock, sizeof(*lock), &lock->l_handle,                       	        ldlm_lock_free);        }        EXIT;}int ldlm_lock_remove_from_lru_nolock(struct ldlm_lock *lock){        int rc = 0;        if (!list_empty(&lock->l_lru)) {                struct ldlm_namespace *ns = lock->l_resource->lr_namespace;                LASSERT(lock->l_resource->lr_type != LDLM_FLOCK);                list_del_init(&lock->l_lru);                ns->ns_nr_unused--;                LASSERT(ns->ns_nr_unused >= 0);                rc = 1;        }        return rc;}int ldlm_lock_remove_from_lru(struct ldlm_lock *lock){        struct ldlm_namespace *ns = lock->l_resource->lr_namespace;        int rc;        ENTRY;        spin_lock(&ns->ns_unused_lock);        rc = ldlm_lock_remove_from_lru_nolock(lock);        spin_unlock(&ns->ns_unused_lock);        EXIT;        return rc;}void ldlm_lock_add_to_lru_nolock(struct ldlm_lock *lock){        struct ldlm_namespace *ns = lock->l_resource->lr_namespace;        lock->l_last_used = cfs_time_current();        LASSERT(list_empty(&lock->l_lru));        list_add_tail(&lock->l_lru, &ns->ns_unused_list);        LASSERT(ns->ns_nr_unused >= 0);        ns->ns_nr_unused++;}void ldlm_lock_add_to_lru(struct ldlm_lock *lock){        struct ldlm_namespace *ns = lock->l_resource->lr_namespace;        ENTRY;        spin_lock(&ns->ns_unused_lock);        ldlm_lock_add_to_lru_nolock(lock);        spin_unlock(&ns->ns_unused_lock);        EXIT;}void ldlm_lock_touch_in_lru(struct ldlm_lock *lock){        struct ldlm_namespace *ns = lock->l_resource->lr_namespace;        ENTRY;        spin_lock(&ns->ns_unused_lock);        if (!list_empty(&lock->l_lru)) {                ldlm_lock_remove_from_lru_nolock(lock);                ldlm_lock_add_to_lru_nolock(lock);        }        spin_unlock(&ns->ns_unused_lock);        EXIT;}/* This used to have a 'strict' flag, which recovery would use to mark an * in-use lock as needing-to-die.  Lest I am ever tempted to put it back, I * shall explain why it's gone: with the new hash table scheme, once you call * ldlm_lock_destroy, you can never drop your final references on this lock. * Because it's not in the hash table anymore.  -phil */int ldlm_lock_destroy_internal(struct ldlm_lock *lock){        ENTRY;        if (lock->l_readers || lock->l_writers) {                LDLM_ERROR(lock, "lock still has references");                ldlm_lock_dump(D_ERROR, lock, 0);                LBUG();        }        if (!list_empty(&lock->l_res_link)) {                LDLM_ERROR(lock, "lock still on resource");                ldlm_lock_dump(D_ERROR, lock, 0);                LBUG();        }        if (lock->l_destroyed) {                LASSERT(list_empty(&lock->l_lru));                EXIT;                return 0;        }        lock->l_destroyed = 1;        if (lock->l_export)                spin_lock(&lock->l_export->exp_ldlm_data.led_lock);        list_del_init(&lock->l_export_chain);        if (lock->l_export)                spin_unlock(&lock->l_export->exp_ldlm_data.led_lock);        ldlm_lock_remove_from_lru(lock);        class_handle_unhash(&lock->l_handle);#if 0        /* Wake anyone waiting for this lock */        /* FIXME: I should probably add yet another flag, instead of using         * l_export to only call this on clients */        if (lock->l_export)                class_export_put(lock->l_export);        lock->l_export = NULL;        if (lock->l_export && lock->l_completion_ast)                lock->l_completion_ast(lock, 0);#endif        EXIT;        return 1;}void ldlm_lock_destroy(struct ldlm_lock *lock){        int first;        ENTRY;        lock_res_and_lock(lock);        first = ldlm_lock_destroy_internal(lock);        unlock_res_and_lock(lock);        /* drop reference from hashtable only for first destroy */        if (first)                LDLM_LOCK_PUT(lock);        EXIT;}void ldlm_lock_destroy_nolock(struct ldlm_lock *lock){        int first;        ENTRY;        first = ldlm_lock_destroy_internal(lock);        /* drop reference from hashtable only for first destroy */        if (first)                LDLM_LOCK_PUT(lock);        EXIT;}/* this is called by portals_handle2object with the handle lock taken */static void lock_handle_addref(void *lock){        LDLM_LOCK_GET((struct ldlm_lock *)lock);}/* * usage: pass in a resource on which you have done ldlm_resource_get *        pass in a parent lock on which you have done a ldlm_lock_get *        after return, ldlm_*_put the resource and parent * returns: lock with refcount 2 - one for current caller and one for remote */static struct ldlm_lock *ldlm_lock_new(struct ldlm_resource *resource){        struct ldlm_lock *lock;        ENTRY;        if (resource == NULL)                LBUG();        OBD_SLAB_ALLOC(lock, ldlm_lock_slab, CFS_ALLOC_IO, sizeof(*lock));        if (lock == NULL)                RETURN(NULL);        spin_lock_init(&lock->l_lock);        lock->l_resource = ldlm_resource_getref(resource);        atomic_set(&lock->l_refc, 2);        CFS_INIT_LIST_HEAD(&lock->l_res_link);        CFS_INIT_LIST_HEAD(&lock->l_lru);        CFS_INIT_LIST_HEAD(&lock->l_export_chain);        CFS_INIT_LIST_HEAD(&lock->l_pending_chain);        CFS_INIT_LIST_HEAD(&lock->l_bl_ast);        CFS_INIT_LIST_HEAD(&lock->l_cp_ast);        cfs_waitq_init(&lock->l_waitq);        lock->l_blocking_lock = NULL;        lock->l_sl_mode.prev = NULL;        lock->l_sl_mode.next = NULL;        lock->l_sl_policy.prev = NULL;        lock->l_sl_policy.next = NULL;        atomic_inc(&resource->lr_namespace->ns_locks);        CFS_INIT_LIST_HEAD(&lock->l_handle.h_link);        class_handle_hash(&lock->l_handle, lock_handle_addref);        CFS_INIT_LIST_HEAD(&lock->l_extents_list);        spin_lock_init(&lock->l_extents_list_lock);        CFS_INIT_LIST_HEAD(&lock->l_cache_locks_list);

⌨️ 快捷键说明

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