|
@@ -13,6 +13,7 @@
|
|
|
#include <linux/numa.h>
|
|
|
#include <linux/init.h>
|
|
|
#include <linux/seqlock.h>
|
|
|
+#include <linux/nodemask.h>
|
|
|
#include <asm/atomic.h>
|
|
|
|
|
|
/* Free memory management - zoned buddy allocator. */
|
|
@@ -349,57 +350,6 @@ unsigned long __init node_memmap_size_bytes(int, unsigned long, unsigned long);
|
|
|
*/
|
|
|
#define zone_idx(zone) ((zone) - (zone)->zone_pgdat->node_zones)
|
|
|
|
|
|
-/**
|
|
|
- * for_each_pgdat - helper macro to iterate over all nodes
|
|
|
- * @pgdat - pointer to a pg_data_t variable
|
|
|
- *
|
|
|
- * Meant to help with common loops of the form
|
|
|
- * pgdat = pgdat_list;
|
|
|
- * while(pgdat) {
|
|
|
- * ...
|
|
|
- * pgdat = pgdat->pgdat_next;
|
|
|
- * }
|
|
|
- */
|
|
|
-#define for_each_pgdat(pgdat) \
|
|
|
- for (pgdat = pgdat_list; pgdat; pgdat = pgdat->pgdat_next)
|
|
|
-
|
|
|
-/*
|
|
|
- * next_zone - helper magic for for_each_zone()
|
|
|
- * Thanks to William Lee Irwin III for this piece of ingenuity.
|
|
|
- */
|
|
|
-static inline struct zone *next_zone(struct zone *zone)
|
|
|
-{
|
|
|
- pg_data_t *pgdat = zone->zone_pgdat;
|
|
|
-
|
|
|
- if (zone < pgdat->node_zones + MAX_NR_ZONES - 1)
|
|
|
- zone++;
|
|
|
- else if (pgdat->pgdat_next) {
|
|
|
- pgdat = pgdat->pgdat_next;
|
|
|
- zone = pgdat->node_zones;
|
|
|
- } else
|
|
|
- zone = NULL;
|
|
|
-
|
|
|
- return zone;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * for_each_zone - helper macro to iterate over all memory zones
|
|
|
- * @zone - pointer to struct zone variable
|
|
|
- *
|
|
|
- * The user only needs to declare the zone variable, for_each_zone
|
|
|
- * fills it in. This basically means for_each_zone() is an
|
|
|
- * easier to read version of this piece of code:
|
|
|
- *
|
|
|
- * for (pgdat = pgdat_list; pgdat; pgdat = pgdat->node_next)
|
|
|
- * for (i = 0; i < MAX_NR_ZONES; ++i) {
|
|
|
- * struct zone * z = pgdat->node_zones + i;
|
|
|
- * ...
|
|
|
- * }
|
|
|
- * }
|
|
|
- */
|
|
|
-#define for_each_zone(zone) \
|
|
|
- for (zone = pgdat_list->node_zones; zone; zone = next_zone(zone))
|
|
|
-
|
|
|
static inline int populated_zone(struct zone *zone)
|
|
|
{
|
|
|
return (!!zone->present_pages);
|
|
@@ -471,6 +421,62 @@ extern struct pglist_data contig_page_data;
|
|
|
|
|
|
#endif /* !CONFIG_NEED_MULTIPLE_NODES */
|
|
|
|
|
|
+static inline struct pglist_data *first_online_pgdat(void)
|
|
|
+{
|
|
|
+ return NODE_DATA(first_online_node);
|
|
|
+}
|
|
|
+
|
|
|
+static inline struct pglist_data *next_online_pgdat(struct pglist_data *pgdat)
|
|
|
+{
|
|
|
+ int nid = next_online_node(pgdat->node_id);
|
|
|
+
|
|
|
+ if (nid == MAX_NUMNODES)
|
|
|
+ return NULL;
|
|
|
+ return NODE_DATA(nid);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * for_each_pgdat - helper macro to iterate over all nodes
|
|
|
+ * @pgdat - pointer to a pg_data_t variable
|
|
|
+ */
|
|
|
+#define for_each_online_pgdat(pgdat) \
|
|
|
+ for (pgdat = first_online_pgdat(); \
|
|
|
+ pgdat; \
|
|
|
+ pgdat = next_online_pgdat(pgdat))
|
|
|
+
|
|
|
+/*
|
|
|
+ * next_zone - helper magic for for_each_zone()
|
|
|
+ * Thanks to William Lee Irwin III for this piece of ingenuity.
|
|
|
+ */
|
|
|
+static inline struct zone *next_zone(struct zone *zone)
|
|
|
+{
|
|
|
+ pg_data_t *pgdat = zone->zone_pgdat;
|
|
|
+
|
|
|
+ if (zone < pgdat->node_zones + MAX_NR_ZONES - 1)
|
|
|
+ zone++;
|
|
|
+ else {
|
|
|
+ pgdat = next_online_pgdat(pgdat);
|
|
|
+ if (pgdat)
|
|
|
+ zone = pgdat->node_zones;
|
|
|
+ else
|
|
|
+ zone = NULL;
|
|
|
+ }
|
|
|
+ return zone;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * for_each_zone - helper macro to iterate over all memory zones
|
|
|
+ * @zone - pointer to struct zone variable
|
|
|
+ *
|
|
|
+ * The user only needs to declare the zone variable, for_each_zone
|
|
|
+ * fills it in.
|
|
|
+ */
|
|
|
+#define for_each_zone(zone) \
|
|
|
+ for (zone = (first_online_pgdat())->node_zones; \
|
|
|
+ zone; \
|
|
|
+ zone = next_zone(zone))
|
|
|
+
|
|
|
#ifdef CONFIG_SPARSEMEM
|
|
|
#include <asm/sparsemem.h>
|
|
|
#endif
|