mirror of
				https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
				synced 2025-10-31 09:36:25 +00:00 
			
		
		
		
	 e992cd9b72
			
		
	
	
		e992cd9b72
		
	
	
	
	
		
			
			It turns out that even zero-sized struct members (int foo[0];) will affect the struct layout, causing us in particular to lose 4 bytes in struct sock. This patch fixes the regression in CONFIG_KMEMCHECK=n case. Reported-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: Vegard Nossum <vegard.nossum@gmail.com> Acked-by: Pekka Enberg <penberg@cs.helsinki.fi> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
		
			
				
	
	
		
			172 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			172 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #ifndef LINUX_KMEMCHECK_H
 | |
| #define LINUX_KMEMCHECK_H
 | |
| 
 | |
| #include <linux/mm_types.h>
 | |
| #include <linux/types.h>
 | |
| 
 | |
| #ifdef CONFIG_KMEMCHECK
 | |
| extern int kmemcheck_enabled;
 | |
| 
 | |
| /* The slab-related functions. */
 | |
| void kmemcheck_alloc_shadow(struct page *page, int order, gfp_t flags, int node);
 | |
| void kmemcheck_free_shadow(struct page *page, int order);
 | |
| void kmemcheck_slab_alloc(struct kmem_cache *s, gfp_t gfpflags, void *object,
 | |
| 			  size_t size);
 | |
| void kmemcheck_slab_free(struct kmem_cache *s, void *object, size_t size);
 | |
| 
 | |
| void kmemcheck_pagealloc_alloc(struct page *p, unsigned int order,
 | |
| 			       gfp_t gfpflags);
 | |
| 
 | |
| void kmemcheck_show_pages(struct page *p, unsigned int n);
 | |
| void kmemcheck_hide_pages(struct page *p, unsigned int n);
 | |
| 
 | |
| bool kmemcheck_page_is_tracked(struct page *p);
 | |
| 
 | |
| void kmemcheck_mark_unallocated(void *address, unsigned int n);
 | |
| void kmemcheck_mark_uninitialized(void *address, unsigned int n);
 | |
| void kmemcheck_mark_initialized(void *address, unsigned int n);
 | |
| void kmemcheck_mark_freed(void *address, unsigned int n);
 | |
| 
 | |
| void kmemcheck_mark_unallocated_pages(struct page *p, unsigned int n);
 | |
| void kmemcheck_mark_uninitialized_pages(struct page *p, unsigned int n);
 | |
| void kmemcheck_mark_initialized_pages(struct page *p, unsigned int n);
 | |
| 
 | |
| int kmemcheck_show_addr(unsigned long address);
 | |
| int kmemcheck_hide_addr(unsigned long address);
 | |
| 
 | |
| bool kmemcheck_is_obj_initialized(unsigned long addr, size_t size);
 | |
| 
 | |
| /*
 | |
|  * Bitfield annotations
 | |
|  *
 | |
|  * How to use: If you have a struct using bitfields, for example
 | |
|  *
 | |
|  *     struct a {
 | |
|  *             int x:8, y:8;
 | |
|  *     };
 | |
|  *
 | |
|  * then this should be rewritten as
 | |
|  *
 | |
|  *     struct a {
 | |
|  *             kmemcheck_bitfield_begin(flags);
 | |
|  *             int x:8, y:8;
 | |
|  *             kmemcheck_bitfield_end(flags);
 | |
|  *     };
 | |
|  *
 | |
|  * Now the "flags_begin" and "flags_end" members may be used to refer to the
 | |
|  * beginning and end, respectively, of the bitfield (and things like
 | |
|  * &x.flags_begin is allowed). As soon as the struct is allocated, the bit-
 | |
|  * fields should be annotated:
 | |
|  *
 | |
|  *     struct a *a = kmalloc(sizeof(struct a), GFP_KERNEL);
 | |
|  *     kmemcheck_annotate_bitfield(a, flags);
 | |
|  */
 | |
| #define kmemcheck_bitfield_begin(name)	\
 | |
| 	int name##_begin[0];
 | |
