From 46055572cf87aee3e0a7be9aeac73726bccd5178 Mon Sep 17 00:00:00 2001 From: nikita Date: Fri, 8 Aug 2008 13:51:27 +0000 Subject: [PATCH] libcfs: add cfs_mem_is_in_cache() checking that a given pointer points at the object allocated from a given slab. --- libcfs/include/libcfs/linux/linux-mem.h | 3 ++- libcfs/include/libcfs/user-mem.h | 1 + libcfs/libcfs/linux/linux-mem.c | 22 ++++++++++++++++++++++ libcfs/libcfs/user-mem.c | 11 +++++++++++ 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/libcfs/include/libcfs/linux/linux-mem.h b/libcfs/include/libcfs/linux/linux-mem.h index d5cf0d3..19dec15 100644 --- a/libcfs/include/libcfs/linux/linux-mem.h +++ b/libcfs/include/libcfs/linux/linux-mem.h @@ -47,7 +47,7 @@ #ifndef __KERNEL__ #error This include is only for kernel use. -#endif +#endif #include #include @@ -129,6 +129,7 @@ extern cfs_mem_cache_t * cfs_mem_cache_create (const char *, size_t, size_t, uns extern int cfs_mem_cache_destroy ( cfs_mem_cache_t * ); extern void *cfs_mem_cache_alloc ( cfs_mem_cache_t *, int); extern void cfs_mem_cache_free ( cfs_mem_cache_t *, void *); +extern int cfs_mem_is_in_cache(const void *addr, const cfs_mem_cache_t *kmem); /* */ diff --git a/libcfs/include/libcfs/user-mem.h b/libcfs/include/libcfs/user-mem.h index 3b0a606..701d8f8 100644 --- a/libcfs/include/libcfs/user-mem.h +++ b/libcfs/include/libcfs/user-mem.h @@ -86,6 +86,7 @@ cfs_mem_cache_create(const char *, size_t, size_t, unsigned long); int cfs_mem_cache_destroy(cfs_mem_cache_t *c); void *cfs_mem_cache_alloc(cfs_mem_cache_t *c, int gfp); void cfs_mem_cache_free(cfs_mem_cache_t *c, void *addr); +int cfs_mem_is_in_cache(const void *addr, const cfs_mem_cache_t *kmem); /* * Copy to/from user diff --git a/libcfs/libcfs/linux/linux-mem.c b/libcfs/libcfs/linux/linux-mem.c index 04ccd4e..20f3667 100644 --- a/libcfs/libcfs/linux/linux-mem.c +++ b/libcfs/libcfs/linux/linux-mem.c @@ -148,6 +148,28 @@ cfs_mem_cache_free(cfs_mem_cache_t *cachep, void *objp) return kmem_cache_free(cachep, objp); } +/** + * Returns true if \a addr is an address of an allocated object in a slab \a + * kmem. Used in assertions. This check is optimistically imprecise, i.e., it + * occasionally returns true for the incorrect addresses, but if it returns + * false, then the addresses is guaranteed to be incorrect. + */ +int cfs_mem_is_in_cache(const void *addr, const cfs_mem_cache_t *kmem) +{ + struct page *page; + + /* + * XXX Copy of mm/slab.c:virt_to_cache(). It won't work with other + * allocators, like slub and slob. + */ + page = virt_to_page(addr); + if (unlikely(PageCompound(page))) + page = (struct page *)page_private(page); + return PageSlab(page) && ((void *)page->lru.next) == kmem; +} +EXPORT_SYMBOL(cfs_mem_is_in_cache); + + EXPORT_SYMBOL(cfs_alloc); EXPORT_SYMBOL(cfs_free); EXPORT_SYMBOL(cfs_alloc_large); diff --git a/libcfs/libcfs/user-mem.c b/libcfs/libcfs/user-mem.c index f1c44f5..7c2cc4d 100644 --- a/libcfs/libcfs/user-mem.c +++ b/libcfs/libcfs/user-mem.c @@ -153,3 +153,14 @@ void cfs_mem_cache_free(cfs_mem_cache_t *c, void *addr) { cfs_free(addr); } + +/** + * Returns true if \a addr is an address of an allocated object in a slab \a + * kmem. Used in assertions. This check is optimistically imprecise, i.e., it + * occasionally returns true for the incorrect addresses, but if it returns + * false, then the addresses is guaranteed to be incorrect. + */ +int cfs_mem_is_in_cache(const void *addr, const cfs_mem_cache_t *kmem) +{ + return 1; +} -- 1.8.3.1