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