4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
7 * This file is part of the device-mapper userspace tools.
9 * This copyrighted material is made available to anyone wishing to use,
10 * modify, copy, or redistribute it subject to the terms and conditions
11 * of the GNU Lesser General Public License v.2.1.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 char *dm_strdup_aux(const char *str
, const char *file
, int line
)
28 log_error("Internal error: dm_strdup called with NULL pointer");
32 if ((ret
= dm_malloc_aux_debug(strlen(str
) + 1, file
, line
)))
39 struct memblock
*prev
, *next
; /* All allocated blocks are linked */
40 size_t length
; /* Size of the requested block */
41 int id
; /* Index of the block */
42 const char *file
; /* File that allocated */
43 int line
; /* Line that allocated */
44 void *magic
; /* Address of this block */
45 } __attribute__((aligned(8)));
48 unsigned block_serialno
;/* Non-decreasing serialno of block */
49 unsigned blocks_allocated
; /* Current number of blocks allocated */
50 unsigned blocks_max
; /* Max no of concurrently-allocated blocks */
51 unsigned int bytes
, mbytes
;
56 static struct memblock
*_head
= 0;
57 static struct memblock
*_tail
= 0;
59 void *dm_malloc_aux_debug(size_t s
, const char *file
, int line
)
62 size_t tsize
= s
+ sizeof(*nb
) + sizeof(unsigned long);
65 log_error("Huge memory allocation (size %" PRIsize_t
66 ") rejected - metadata corruption?", s
);
70 if (!(nb
= malloc(tsize
))) {
71 log_error("couldn't allocate any memory, size = %" PRIsize_t
,
76 /* set up the file and line info */
85 nb
->id
= ++_mem_stats
.block_serialno
;
88 /* stomp a pretty pattern across the new memory
89 and fill in the boundary bytes */
91 char *ptr
= (char *) (nb
+ 1);
93 for (i
= 0; i
< s
; i
++)
94 *ptr
++ = i
& 0x1 ? (char) 0xba : (char) 0xbe;
96 for (i
= 0; i
< sizeof(unsigned long); i
++)
97 *ptr
++ = (char) nb
->id
;
102 /* link to tail of the list */
110 _mem_stats
.blocks_allocated
++;
111 if (_mem_stats
.blocks_allocated
> _mem_stats
.blocks_max
)
112 _mem_stats
.blocks_max
= _mem_stats
.blocks_allocated
;
114 _mem_stats
.bytes
+= s
;
115 if (_mem_stats
.bytes
> _mem_stats
.mbytes
)
116 _mem_stats
.mbytes
= _mem_stats
.bytes
;
118 /* log_debug("Allocated: %u %u %u", nb->id, _mem_stats.blocks_allocated,
119 _mem_stats.bytes); */
124 void dm_free_aux(void *p
)
128 struct memblock
*mb
= ((struct memblock
*) p
) - 1;
135 assert(mb
->magic
== p
);
137 /* check data at the far boundary */
138 ptr
= ((char *) mb
) + sizeof(struct memblock
) + mb
->length
;
139 for (i
= 0; i
< sizeof(unsigned long); i
++)
140 if (*ptr
++ != (char) mb
->id
)
141 assert(!"Damage at far end of block");
143 /* have we freed this before ? */
148 mb
->prev
->next
= mb
->next
;
153 mb
->next
->prev
= mb
->prev
;
159 /* stomp a different pattern across the memory */
160 ptr
= ((char *) mb
) + sizeof(struct memblock
);
161 for (i
= 0; i
< mb
->length
; i
++)
162 *ptr
++ = i
& 1 ? (char) 0xde : (char) 0xad;
164 assert(_mem_stats
.blocks_allocated
);
165 _mem_stats
.blocks_allocated
--;
166 _mem_stats
.bytes
-= mb
->length
;
168 /* free the memory */
172 void *dm_realloc_aux(void *p
, unsigned int s
, const char *file
, int line
)
175 struct memblock
*mb
= ((struct memblock
*) p
) - 1;
177 r
= dm_malloc_aux_debug(s
, file
, line
);
180 memcpy(r
, p
, mb
->length
);
187 int dm_dump_memory_debug(void)
189 unsigned long tot
= 0;
195 log_very_verbose("You have a memory leak:");
197 for (mb
= _head
; mb
; mb
= mb
->next
) {
198 for (c
= 0; c
< sizeof(str
) - 1; c
++) {
201 else if (*(char *)(mb
->magic
+ c
) == '\0')
203 else if (*(char *)(mb
->magic
+ c
) < ' ')
206 str
[c
] = *(char *)(mb
->magic
+ c
);
208 str
[sizeof(str
) - 1] = '\0';
210 LOG_MESG(_LOG_INFO
, mb
->file
, mb
->line
, 0,
211 "block %d at %p, size %" PRIsize_t
"\t [%s]",
212 mb
->id
, mb
->magic
, mb
->length
, str
);
217 log_very_verbose("%ld bytes leaked in total", tot
);
222 void dm_bounds_check_debug(void)
224 struct memblock
*mb
= _head
;
227 char *ptr
= ((char *) (mb
+ 1)) + mb
->length
;
228 for (i
= 0; i
< sizeof(unsigned long); i
++)
229 if (*ptr
++ != (char) mb
->id
)
230 assert(!"Memory smash");
236 void *dm_malloc_aux(size_t s
, const char *file
__attribute((unused
)),
237 int line
__attribute((unused
)))
240 log_error("Huge memory allocation (size %" PRIsize_t
241 ") rejected - metadata corruption?", s
);