mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	mm: add a signature in struct page
This is needed by the page_pool to avoid recycling a page not allocated via page_pool. The page->signature field is aliased to page->lru.next and page->compound_head, but it can't be set by mistake because the signature value is a bad pointer, and can't trigger a false positive in PageTail() because the last bit is 0. Co-developed-by: Matthew Wilcox (Oracle) <willy@infradead.org> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Signed-off-by: Matteo Croce <mcroce@microsoft.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									35cba15a50
								
							
						
					
					
						commit
						c07aea3ef4
					
				
					 4 changed files with 22 additions and 5 deletions
				
			
		| 
						 | 
					@ -1668,10 +1668,11 @@ struct address_space *page_mapping(struct page *page);
 | 
				
			||||||
static inline bool page_is_pfmemalloc(const struct page *page)
 | 
					static inline bool page_is_pfmemalloc(const struct page *page)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Page index cannot be this large so this must be
 | 
						 * lru.next has bit 1 set if the page is allocated from the
 | 
				
			||||||
	 * a pfmemalloc page.
 | 
						 * pfmemalloc reserves.  Callers may simply overwrite it if
 | 
				
			||||||
 | 
						 * they do not need to preserve that information.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	return page->index == -1UL;
 | 
						return (uintptr_t)page->lru.next & BIT(1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -1680,12 +1681,12 @@ static inline bool page_is_pfmemalloc(const struct page *page)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static inline void set_page_pfmemalloc(struct page *page)
 | 
					static inline void set_page_pfmemalloc(struct page *page)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	page->index = -1UL;
 | 
						page->lru.next = (void *)BIT(1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void clear_page_pfmemalloc(struct page *page)
 | 
					static inline void clear_page_pfmemalloc(struct page *page)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	page->index = 0;
 | 
						page->lru.next = NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -96,6 +96,13 @@ struct page {
 | 
				
			||||||
			unsigned long private;
 | 
								unsigned long private;
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
		struct {	/* page_pool used by netstack */
 | 
							struct {	/* page_pool used by netstack */
 | 
				
			||||||
 | 
								/**
 | 
				
			||||||
 | 
								 * @pp_magic: magic value to avoid recycling non
 | 
				
			||||||
 | 
								 * page_pool allocated pages.
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								unsigned long pp_magic;
 | 
				
			||||||
 | 
								struct page_pool *pp;
 | 
				
			||||||
 | 
								unsigned long _pp_mapping_pad;
 | 
				
			||||||
			/**
 | 
								/**
 | 
				
			||||||
			 * @dma_addr: might require a 64-bit value on
 | 
								 * @dma_addr: might require a 64-bit value on
 | 
				
			||||||
			 * 32-bit architectures.
 | 
								 * 32-bit architectures.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -78,4 +78,7 @@
 | 
				
			||||||
/********** security/ **********/
 | 
					/********** security/ **********/
 | 
				
			||||||
#define KEY_DESTROY		0xbd
 | 
					#define KEY_DESTROY		0xbd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/********** net/core/page_pool.c **********/
 | 
				
			||||||
 | 
					#define PP_SIGNATURE		(0x40 + POISON_POINTER_DELTA)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,6 +17,7 @@
 | 
				
			||||||
#include <linux/dma-mapping.h>
 | 
					#include <linux/dma-mapping.h>
 | 
				
			||||||
#include <linux/page-flags.h>
 | 
					#include <linux/page-flags.h>
 | 
				
			||||||
#include <linux/mm.h> /* for __put_page() */
 | 
					#include <linux/mm.h> /* for __put_page() */
 | 
				
			||||||
 | 
					#include <linux/poison.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <trace/events/page_pool.h>
 | 
					#include <trace/events/page_pool.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -221,6 +222,8 @@ static struct page *__page_pool_alloc_page_order(struct page_pool *pool,
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						page->pp_magic |= PP_SIGNATURE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Track how many pages are held 'in-flight' */
 | 
						/* Track how many pages are held 'in-flight' */
 | 
				
			||||||
	pool->pages_state_hold_cnt++;
 | 
						pool->pages_state_hold_cnt++;
 | 
				
			||||||
	trace_page_pool_state_hold(pool, page, pool->pages_state_hold_cnt);
 | 
						trace_page_pool_state_hold(pool, page, pool->pages_state_hold_cnt);
 | 
				
			||||||
| 
						 | 
					@ -263,6 +266,7 @@ static struct page *__page_pool_alloc_pages_slow(struct page_pool *pool,
 | 
				
			||||||
			put_page(page);
 | 
								put_page(page);
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							page->pp_magic |= PP_SIGNATURE;
 | 
				
			||||||
		pool->alloc.cache[pool->alloc.count++] = page;
 | 
							pool->alloc.cache[pool->alloc.count++] = page;
 | 
				
			||||||
		/* Track how many pages are held 'in-flight' */
 | 
							/* Track how many pages are held 'in-flight' */
 | 
				
			||||||
		pool->pages_state_hold_cnt++;
 | 
							pool->pages_state_hold_cnt++;
 | 
				
			||||||
| 
						 | 
					@ -341,6 +345,8 @@ void page_pool_release_page(struct page_pool *pool, struct page *page)
 | 
				
			||||||
			     DMA_ATTR_SKIP_CPU_SYNC);
 | 
								     DMA_ATTR_SKIP_CPU_SYNC);
 | 
				
			||||||
	page_pool_set_dma_addr(page, 0);
 | 
						page_pool_set_dma_addr(page, 0);
 | 
				
			||||||
skip_dma_unmap:
 | 
					skip_dma_unmap:
 | 
				
			||||||
 | 
						page->pp_magic = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* This may be the last page returned, releasing the pool, so
 | 
						/* This may be the last page returned, releasing the pool, so
 | 
				
			||||||
	 * it is not safe to reference pool afterwards.
 | 
						 * it is not safe to reference pool afterwards.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue