2 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3 * Copyright (C) 2004-2007 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
21 char *dm_strdup_aux(const char *str, const char *file, int line)
26 log_error(INTERNAL_ERROR "dm_strdup called with NULL pointer");
30 if ((ret = dm_malloc_aux_debug(strlen(str) + 1, file, line)))
37 struct memblock *prev, *next; /* All allocated blocks are linked */
38 size_t length; /* Size of the requested block */
39 int id; /* Index of the block */
40 const char *file; /* File that allocated */
41 int line; /* Line that allocated */
42 void *magic; /* Address of this block */
43 } __attribute__((aligned(8)));
46 unsigned block_serialno;/* Non-decreasing serialno of block */
47 unsigned blocks_allocated; /* Current number of blocks allocated */
48 unsigned blocks_max; /* Max no of concurrently-allocated blocks */
49 unsigned int bytes, mbytes;
54 static struct memblock *_head = 0;
55 static struct memblock *_tail = 0;
57 void *dm_malloc_aux_debug(size_t s, const char *file, int line)
60 size_t tsize = s + sizeof(*nb) + sizeof(unsigned long);
63 log_error("Huge memory allocation (size %" PRIsize_t
64 ") rejected - metadata corruption?", s);
68 if (!(nb = malloc(tsize))) {
69 log_error("couldn't allocate any memory, size = %" PRIsize_t,
74 /* set up the file and line info */
83 nb->id = ++_mem_stats.block_serialno;
86 /* stomp a pretty pattern across the new memory
87 and fill in the boundary bytes */
89 char *ptr = (char *) (nb + 1);
91 for (i = 0; i < s; i++)
92 *ptr++ = i & 0x1 ? (char) 0xba : (char) 0xbe;
94 for (i = 0; i < sizeof(unsigned long); i++)
95 *ptr++ = (char) nb->id;
100 /* link to tail of the list */
108 _mem_stats.blocks_allocated++;
109 if (_mem_stats.blocks_allocated > _mem_stats.blocks_max)
110 _mem_stats.blocks_max = _mem_stats.blocks_allocated;
112 _mem_stats.bytes += s;
113 if (_mem_stats.bytes > _mem_stats.mbytes)
114 _mem_stats.mbytes = _mem_stats.bytes;
116 /* log_debug("Allocated: %u %u %u", nb->id, _mem_stats.blocks_allocated,
117 _mem_stats.bytes); */
122 void *dm_zalloc_aux_debug(size_t s, const char *file, int line)
124 void *ptr = dm_malloc_aux_debug(s, file, line);
132 void dm_free_aux(void *p)
136 struct memblock *mb = ((struct memblock *) p) - 1;
143 assert(mb->magic == p);
145 /* check data at the far boundary */
146 ptr = ((char *) mb) + sizeof(struct memblock) + mb->length;
147 for (i = 0; i < sizeof(unsigned long); i++)
148 if (*ptr++ != (char) mb->id)
149 assert(!"Damage at far end of block");
151 /* have we freed this before ? */
156 mb->prev->next = mb->next;
161 mb->next->prev = mb->prev;
167 /* stomp a different pattern across the memory */
168 ptr = ((char *) mb) + sizeof(struct memblock);
169 for (i = 0; i < mb->length; i++)
170 *ptr++ = i & 1 ? (char) 0xde : (char) 0xad;
172 assert(_mem_stats.blocks_allocated);
173 _mem_stats.blocks_allocated--;
174 _mem_stats.bytes -= mb->length;
176 /* free the memory */
180 void *dm_realloc_aux(void *p, unsigned int s, const char *file, int line)
183 struct memblock *mb = ((struct memblock *) p) - 1;
185 r = dm_malloc_aux_debug(s, file, line);
188 memcpy(r, p, mb->length);
195 int dm_dump_memory_debug(void)
197 unsigned long tot = 0;
203 log_very_verbose("You have a memory leak:");
205 for (mb = _head; mb; mb = mb->next) {
208 * We can't look at the memory in case it has had
209 * VALGRIND_MAKE_MEM_NOACCESS called on it.
213 for (c = 0; c < sizeof(str) - 1; c++) {
216 else if (((char *)mb->magic)[c] == '\0')
218 else if (((char *)mb->magic)[c] < ' ')
221 str[c] = ((char *)mb->magic)[c];
223 str[sizeof(str) - 1] = '\0';
226 LOG_MESG(_LOG_INFO, mb->file, mb->line, 0,
227 "block %d at %p, size %" PRIsize_t "\t [%s]",
228 mb->id, mb->magic, mb->length, str);
233 log_very_verbose("%ld bytes leaked in total", tot);
238 void dm_bounds_check_debug(void)
240 struct memblock *mb = _head;
243 char *ptr = ((char *) (mb + 1)) + mb->length;
244 for (i = 0; i < sizeof(unsigned long); i++)
245 if (*ptr++ != (char) mb->id)
246 assert(!"Memory smash");
252 void *dm_malloc_aux(size_t s, const char *file __attribute__((unused)),
253 int line __attribute__((unused)))
256 log_error("Huge memory allocation (size %" PRIsize_t
257 ") rejected - metadata corruption?", s);
264 void *dm_zalloc_aux(size_t s, const char *file, int line)
266 void *ptr = dm_malloc_aux(s, file, line);