2 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3 * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
5 * This file is part of the device-mapper userspace tools.
7 * This copyrighted material is made available to anyone wishing to use,
8 * modify, copy, or redistribute it subject to the terms and conditions
9 * of the GNU Lesser General Public License v.2.1.
11 * You should have received a copy of the GNU Lesser General Public License
12 * along with this program; if not, write to the Free Software Foundation,
13 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 unsigned block_serialno; /* Non-decreasing serialno of block */
27 unsigned blocks_allocated; /* Current number of blocks allocated */
28 unsigned blocks_max; /* Max no of concurrently-allocated blocks */
29 unsigned int bytes, maxbytes;
35 void *orig_pool; /* to pair it with first allocation call */
46 /* by default things come out aligned for doubles */
47 #define DEFAULT_ALIGNMENT __alignof__ (double)
49 struct dm_pool *dm_pool_create(const char *name, size_t chunk_hint)
51 struct dm_pool *mem = dm_malloc(sizeof(*mem));
54 log_error("Couldn't create memory pool %s (size %"
55 PRIsize_t ")", name, sizeof(*mem));
62 mem->blocks = mem->tail = NULL;
64 mem->stats.block_serialno = 0;
65 mem->stats.blocks_allocated = 0;
66 mem->stats.blocks_max = 0;
68 mem->stats.maxbytes = 0;
73 log_debug("Created mempool %s", name);
76 dm_list_add(&_dm_pools, &mem->list);
80 static void _free_blocks(struct dm_pool *p, struct block *b)
85 p->stats.bytes -= b->size;
86 p->stats.blocks_allocated--;
95 static void _pool_stats(struct dm_pool *p, const char *action)
98 log_debug("%s mempool %s: %u/%u bytes, %u/%u blocks, "
99 "%u allocations)", action, p->name, p->stats.bytes,
100 p->stats.maxbytes, p->stats.blocks_allocated,
101 p->stats.blocks_max, p->stats.block_serialno);
107 void dm_pool_destroy(struct dm_pool *p)
109 _pool_stats(p, "Destroying");
110 _free_blocks(p, p->blocks);
111 dm_list_del(&p->list);
115 void *dm_pool_alloc(struct dm_pool *p, size_t s)
117 return dm_pool_alloc_aligned(p, s, DEFAULT_ALIGNMENT);
120 static void _append_block(struct dm_pool *p, struct block *b)
126 p->blocks = p->tail = b;
128 p->stats.block_serialno++;
129 p->stats.blocks_allocated++;
130 if (p->stats.blocks_allocated > p->stats.blocks_max)
131 p->stats.blocks_max = p->stats.blocks_allocated;
133 p->stats.bytes += b->size;
134 if (p->stats.bytes > p->stats.maxbytes)
135 p->stats.maxbytes = p->stats.bytes;
138 static struct block *_new_block(size_t s, unsigned alignment)
140 /* FIXME: I'm currently ignoring the alignment arg. */
141 size_t len = sizeof(struct block) + s;
142 struct block *b = dm_malloc(len);
145 * Too lazy to implement alignment for debug version, and
146 * I don't think LVM will use anything but default
149 assert(alignment == DEFAULT_ALIGNMENT);
152 log_error("Out of memory");
156 if (!(b->data = dm_malloc(s))) {
157 log_error("Out of memory");
168 void *dm_pool_alloc_aligned(struct dm_pool *p, size_t s, unsigned alignment)
170 struct block *b = _new_block(s, alignment);
180 void dm_pool_empty(struct dm_pool *p)
182 _pool_stats(p, "Emptying");
183 _free_blocks(p, p->blocks);
184 p->blocks = p->tail = NULL;
187 void dm_pool_free(struct dm_pool *p, void *ptr)
189 struct block *b, *prev = NULL;
191 _pool_stats(p, "Freeing (before)");
193 for (b = p->blocks; b; b = b->next) {
200 * If this fires then you tried to free a
201 * pointer that either wasn't from this
202 * pool, or isn't the start of a block.
212 p->blocks = p->tail = NULL;
214 _pool_stats(p, "Freeing (after)");
217 int dm_pool_begin_object(struct dm_pool *p, size_t init_size)
224 int dm_pool_grow_object(struct dm_pool *p, const void *extra, size_t delta)
230 delta = strlen(extra);
235 new_size = delta + p->object->size;
239 if (!(new = _new_block(new_size, DEFAULT_ALIGNMENT))) {
240 log_error("Couldn't extend object.");
245 memcpy(new->data, p->object->data, p->object->size);
246 dm_free(p->object->data);
251 memcpy(new->data + new_size - delta, extra, delta);
256 void *dm_pool_end_object(struct dm_pool *p)
259 _append_block(p, p->object);
263 return p->tail->data;
266 void dm_pool_abandon_object(struct dm_pool *p)