4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.gnu.org/licenses/gpl-2.0.html
23 * This file is part of Lustre, http://www.lustre.org/
25 * lustre/obdclass/lu_tgt_descs.c
27 * Lustre target descriptions
28 * These are the only exported functions, they provide some generic
29 * infrastructure for target description management used by LOD/LMV
33 #define DEBUG_SUBSYSTEM S_CLASS
35 #include <linux/module.h>
36 #include <linux/list.h>
37 #include <libcfs/libcfs.h>
38 #include <libcfs/libcfs_hash.h> /* hash_long() */
39 #include <libcfs/linux/linux-mem.h>
40 #include <obd_class.h>
41 #include <obd_support.h>
42 #include <lustre_disk.h>
43 #include <lustre_fid.h>
44 #include <lu_object.h>
47 * Allocate and initialize target table.
49 * A helper function to initialize the target table and allocate
50 * a bitmap of the available targets.
52 * \param[in] ltd target's table to initialize
54 * \retval 0 on success
55 * \retval negative negated errno on error
57 int lu_tgt_descs_init(struct lu_tgt_descs *ltd)
59 mutex_init(<d->ltd_mutex);
60 init_rwsem(<d->ltd_rw_sem);
63 * the tgt array and bitmap are allocated/grown dynamically as tgts are
64 * added to the LOD/LMV, see lu_tgt_descs_add()
66 ltd->ltd_tgt_bitmap = CFS_ALLOCATE_BITMAP(BITS_PER_LONG);
67 if (!ltd->ltd_tgt_bitmap)
70 ltd->ltd_tgts_size = BITS_PER_LONG;
73 ltd->ltd_death_row = 0;
74 ltd->ltd_refcount = 0;
78 EXPORT_SYMBOL(lu_tgt_descs_init);
81 * Free bitmap and target table pages.
83 * \param[in] ltd target table
85 void lu_tgt_descs_fini(struct lu_tgt_descs *ltd)
89 CFS_FREE_BITMAP(ltd->ltd_tgt_bitmap);
90 for (i = 0; i < TGT_PTRS; i++) {
91 if (ltd->ltd_tgt_idx[i])
92 OBD_FREE_PTR(ltd->ltd_tgt_idx[i]);
94 ltd->ltd_tgts_size = 0;
96 EXPORT_SYMBOL(lu_tgt_descs_fini);
99 * Expand size of target table.
101 * When the target table is full, we have to extend the table. To do so,
102 * we allocate new memory with some reserve, move data from the old table
103 * to the new one and release memory consumed by the old table.
105 * \param[in] ltd target table
106 * \param[in] newsize new size of the table
108 * \retval 0 on success
109 * \retval -ENOMEM if reallocation failed
111 static int lu_tgt_descs_resize(struct lu_tgt_descs *ltd, __u32 newsize)
113 struct cfs_bitmap *new_bitmap, *old_bitmap = NULL;
115 /* someone else has already resize the array */
116 if (newsize <= ltd->ltd_tgts_size)
119 new_bitmap = CFS_ALLOCATE_BITMAP(newsize);
123 if (ltd->ltd_tgts_size > 0) {
124 /* the bitmap already exists, copy data from old one */
125 cfs_bitmap_copy(new_bitmap, ltd->ltd_tgt_bitmap);
126 old_bitmap = ltd->ltd_tgt_bitmap;
129 ltd->ltd_tgts_size = newsize;
130 ltd->ltd_tgt_bitmap = new_bitmap;
133 CFS_FREE_BITMAP(old_bitmap);
135 CDEBUG(D_CONFIG, "tgt size: %d\n", ltd->ltd_tgts_size);
141 * Add new target to target table.
143 * Extend target table if it's full, update target table and bitmap.
144 * Notice we need to take ltd_rw_sem exclusively before entry to ensure
147 * \param[in] ltd target table
148 * \param[in] tgt new target desc
150 * \retval 0 on success
151 * \retval -ENOMEM if reallocation failed
152 * -EEXIST if target existed
154 int lu_tgt_descs_add(struct lu_tgt_descs *ltd, struct lu_tgt_desc *tgt)
156 __u32 index = tgt->ltd_index;
161 if (index >= ltd->ltd_tgts_size) {
164 while (newsize < index + 1)
165 newsize = newsize << 1;
167 rc = lu_tgt_descs_resize(ltd, newsize);
170 } else if (cfs_bitmap_check(ltd->ltd_tgt_bitmap, index)) {
174 if (ltd->ltd_tgt_idx[index / TGT_PTRS_PER_BLOCK] == NULL) {
175 OBD_ALLOC_PTR(ltd->ltd_tgt_idx[index / TGT_PTRS_PER_BLOCK]);
176 if (ltd->ltd_tgt_idx[index / TGT_PTRS_PER_BLOCK] == NULL)
180 LTD_TGT(ltd, tgt->ltd_index) = tgt;
181 cfs_bitmap_set(ltd->ltd_tgt_bitmap, tgt->ltd_index);
186 EXPORT_SYMBOL(lu_tgt_descs_add);
189 * Delete target from target table
191 void lu_tgt_descs_del(struct lu_tgt_descs *ltd, struct lu_tgt_desc *tgt)
193 LTD_TGT(ltd, tgt->ltd_index) = NULL;
194 cfs_bitmap_clear(ltd->ltd_tgt_bitmap, tgt->ltd_index);
197 EXPORT_SYMBOL(lu_tgt_descs_del);