aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/mmzone.h
diff options
context:
space:
mode:
authorMel Gorman <mel@csn.ul.ie>2008-04-28 05:12:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-28 11:58:19 -0400
commit19770b32609b6bf97a3dece2529089494cbfc549 (patch)
tree3b5922d1b20aabdf929bde9309f323841717747a /include/linux/mmzone.h
parentdd1a239f6f2d4d3eedd318583ec319aa145b324c (diff)
mm: filter based on a nodemask as well as a gfp_mask
The MPOL_BIND policy creates a zonelist that is used for allocations controlled by that mempolicy. As the per-node zonelist is already being filtered based on a zone id, this patch adds a version of __alloc_pages() that takes a nodemask for further filtering. This eliminates the need for MPOL_BIND to create a custom zonelist. A positive benefit of this is that allocations using MPOL_BIND now use the local node's distance-ordered zonelist instead of a custom node-id-ordered zonelist. I.e., pages will be allocated from the closest allowed node with available memory. [Lee.Schermerhorn@hp.com: Mempolicy: update stale documentation and comments] [Lee.Schermerhorn@hp.com: Mempolicy: make dequeue_huge_page_vma() obey MPOL_BIND nodemask] [Lee.Schermerhorn@hp.com: Mempolicy: make dequeue_huge_page_vma() obey MPOL_BIND nodemask rework] Signed-off-by: Mel Gorman <mel@csn.ul.ie> Acked-by: Christoph Lameter <clameter@sgi.com> Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Mel Gorman <mel@csn.ul.ie> Cc: Hugh Dickins <hugh@veritas.com> Cc: Nick Piggin <nickpiggin@yahoo.com.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux/mmzone.h')
-rw-r--r--include/linux/mmzone.h80
1 files changed, 50 insertions, 30 deletions
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index d34b4c290017..498d6ceff2f4 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -749,36 +749,60 @@ static inline int zonelist_node_idx(struct zoneref *zoneref)
749#endif /* CONFIG_NUMA */ 749#endif /* CONFIG_NUMA */
750} 750}
751 751
752static inline void zoneref_set_zone(struct zone *zone, struct zoneref *zoneref) 752/**
753{ 753 * next_zones_zonelist - Returns the next zone at or below highest_zoneidx within the allowed nodemask using a cursor within a zonelist as a starting point
754 zoneref->zone = zone; 754 * @z - The cursor used as a starting point for the search
755 zoneref->zone_idx = zone_idx(zone); 755 * @highest_zoneidx - The zone index of the highest zone to return
756} 756 * @nodes - An optional nodemask to filter the zonelist with
757 * @zone - The first suitable zone found is returned via this parameter
758 *
759 * This function returns the next zone at or below a given zone index that is
760 * within the allowed nodemask using a cursor as the starting point for the
761 * search. The zoneref returned is a cursor that is used as the next starting
762 * point for future calls to next_zones_zonelist().
763 */
764struct zoneref *next_zones_zonelist(struct zoneref *z,
765 enum zone_type highest_zoneidx,
766 nodemask_t *nodes,
767 struct zone **zone);
757 768
758/* Returns the first zone at or below highest_zoneidx in a zonelist */ 769/**
770 * first_zones_zonelist - Returns the first zone at or below highest_zoneidx within the allowed nodemask in a zonelist
771 * @zonelist - The zonelist to search for a suitable zone
772 * @highest_zoneidx - The zone index of the highest zone to return
773 * @nodes - An optional nodemask to filter the zonelist with
774 * @zone - The first suitable zone found is returned via this parameter
775 *
776 * This function returns the first zone at or below a given zone index that is
777 * within the allowed nodemask. The zoneref returned is a cursor that can be
778 * used to iterate the zonelist with next_zones_zonelist. The cursor should
779 * not be used by the caller as it does not match the value of the zone
780 * returned.
781 */
759static inline struct zoneref *first_zones_zonelist(struct zonelist *zonelist, 782static inline struct zoneref *first_zones_zonelist(struct zonelist *zonelist,
760 enum zone_type highest_zoneidx) 783 enum zone_type highest_zoneidx,
784 nodemask_t *nodes,
785 struct zone **zone)
761{ 786{
762 struct zoneref *z; 787 return next_zones_zonelist(zonelist->_zonerefs, highest_zoneidx, nodes,
763 788 zone);
764 /* Find the first suitable zone to use for the allocation */
765 z = zonelist->_zonerefs;
766 while (zonelist_zone_idx(z) > highest_zoneidx)
767 z++;
768
769 return z;
770} 789}
771 790
772/* Returns the next zone at or below highest_zoneidx in a zonelist */ 791/**
773static inline struct zoneref *next_zones_zonelist(struct zoneref *z, 792 * for_each_zone_zonelist_nodemask - helper macro to iterate over valid zones in a zonelist at or below a given zone index and within a nodemask
774 enum zone_type highest_zoneidx) 793 * @zone - The current zone in the iterator
775{ 794 * @z - The current pointer within zonelist->zones being iterated
776 /* Find the next suitable zone to use for the allocation */ 795 * @zlist - The zonelist being iterated
777 while (zonelist_zone_idx(z) > highest_zoneidx) 796 * @highidx - The zone index of the highest zone to return
778 z++; 797 * @nodemask - Nodemask allowed by the allocator
779 798 *
780 return z; 799 * This iterator iterates though all zones at or below a given zone index and
781} 800 * within a given nodemask
801 */
802#define for_each_zone_zonelist_nodemask(zone, z, zlist, highidx, nodemask) \
803 for (z = first_zones_zonelist(zlist, highidx, nodemask, &zone); \
804 zone; \
805 z = next_zones_zonelist(z, highidx, nodemask, &zone)) \
782 806
783/** 807/**
784 * for_each_zone_zonelist - helper macro to iterate over valid zones in a zonelist at or below a given zone index 808 * for_each_zone_zonelist - helper macro to iterate over valid zones in a zonelist at or below a given zone index
@@ -790,11 +814,7 @@ static inline struct zoneref *next_zones_zonelist(struct zoneref *z,
790 * This iterator iterates though all zones at or below a given zone index. 814 * This iterator iterates though all zones at or below a given zone index.
791 */ 815 */
792#define for_each_zone_zonelist(zone, z, zlist, highidx) \ 816#define for_each_zone_zonelist(zone, z, zlist, highidx) \
793 for (z = first_zones_zonelist(zlist, highidx), \ 817 for_each_zone_zonelist_nodemask(zone, z, zlist, highidx, NULL)
794 zone = zonelist_zone(z++); \
795 zone; \
796 z = next_zones_zonelist(z, highidx), \
797 zone = zonelist_zone(z++))
798 818
799#ifdef CONFIG_SPARSEMEM 819#ifdef CONFIG_SPARSEMEM
800#include <asm/sparsemem.h> 820#include <asm/sparsemem.h>