| 
 | |
| #define kmemcheck_bitfield_end(name)	\
 | |
| 	int name##_end[0];
 | |
| 
 | |
| #define kmemcheck_annotate_bitfield(ptr, name)				\
 | |
| 	do {								\
 | |
| 		int _n;							\
 | |
| 									\
 | |
| 		if (!ptr)						\
 | |
| 			break;						\
 | |
| 									\
 | |
| 		_n = (long) &((ptr)->name##_end)			\
 | |
| 			- (long) &((ptr)->name##_begin);		\
 | |
| 		MAYBE_BUILD_BUG_ON(_n < 0);				\
 | |
| 									\
 | |
| 		kmemcheck_mark_initialized(&((ptr)->name##_begin), _n);	\
 | |
| 	} while (0)
 | |
| 
 | |
| #define kmemcheck_annotate_variable(var)				\
 | |
| 	do {								\
 | |
| 		kmemcheck_mark_initialized(&(var), sizeof(var));	\
 | |
| 	} while (0)							\
 | |
| 
 | |
| #else
 | |
| #define kmemcheck_enabled 0
 | |
| 
 | |
| static inline void
 | |
| kmemcheck_alloc_shadow(struct page *page, int order, gfp_t flags, int node)
 | |
| {
 | |
| }
 | |
| 
 | |
| static inline void
 | |
| kmemcheck_free_shadow(struct page *page, int order)
 | |
| {
 | |
| }
 | |
| 
 | |
| static inline void
 | |
| kmemcheck_slab_alloc(struct kmem_cache *s, gfp_t gfpflags, void *object,
 | |
| 		     size_t size)
 | |
| {
 | |
| }
 | |
| 
 | |
| static inline void kmemcheck_slab_free(struct kmem_cache *s, void *object,
 | |
| 				       size_t size)
 | |
| {
 | |
| }
 | |
| 
 | |
| static inline void kmemcheck_pagealloc_alloc(struct page *p,
 | |
| 	unsigned int order, gfp_t gfpflags)
 | |
| {
 | |
| }
 | |
| 
 | |
| static inline bool kmemcheck_page_is_tracked(struct page *p)
 | |
| {
 | |
| 	return false;
 | |
| }
 | |
| 
 | |
| static inline void kmemcheck_mark_unallocated(void *address, unsigned int n)
 | |
| {
 | |
| }
 | |
| 
 | |
| static inline void kmemcheck_mark_uninitialized(void *address, unsigned int n)
 | |
| {
 | |
| }
 | |
| 
 | |
| static inline void kmemcheck_mark_initialized(void *address, unsigned int n)
 | |
| {
 | |
| }
 | |
| 
 | |
| static inline void kmemcheck_mark_freed(void *address, unsigned int n)
 | |
| {
 | |
| }
 | |
| 
 | |
| static inline void kmemcheck_mark_unallocated_pages(struct page *p,
 | |
| 						    unsigned int n)
 | |
| {
 | |
| }
 | |
| 
 | |
| static inline void kmemcheck_mark_uninitialized_pages(struct page *p,
 | |
| 						      unsigned int n)
 | |
| {
 | |
| }
 | |
| 
 | |
| static inline void kmemcheck_mark_initialized_pages(struct page *p,
 | |
| 						    unsigned int n)
 | |
| {
 | |
| }
 | |
| 
 | |
| static inline bool kmemcheck_is_obj_initialized(unsigned long addr, size_t size)
 | |
| {
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| #define kmemcheck_bitfield_begin(name)
 | |
| #define kmemcheck_bitfield_end(name)
 | |
| #define kmemcheck_annotate_bitfield(ptr, name)	\
 | |
| 	do {					\
 | |
| 	} while (0)
 | |
| 
 | |
| #define kmemcheck_annotate_variable(var)	\
 | |
| 	do {					\
 | |
| 	} while (0)
 | |
| 
 | |
| #endif /* CONFIG_KMEMCHECK */
 | |
| 
 | |
| #endif /* LINUX_KMEMCHECK_H */
 |