1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2002 Cluster File Systems, Inc.
5 * Author: Phil Schwan <phil@clusterfs.com>
7 * This file is part of Lustre, http://www.lustre.org/
9 * Lustre is free software; you can redistribute it and/or
10 * modify it under the terms of version 2 of the GNU General Public
11 * License as published by the Free Software Foundation.
13 * Lustre is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with Lustre; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #define DEBUG_SUBSYSTEM S_CLASS
25 # include <linux/types.h>
26 # include <linux/random.h>
28 # include <liblustre.h>
31 #include <linux/obd_support.h>
32 #include <linux/lustre_handles.h>
34 static spinlock_t handle_lock = SPIN_LOCK_UNLOCKED;
35 static __u64 handle_base;
37 static struct list_head *handle_hash = NULL;
38 static int handle_count = 0;
40 #define HANDLE_HASH_SIZE (1 << 14)
41 #define HANDLE_HASH_MASK (HANDLE_HASH_SIZE - 1)
43 void class_handle_hash(struct portals_handle *h, portals_handle_addref_cb cb)
45 struct list_head *bucket;
49 LASSERT(list_empty(&h->h_link));
51 spin_lock(&handle_lock);
52 h->h_cookie = handle_base;
53 handle_base += HANDLE_INCR;
54 spin_unlock(&handle_lock);
57 bucket = handle_hash + (h->h_cookie & HANDLE_HASH_MASK);
58 CDEBUG(D_INFO, "adding object %p with handle "LPX64" to hash\n",
61 spin_lock(&handle_lock);
62 list_add(&h->h_link, bucket);
64 spin_unlock(&handle_lock);
68 static void class_handle_unhash_nolock(struct portals_handle *h)
70 if (list_empty(&h->h_link)) {
71 CERROR("removing an already-removed handle ("LPX64")\n",
76 CDEBUG(D_INFO, "removing object %p with handle "LPX64" from hash\n",
80 list_del_init(&h->h_link);
83 void class_handle_unhash(struct portals_handle *h)
85 spin_lock(&handle_lock);
86 class_handle_unhash_nolock(h);
87 spin_unlock(&handle_lock);
90 void *class_handle2object(__u64 cookie)
92 struct list_head *bucket, *tmp;
96 LASSERT(handle_hash != NULL);
98 bucket = handle_hash + (cookie & HANDLE_HASH_MASK);
100 spin_lock(&handle_lock);
101 list_for_each(tmp, bucket) {
102 struct portals_handle *h;
103 h = list_entry(tmp, struct portals_handle, h_link);
105 if (h->h_cookie == cookie) {
111 spin_unlock(&handle_lock);
116 int class_handle_init(void)
118 struct list_head *bucket;
120 LASSERT(handle_hash == NULL);
122 OBD_VMALLOC(handle_hash, sizeof(*handle_hash) * HANDLE_HASH_SIZE);
123 if (handle_hash == NULL)
126 for (bucket = handle_hash + HANDLE_HASH_SIZE - 1; bucket >= handle_hash;
128 INIT_LIST_HEAD(bucket);
130 get_random_bytes(&handle_base, sizeof(handle_base));
131 LASSERT(handle_base != 0ULL);
136 static void cleanup_all_handles(void)
140 spin_lock(&handle_lock);
141 for (i = 0; i < HANDLE_HASH_SIZE; i++) {
142 struct list_head *tmp, *pos;
143 list_for_each_safe(tmp, pos, &(handle_hash[i])) {
144 struct portals_handle *h;
145 h = list_entry(tmp, struct portals_handle, h_link);
147 CERROR("force clean handle "LPX64" addr %p addref %p\n",
148 h->h_cookie, h, h->h_addref);
150 class_handle_unhash_nolock(h);
153 spin_unlock(&handle_lock);
156 void class_handle_cleanup(void)
158 LASSERT(handle_hash != NULL);
160 if (handle_count != 0) {
161 CERROR("handle_count at cleanup: %d\n", handle_count);
162 cleanup_all_handles();
165 OBD_VFREE(handle_hash, sizeof(*handle_hash) * HANDLE_HASH_SIZE);
169 CERROR("leaked %d handles\n", handle_count);