|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v4] xmalloc: add support for checking the pool integrity
Implemented xmem_pool_check(), xmem_pool_check_locked() and
xmem_pool_check_unlocked() to verity the integrity of the TLSF matrix.
Signed-off-by: Mihai DonÈu <mdontu@xxxxxxxxxxxxxxx>
---
Changes since v3:
- try harder to respect the 80 column limit
- use 'unsigned int' instead of 'int' where possible
- made the logged messages even shorter
- dropped the use of goto (didn't really make sense)
Changes since v2:
- print the name of the corrupted pool
- adjusted the messages to better fit within 80 columns
- minor style change (a ? a : b -> a ?: b)
Changes since v1:
- fixed the codingstyle
- swaped _locked/_unlocked naming
- reworked __xmem_pool_check_locked() a bit
- used bool_t where appropriate
- made xmem_pool_check() take a pool argument which can be NULL
---
xen/common/xmalloc_tlsf.c | 121 +++++++++++++++++++++++++++++++++++++++++++++-
xen/include/xen/xmalloc.h | 7 +++
2 files changed, 126 insertions(+), 2 deletions(-)
diff --git a/xen/common/xmalloc_tlsf.c b/xen/common/xmalloc_tlsf.c
index a5769c9..eca4f1c 100644
--- a/xen/common/xmalloc_tlsf.c
+++ b/xen/common/xmalloc_tlsf.c
@@ -120,9 +120,122 @@ struct xmem_pool {
char name[MAX_POOL_NAME_LEN];
};
+static struct xmem_pool *xenpool;
+
+static inline void MAPPING_INSERT(unsigned long r, int *fl, int *sl);
+
/*
* Helping functions
*/
+#ifndef NDEBUG
+static bool_t xmem_pool_check_size(const struct xmem_pool *pool,
+ int fl, int sl)
+{
+ const struct bhdr *b = pool->matrix[fl][sl];
+
+ while ( b )
+ {
+ int __fl;
+ int __sl;
+
+ MAPPING_INSERT(b->size, &__fl, &__sl);
+ if ( __fl != fl || __sl != sl )
+ {
+ printk(XENLOG_ERR
+ "xmem_pool: %s: misplaced block %p:%u ({%d,%d} ->
{%d,%d})\n",
+ pool->name, b, b->size, fl, sl, __fl, __sl);
+ return 0;
+ }
+ b = b->ptr.free_ptr.next;
+ }
+ return 1;
+}
+
+/*
+ * This function must be called from a context where pool->lock is
+ * already acquired.
+ *
+ * Returns true if the pool has been corrupted, false otherwise
+ */
+#define xmem_pool_check_locked(pool) \
+ __xmem_pool_check_locked(__FILE__, __LINE__, pool)
+static bool_t __xmem_pool_check_locked(const char *file, int line,
+ const struct xmem_pool *pool)
+{
+ unsigned int i;
+ static bool_t once = 1;
+
+ if ( !once )
+ return 1;
+ for ( i = 0; i < REAL_FLI; i++ )
+ {
+ int fl = (pool->fl_bitmap & (1 << i)) ? i : -1;
+
+ if ( fl >= 0 )
+ {
+ unsigned int j;
+
+ if ( !pool->sl_bitmap[fl] )
+ {
+ printk(XENLOG_ERR
+ "xmem_pool: %s: TLSF bitmap corrupt (!empty FL, empty
SL)\n",
+ pool->name);
+ __warn(file, line);
+ once = 0;
+ break;
+ }
+ for ( j = 0; j < MAX_SLI; j++ )
+ {
+ int sl = (pool->sl_bitmap[fl] & (1 << j)) ? j : -1;
+
+ if ( sl < 0 )
+ continue;
+ if ( !pool->matrix[fl][sl] )
+ {
+ printk(XENLOG_ERR
+ "xmem_pool: %s: TLSF bitmap corrupt
(!matrix[%d][%d])\n",
+ pool->name, fl, sl);
+ __warn(file, line);
+ once = 0;
+ break;
+ }
+ if ( !xmem_pool_check_size(pool, fl, sl) )
+ {
+ printk(XENLOG_ERR "xmem_pool: %s: TLSF chunk matrix
corrupt\n",
+ pool->name);
+ __warn(file, line);
+ once = 0;
+ break;
+ }
+ }
+ if ( !once )
+ break;
+ }
+ }
+ return !once;
+}
+
+#define xmem_pool_check_unlocked(pool) \
+ __xmem_pool_check_unlocked(__FILE__, __LINE__, pool)
+static bool_t __xmem_pool_check_unlocked(const char *file, int line,
+ struct xmem_pool *pool)
+{
+ bool_t oops;
+
+ spin_lock(&pool->lock);
+ oops = __xmem_pool_check_locked(file, line, pool);
+ spin_unlock(&pool->lock);
+ return oops;
+}
+
+bool_t __xmem_pool_check(const char *file, int line, struct xmem_pool *pool)
+{
+ return __xmem_pool_check_unlocked(file, line, pool ?: xenpool);
+}
+#else
+#define xmem_pool_check_locked(pool) ((void)(pool))
+#define xmem_pool_check_unlocked(pool) ((void)(pool))
+#endif
/**
* Returns indexes (fl, sl) of the list used to serve request of size r
@@ -381,6 +494,8 @@ void *xmem_pool_alloc(unsigned long size, struct xmem_pool
*pool)
int fl, sl;
unsigned long tmp_size;
+ xmem_pool_check_unlocked(pool);
+
if ( pool->init_region == NULL )
{
if ( (region = pool->get_mem(pool->init_size)) == NULL )
@@ -442,11 +557,13 @@ void *xmem_pool_alloc(unsigned long size, struct
xmem_pool *pool)
pool->used_size += (b->size & BLOCK_SIZE_MASK) + BHDR_OVERHEAD;
+ xmem_pool_check_locked(pool);
spin_unlock(&pool->lock);
return (void *)b->ptr.buffer;
/* Failed alloc */
out_locked:
+ xmem_pool_check_locked(pool);
spin_unlock(&pool->lock);
out:
@@ -464,6 +581,7 @@ void xmem_pool_free(void *ptr, struct xmem_pool *pool)
b = (struct bhdr *)((char *) ptr - BHDR_OVERHEAD);
spin_lock(&pool->lock);
+ xmem_pool_check_locked(pool);
b->size |= FREE_BLOCK;
pool->used_size -= (b->size & BLOCK_SIZE_MASK) + BHDR_OVERHEAD;
b->ptr.free_ptr = (struct free_ptr) { NULL, NULL};
@@ -500,6 +618,7 @@ void xmem_pool_free(void *ptr, struct xmem_pool *pool)
tmp_b->size |= PREV_FREE;
tmp_b->prev_hdr = b;
out:
+ xmem_pool_check_locked(pool);
spin_unlock(&pool->lock);
}
@@ -512,8 +631,6 @@ int xmem_pool_maxalloc(struct xmem_pool *pool)
* Glue for xmalloc().
*/
-static struct xmem_pool *xenpool;
-
static void *xmalloc_pool_get(unsigned long size)
{
ASSERT(size == PAGE_SIZE);
diff --git a/xen/include/xen/xmalloc.h b/xen/include/xen/xmalloc.h
index 24a99ac..ad48930 100644
--- a/xen/include/xen/xmalloc.h
+++ b/xen/include/xen/xmalloc.h
@@ -123,4 +123,11 @@ unsigned long xmem_pool_get_used_size(struct xmem_pool
*pool);
*/
unsigned long xmem_pool_get_total_size(struct xmem_pool *pool);
+#ifndef NDEBUG
+#define xmem_pool_check(pool) __xmem_pool_check(__FILE__, __LINE__, pool)
+bool_t __xmem_pool_check(const char *file, int line, struct xmem_pool *pool);
+#else
+#define xmem_pool_check(pool) ((void)0)
+#endif
+
#endif /* __XMALLOC_H__ */
--
2.2.0
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |