102 lines · 2.4 KB · C
RawDownload
/* * Quicklist support. * * Quicklists are light weight lists of pages that have a defined state * on alloc and free. Pages must be in the quicklist specific defined state * (zero by default) when the page is freed. It seems that the initial idea * for such lists first came from Dave Miller and then various other people * improved on it. * * Copyright (C) 2007 SGI, * 	Christoph Lameter <clameter@sgi.com> * 		Generalized, added support for multiple lists and * 		constructors / destructors. */#include <linux/kernel.h> #include <linux/gfp.h>#include <linux/mm.h>#include <linux/mmzone.h>#include <linux/quicklist.h> DEFINE_PER_CPU(struct quicklist [CONFIG_NR_QUICK], quicklist); #define FRACTION_OF_NODE_MEM	16 static unsigned long max_pages(unsigned long min_pages){	unsigned long node_free_pages, max;	int node = numa_node_id();	struct zone *zones = NODE_DATA(node)->node_zones;	int num_cpus_on_node; 	node_free_pages =#ifdef CONFIG_ZONE_DMA		zone_page_state(&zones[ZONE_DMA], NR_FREE_PAGES) +#endif#ifdef CONFIG_ZONE_DMA32		zone_page_state(&zones[ZONE_DMA32], NR_FREE_PAGES) +#endif		zone_page_state(&zones[ZONE_NORMAL], NR_FREE_PAGES); 	max = node_free_pages / FRACTION_OF_NODE_MEM; 	num_cpus_on_node = cpumask_weight(cpumask_of_node(node));	max /= num_cpus_on_node; 	return max(max, min_pages);} static long min_pages_to_free(struct quicklist *q,	unsigned long min_pages, long max_free){	long pages_to_free; 	pages_to_free = q->nr_pages - max_pages(min_pages); 	return min(pages_to_free, max_free);} /* * Trim down the number of pages in the quicklist */void quicklist_trim(int nr, void (*dtor)(void *),	unsigned long min_pages, unsigned long max_free){	long pages_to_free;	struct quicklist *q; 	q = &get_cpu_var(quicklist)[nr];	if (q->nr_pages > min_pages) {		pages_to_free = min_pages_to_free(q, min_pages, max_free); 		while (pages_to_free > 0) {			/*			 * We pass a gfp_t of 0 to quicklist_alloc here			 * because we will never call into the page allocator.			 */			void *p = quicklist_alloc(nr, 0, NULL); 			if (dtor)				dtor(p);			free_page((unsigned long)p);			pages_to_free--;		}	}	put_cpu_var(quicklist);} unsigned long quicklist_total_size(void){	unsigned long count = 0;	int cpu;	struct quicklist *ql, *q; 	for_each_online_cpu(cpu) {		ql = per_cpu(quicklist, cpu);		for (q = ql; q < ql + CONFIG_NR_QUICK; q++)			count += q->nr_pages;	}	return count;}