dm-table.c (ab4c1424882be9cd70b89abf2b484add355712fa) dm-table.c (d58168763f74d1edbc296d7038c60efe6493fdd4)
1/*
2 * Copyright (C) 2001 Sistina Software (UK) Limited.
1/*
2 * Copyright (C) 2001 Sistina Software (UK) Limited.
3 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
3 * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
4 *
5 * This file is released under the GPL.
6 */
7
8#include "dm.h"
9
10#include <linux/module.h>
11#include <linux/vmalloc.h>
12#include <linux/blkdev.h>
13#include <linux/namei.h>
14#include <linux/ctype.h>
15#include <linux/slab.h>
16#include <linux/interrupt.h>
17#include <linux/mutex.h>
4 *
5 * This file is released under the GPL.
6 */
7
8#include "dm.h"
9
10#include <linux/module.h>
11#include <linux/vmalloc.h>
12#include <linux/blkdev.h>
13#include <linux/namei.h>
14#include <linux/ctype.h>
15#include <linux/slab.h>
16#include <linux/interrupt.h>
17#include <linux/mutex.h>
18#include <linux/delay.h>
18#include <asm/atomic.h>
19
20#define DM_MSG_PREFIX "table"
21
22#define MAX_DEPTH 16
23#define NODE_SIZE L1_CACHE_BYTES
24#define KEYS_PER_NODE (NODE_SIZE / sizeof(sector_t))
25#define CHILDREN_PER_NODE (KEYS_PER_NODE + 1)
26
19#include <asm/atomic.h>
20
21#define DM_MSG_PREFIX "table"
22
23#define MAX_DEPTH 16
24#define NODE_SIZE L1_CACHE_BYTES
25#define KEYS_PER_NODE (NODE_SIZE / sizeof(sector_t))
26#define CHILDREN_PER_NODE (KEYS_PER_NODE + 1)
27
28/*
29 * The table has always exactly one reference from either mapped_device->map
30 * or hash_cell->new_map. This reference is not counted in table->holders.
31 * A pair of dm_create_table/dm_destroy_table functions is used for table
32 * creation/destruction.
33 *
34 * Temporary references from the other code increase table->holders. A pair
35 * of dm_table_get/dm_table_put functions is used to manipulate it.
36 *
37 * When the table is about to be destroyed, we wait for table->holders to
38 * drop to zero.
39 */
40
27struct dm_table {
28 struct mapped_device *md;
29 atomic_t holders;
30
31 /* btree table */
32 unsigned int depth;
33 unsigned int counts[MAX_DEPTH]; /* in nodes */
34 sector_t *index[MAX_DEPTH];

--- 188 unchanged lines hidden (view full) ---

223 unsigned num_targets, struct mapped_device *md)
224{
225 struct dm_table *t = kzalloc(sizeof(*t), GFP_KERNEL);
226
227 if (!t)
228 return -ENOMEM;
229
230 INIT_LIST_HEAD(&t->devices);
41struct dm_table {
42 struct mapped_device *md;
43 atomic_t holders;
44
45 /* btree table */
46 unsigned int depth;
47 unsigned int counts[MAX_DEPTH]; /* in nodes */
48 sector_t *index[MAX_DEPTH];

--- 188 unchanged lines hidden (view full) ---

237 unsigned num_targets, struct mapped_device *md)
238{
239 struct dm_table *t = kzalloc(sizeof(*t), GFP_KERNEL);
240
241 if (!t)
242 return -ENOMEM;
243
244 INIT_LIST_HEAD(&t->devices);
231 atomic_set(&t->holders, 1);
245 atomic_set(&t->holders, 0);
232 t->barriers_supported = 1;
233
234 if (!num_targets)
235 num_targets = KEYS_PER_NODE;
236
237 num_targets = dm_round_up(num_targets, KEYS_PER_NODE);
238
239 if (alloc_targets(t, num_targets)) {

--- 14 unchanged lines hidden (view full) ---

254
255 list_for_each_safe(tmp, next, devices) {
256 struct dm_dev_internal *dd =
257 list_entry(tmp, struct dm_dev_internal, list);
258 kfree(dd);
259 }
260}
261
246 t->barriers_supported = 1;
247
248 if (!num_targets)
249 num_targets = KEYS_PER_NODE;
250
251 num_targets = dm_round_up(num_targets, KEYS_PER_NODE);
252
253 if (alloc_targets(t, num_targets)) {

--- 14 unchanged lines hidden (view full) ---

268
269 list_for_each_safe(tmp, next, devices) {
270 struct dm_dev_internal *dd =
271 list_entry(tmp, struct dm_dev_internal, list);
272 kfree(dd);
273 }
274}
275
262static void table_destroy(struct dm_table *t)
276void dm_table_destroy(struct dm_table *t)
263{
264 unsigned int i;
265
277{
278 unsigned int i;
279
280 while (atomic_read(&t->holders))
281 msleep(1);
282 smp_mb();
283
266 /* free the indexes (see dm_table_complete) */
267 if (t->depth >= 2)
268 vfree(t->index[t->depth - 2]);
269
270 /* free the targets */
271 for (i = 0; i < t->num_targets; i++) {
272 struct dm_target *tgt = t->targets + i;
273

--- 21 unchanged lines hidden (view full) ---

295 atomic_inc(&t->holders);
296}
297
298void dm_table_put(struct dm_table *t)
299{
300 if (!t)
301 return;
302
284 /* free the indexes (see dm_table_complete) */
285 if (t->depth >= 2)
286 vfree(t->index[t->depth - 2]);
287
288 /* free the targets */
289 for (i = 0; i < t->num_targets; i++) {
290 struct dm_target *tgt = t->targets + i;
291

--- 21 unchanged lines hidden (view full) ---

313 atomic_inc(&t->holders);
314}
315
316void dm_table_put(struct dm_table *t)
317{
318 if (!t)
319 return;
320
303 if (atomic_dec_and_test(&t->holders))
304 table_destroy(t);
321 smp_mb__before_atomic_dec();
322 atomic_dec(&t->holders);
305}
306
307/*
308 * Checks to see if we need to extend highs or targets.
309 */
310static inline int check_space(struct dm_table *t)
311{
312 if (t->num_targets >= t->num_allocated)

--- 705 unchanged lines hidden ---
323}
324
325/*
326 * Checks to see if we need to extend highs or targets.
327 */
328static inline int check_space(struct dm_table *t)
329{
330 if (t->num_targets >= t->num_allocated)

--- 705 unchanged lines hidden ---