1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * Copyright (C) 2006 Cluster File Systems, Inc.
8 * This file is part of the Lustre file system, http://www.lustre.org
9 * Lustre is a trademark of Cluster File Systems, Inc.
11 * You may have signed or agreed to another license before downloading
12 * this software. If so, you are bound by the terms and conditions
13 * of that agreement, and the following does not apply to you. See the
14 * LICENSE file included with this distribution for more information.
16 * If you did not agree to a different license, then this copy of Lustre
17 * is open source software; you can redistribute it and/or modify it
18 * under the terms of version 2 of the GNU General Public License as
19 * published by the Free Software Foundation.
21 * In either case, Lustre is distributed in the hope that it will be
22 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
23 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * license text for more details.
26 * These are the only exported functions, they provide some generic
27 * infrastructure for managing object devices
30 #define DEBUG_SUBSYSTEM S_CLASS
32 # define EXPORT_SYMTAB
35 #include <linux/seq_file.h>
36 #include <linux/module.h>
37 #include <linux/obd_support.h>
38 #include <linux/lu_object.h>
40 #include <libcfs/list.h>
42 static void lu_object_free(struct lu_context *ctx, struct lu_object *o);
44 void lu_object_put(struct lu_context *ctxt, struct lu_object *o)
46 struct lu_object_header *top;
50 site = o->lo_dev->ld_site;
51 spin_lock(&site->ls_guard);
52 if (-- top->loh_ref == 0) {
53 list_for_each_entry(o, &top->loh_layers, lo_linkage) {
54 if (lu_object_ops(o)->ldo_object_release != NULL)
55 lu_object_ops(o)->ldo_object_release(ctxt, o);
58 if (lu_object_is_dying(top)) {
59 hlist_del_init(&top->loh_hash);
60 list_del_init(&top->loh_lru);
63 spin_unlock(&site->ls_guard);
64 if (lu_object_is_dying(top))
66 * Object was already removed from hash and lru above, can
69 lu_object_free(ctxt, o);
71 EXPORT_SYMBOL(lu_object_put);
73 struct lu_object *lu_object_alloc(struct lu_context *ctxt,
74 struct lu_site *s, const struct lu_fid *f)
76 struct lu_object *scan;
77 struct lu_object *top;
81 top = s->ls_top_dev->ld_ops->ldo_object_alloc(ctxt, s->ls_top_dev);
84 *lu_object_fid(top) = *f;
87 list_for_each_entry(scan,
88 &top->lo_header->loh_layers, lo_linkage) {
89 if (scan->lo_flags & LU_OBJECT_ALLOCATED)
92 scan->lo_header = top->lo_header;
93 result = lu_object_ops(scan)->ldo_object_init(ctxt,
96 lu_object_free(ctxt, top);
97 RETURN(ERR_PTR(result));
99 scan->lo_flags |= LU_OBJECT_ALLOCATED;
102 s->ls_stats.s_created ++;
106 static void lu_object_free(struct lu_context *ctx, struct lu_object *o)
108 struct list_head splice;
109 struct lu_object *scan;
111 list_for_each_entry_reverse(scan,
112 &o->lo_header->loh_layers, lo_linkage) {
113 if (lu_object_ops(scan)->ldo_object_delete != NULL)
114 lu_object_ops(scan)->ldo_object_delete(ctx, scan);
116 -- o->lo_dev->ld_site->ls_total;
117 INIT_LIST_HEAD(&splice);
118 list_splice_init(&o->lo_header->loh_layers, &splice);
119 while (!list_empty(&splice)) {
120 o = container_of(splice.next, struct lu_object, lo_linkage);
121 list_del_init(&o->lo_linkage);
122 LASSERT(lu_object_ops(o)->ldo_object_free != NULL);
123 lu_object_ops(o)->ldo_object_free(ctx, o);
127 void lu_site_purge(struct lu_context *ctx, struct lu_site *s, int nr)
129 struct list_head dispose;
130 struct lu_object_header *h;
131 struct lu_object_header *temp;
133 INIT_LIST_HEAD(&dispose);
134 spin_lock(&s->ls_guard);
135 list_for_each_entry_safe(h, temp, &s->ls_lru, loh_lru) {
140 hlist_del_init(&h->loh_hash);
141 list_move(&h->loh_lru, &dispose);
143 spin_unlock(&s->ls_guard);
144 while (!list_empty(&dispose)) {
145 h = container_of(dispose.next,
146 struct lu_object_header, loh_lru);
147 list_del_init(&h->loh_lru);
148 lu_object_free(ctx, lu_object_top(h));
149 s->ls_stats.s_lru_purged ++;
152 EXPORT_SYMBOL(lu_site_purge);
154 int lu_object_print(struct lu_context *ctx,
155 struct seq_file *f, const struct lu_object *o)
157 static char ruler[] = "........................................";
158 const struct lu_object *scan;
164 list_for_each_entry_continue(scan, &o->lo_linkage, lo_linkage) {
165 depth = scan->lo_depth;
166 if (depth <= o->lo_depth && scan != o)
168 LASSERT(lu_object_ops(scan)->ldo_object_print != NULL);
169 nob += seq_printf(f, "%*.*s", depth, depth, ruler);
170 nob += lu_object_ops(scan)->ldo_object_print(ctx, f, scan);
171 nob += seq_printf(f, "\n");
175 EXPORT_SYMBOL(lu_object_print);
177 static struct lu_object *htable_lookup(struct lu_site *s,
178 const struct hlist_head *bucket,
179 const struct lu_fid *f)
181 struct lu_object_header *h;
182 struct hlist_node *scan;
184 hlist_for_each_entry(h, scan, bucket, loh_hash) {
185 s->ls_stats.s_cache_check ++;
186 if (lu_fid_eq(&h->loh_fid, f) && !lu_object_is_dying(h)) {
187 /* bump reference count... */
188 if (h->loh_ref ++ == 0)
190 /* and move to the head of the LRU */
191 list_move_tail(&h->loh_lru, &s->ls_lru);
192 s->ls_stats.s_cache_hit ++;
193 return lu_object_top(h);
196 s->ls_stats.s_cache_miss ++;
200 static __u32 fid_hash(const struct lu_fid *f)
202 /* all objects with same id and different versions will belong to same
203 * collisions list. */
204 return (fid_seq(f) - 1) * LUSTRE_FID_SEQ_WIDTH + fid_oid(f);
207 struct lu_object *lu_object_find(struct lu_context *ctxt, struct lu_site *s,
208 const struct lu_fid *f)
211 struct lu_object *shadow;
212 struct hlist_head *bucket;
214 bucket = s->ls_hash + (fid_hash(f) & s->ls_hash_mask);
215 spin_lock(&s->ls_guard);
216 o = htable_lookup(s, bucket, f);
217 spin_unlock(&s->ls_guard);
221 o = lu_object_alloc(ctxt, s, f);
226 LASSERT(lu_fid_eq(lu_object_fid(o), f));
228 spin_lock(&s->ls_guard);
229 shadow = htable_lookup(s, bucket, f);
230 if (shadow == NULL) {
231 hlist_add_head(&o->lo_header->loh_hash, bucket);
232 list_add_tail(&s->ls_lru, &o->lo_header->loh_lru);
236 s->ls_stats.s_cache_race ++;
237 spin_unlock(&s->ls_guard);
239 lu_object_free(ctxt, o);
242 EXPORT_SYMBOL(lu_object_find);
245 LU_SITE_HTABLE_BITS = 8,
246 LU_SITE_HTABLE_SIZE = (1 << LU_SITE_HTABLE_BITS),
247 LU_SITE_HTABLE_MASK = LU_SITE_HTABLE_SIZE - 1
250 int lu_site_init(struct lu_site *s, struct lu_device *top)
252 memset(s, 0, sizeof *s);
254 spin_lock_init(&s->ls_guard);
255 CFS_INIT_LIST_HEAD(&s->ls_lru);
260 * XXX nikita: fixed size hash-table.
262 s->ls_hash_mask = LU_SITE_HTABLE_MASK;
263 OBD_ALLOC(s->ls_hash, LU_SITE_HTABLE_SIZE * sizeof s->ls_hash[0]);
264 if (s->ls_hash != NULL) {
266 for (i = 0; i < LU_SITE_HTABLE_SIZE; i++)
267 INIT_HLIST_HEAD(&s->ls_hash[i]);
272 EXPORT_SYMBOL(lu_site_init);
274 void lu_site_fini(struct lu_site *s)
276 LASSERT(list_empty(&s->ls_lru));
277 LASSERT(s->ls_total == 0);
278 LASSERT(s->ls_busy == 0);
280 if (s->ls_hash != NULL) {
282 for (i = 0; i < LU_SITE_HTABLE_SIZE; i++)
283 LASSERT(hlist_empty(&s->ls_hash[i]));
285 LU_SITE_HTABLE_SIZE * sizeof s->ls_hash[0]);
288 if (s->ls_top_dev != NULL) {
289 lu_device_put(s->ls_top_dev);
290 s->ls_top_dev->ld_site = NULL;
291 s->ls_top_dev = NULL;
294 EXPORT_SYMBOL(lu_site_fini);
296 void lu_device_get(struct lu_device *d)
298 atomic_inc(&d->ld_ref);
300 EXPORT_SYMBOL(lu_device_get);
302 void lu_device_put(struct lu_device *d)
304 atomic_dec(&d->ld_ref);
306 EXPORT_SYMBOL(lu_device_put);
308 int lu_device_init(struct lu_device *d, struct lu_device_type *t)
310 memset(d, 0, sizeof *d);
311 atomic_set(&d->ld_ref, 0);
315 EXPORT_SYMBOL(lu_device_init);
317 void lu_device_fini(struct lu_device *d)
319 LASSERT(atomic_read(&d->ld_ref) == 0);
321 EXPORT_SYMBOL(lu_device_fini);
323 int lu_object_init(struct lu_object *o,
324 struct lu_object_header *h, struct lu_device *d)
326 memset(o, 0, sizeof *o);
330 CFS_INIT_LIST_HEAD(&o->lo_linkage);
333 EXPORT_SYMBOL(lu_object_init);
335 void lu_object_fini(struct lu_object *o)
337 LASSERT(list_empty(&o->lo_linkage));
339 if (o->lo_dev != NULL) {
340 lu_device_get(o->lo_dev);
344 EXPORT_SYMBOL(lu_object_fini);
346 void lu_object_add_top(struct lu_object_header *h, struct lu_object *o)
348 list_move(&o->lo_linkage, &h->loh_layers);
350 EXPORT_SYMBOL(lu_object_add_top);
352 void lu_object_add(struct lu_object *before, struct lu_object *o)
354 list_move(&o->lo_linkage, &before->lo_linkage);
356 EXPORT_SYMBOL(lu_object_add);
358 int lu_object_header_init(struct lu_object_header *h)
360 memset(h, 0, sizeof *h);
361 INIT_HLIST_NODE(&h->loh_hash);
362 CFS_INIT_LIST_HEAD(&h->loh_lru);
363 CFS_INIT_LIST_HEAD(&h->loh_layers);
366 EXPORT_SYMBOL(lu_object_header_init);
368 void lu_object_header_fini(struct lu_object_header *h)
370 LASSERT(list_empty(&h->loh_layers));
371 LASSERT(list_empty(&h->loh_lru));
372 LASSERT(hlist_unhashed(&h->loh_hash));
374 EXPORT_SYMBOL(lu_object_header_fini);
376 struct lu_object *lu_object_locate(struct lu_object_header *h,
377 struct lu_device_type *dtype)
381 list_for_each_entry(o, &h->loh_layers, lo_linkage) {
382 if (o->lo_dev->ld_type == dtype)
387 EXPORT_SYMBOL(lu_object_locate);
391 * Maximal number of tld slots.
393 LU_CONTEXT_KEY_NR = 16
396 static struct lu_context_key *lu_keys[LU_CONTEXT_KEY_NR] = { NULL, };
398 static spinlock_t lu_keys_guard = SPIN_LOCK_UNLOCKED;
400 int lu_context_key_register(struct lu_context_key *key)
406 spin_lock(&lu_keys_guard);
407 for (i = 0; i < ARRAY_SIZE(lu_keys); ++i) {
408 if (lu_keys[i] == NULL) {
416 spin_unlock(&lu_keys_guard);
419 EXPORT_SYMBOL(lu_context_key_register);
421 void lu_context_key_degister(struct lu_context_key *key)
423 LASSERT(key->lct_used >= 1);
424 LASSERT(0 <= key->lct_index && key->lct_index < ARRAY_SIZE(lu_keys));
426 if (key->lct_used > 1)
427 CERROR("key has instances.\n");
428 spin_lock(&lu_keys_guard);
429 lu_keys[key->lct_index] = NULL;
430 spin_unlock(&lu_keys_guard);
432 EXPORT_SYMBOL(lu_context_key_degister);
434 void *lu_context_key_get(struct lu_context *ctx, struct lu_context_key *key)
436 LASSERT(0 <= key->lct_index && key->lct_index < ARRAY_SIZE(lu_keys));
437 return ctx->lc_value[key->lct_index];
439 EXPORT_SYMBOL(lu_context_key_get);
441 static void keys_fini(struct lu_context *ctx)
445 if (ctx->lc_value != NULL) {
446 for (i = 0; i < ARRAY_SIZE(lu_keys); ++i) {
447 if (ctx->lc_value[i] != NULL) {
448 struct lu_context_key *key;
451 LASSERT(key != NULL);
452 LASSERT(key->lct_fini != NULL);
453 LASSERT(key->lct_used > 1);
455 key->lct_fini(ctx, ctx->lc_value[i]);
457 ctx->lc_value[i] = NULL;
460 OBD_FREE(ctx->lc_value,
461 ARRAY_SIZE(lu_keys) * sizeof ctx->lc_value[0]);
462 ctx->lc_value = NULL;
466 static int keys_init(struct lu_context *ctx)
471 OBD_ALLOC(ctx->lc_value, ARRAY_SIZE(lu_keys) * sizeof ctx->lc_value[0]);
472 if (ctx->lc_value != NULL) {
473 for (i = 0; i < ARRAY_SIZE(lu_keys); ++i) {
474 struct lu_context_key *key;
480 LASSERT(key->lct_init != NULL);
481 LASSERT(key->lct_index == i);
483 value = key->lct_init(ctx);
486 return PTR_ERR(value);
489 ctx->lc_value[i] = value;
498 int lu_context_init(struct lu_context *ctx)
500 memset(ctx, 0, sizeof *ctx);
504 EXPORT_SYMBOL(lu_context_init);
506 void lu_context_fini(struct lu_context *ctx)
510 EXPORT_SYMBOL(lu_context_fini);
512 void lu_context_enter(struct lu_context *ctx)
515 EXPORT_SYMBOL(lu_context_enter);
517 void lu_context_exit(struct lu_context *ctx)
520 EXPORT_SYMBOL(lu_context_exit);