mm, page_alloc: avoid looking up the first zone in a zonelist twice
[cascardo/linux.git] / include / linux / mmzone.h
index c60df92..4b28d2f 100644 (file)
@@ -747,7 +747,8 @@ extern struct mutex zonelists_mutex;
 void build_all_zonelists(pg_data_t *pgdat, struct zone *zone);
 void wakeup_kswapd(struct zone *zone, int order, enum zone_type classzone_idx);
 bool zone_watermark_ok(struct zone *z, unsigned int order,
-               unsigned long mark, int classzone_idx, int alloc_flags);
+               unsigned long mark, int classzone_idx,
+               unsigned int alloc_flags);
 bool zone_watermark_ok_safe(struct zone *z, unsigned int order,
                unsigned long mark, int classzone_idx);
 enum memmap_context {
@@ -828,10 +829,7 @@ static inline int is_highmem_idx(enum zone_type idx)
 static inline int is_highmem(struct zone *zone)
 {
 #ifdef CONFIG_HIGHMEM
-       int zone_off = (char *)zone - (char *)zone->zone_pgdat->node_zones;
-       return zone_off == ZONE_HIGHMEM * sizeof(*zone) ||
-              (zone_off == ZONE_MOVABLE * sizeof(*zone) &&
-               zone_movable_is_highmem());
+       return is_highmem_idx(zone_idx(zone));
 #else
        return 0;
 #endif
@@ -922,6 +920,10 @@ static inline int zonelist_node_idx(struct zoneref *zoneref)
 #endif /* CONFIG_NUMA */
 }
 
+struct zoneref *__next_zones_zonelist(struct zoneref *z,
+                                       enum zone_type highest_zoneidx,
+                                       nodemask_t *nodes);
+
 /**
  * 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
  * @z - The cursor used as a starting point for the search
@@ -934,9 +936,14 @@ static inline int zonelist_node_idx(struct zoneref *zoneref)
  * being examined. It should be advanced by one before calling
  * next_zones_zonelist again.
  */
-struct zoneref *next_zones_zonelist(struct zoneref *z,
+static __always_inline struct zoneref *next_zones_zonelist(struct zoneref *z,
                                        enum zone_type highest_zoneidx,
-                                       nodemask_t *nodes);
+                                       nodemask_t *nodes)
+{
+       if (likely(!nodes && zonelist_zone_idx(z) <= highest_zoneidx))
+               return z;
+       return __next_zones_zonelist(z, highest_zoneidx, nodes);
+}
 
 /**
  * first_zones_zonelist - Returns the first zone at or below highest_zoneidx within the allowed nodemask in a zonelist
@@ -952,13 +959,10 @@ struct zoneref *next_zones_zonelist(struct zoneref *z,
  */
 static inline struct zoneref *first_zones_zonelist(struct zonelist *zonelist,
                                        enum zone_type highest_zoneidx,
-                                       nodemask_t *nodes,
-                                       struct zone **zone)
+                                       nodemask_t *nodes)
 {
-       struct zoneref *z = next_zones_zonelist(zonelist->_zonerefs,
+       return next_zones_zonelist(zonelist->_zonerefs,
                                                        highest_zoneidx, nodes);
-       *zone = zonelist_zone(z);
-       return z;
 }
 
 /**
@@ -973,10 +977,17 @@ static inline struct zoneref *first_zones_zonelist(struct zonelist *zonelist,
  * within a given nodemask
  */
 #define for_each_zone_zonelist_nodemask(zone, z, zlist, highidx, nodemask) \
-       for (z = first_zones_zonelist(zlist, highidx, nodemask, &zone); \
+       for (z = first_zones_zonelist(zlist, highidx, nodemask), zone = zonelist_zone(z);       \
                zone;                                                   \
                z = next_zones_zonelist(++z, highidx, nodemask),        \
-                       zone = zonelist_zone(z))                        \
+                       zone = zonelist_zone(z))
+
+#define for_next_zone_zonelist_nodemask(zone, z, zlist, highidx, nodemask) \
+       for (zone = z->zone;    \
+               zone;                                                   \
+               z = next_zones_zonelist(++z, highidx, nodemask),        \
+                       zone = zonelist_zone(z))
+
 
 /**
  * for_each_zone_zonelist - helper macro to iterate over valid zones in a zonelist at or below a given zone index