|
@@ -607,6 +607,79 @@ err:
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * common helper functions for hstate_next_node_to_{alloc|free}.
|
|
|
|
+ * We may have allocated or freed a huge page based on a different
|
|
|
|
+ * nodes_allowed previously, so h->next_node_to_{alloc|free} might
|
|
|
|
+ * be outside of *nodes_allowed. Ensure that we use an allowed
|
|
|
|
+ * node for alloc or free.
|
|
|
|
+ */
|
|
|
|
+static int next_node_allowed(int nid, nodemask_t *nodes_allowed)
|
|
|
|
+{
|
|
|
|
+ nid = next_node(nid, *nodes_allowed);
|
|
|
|
+ if (nid == MAX_NUMNODES)
|
|
|
|
+ nid = first_node(*nodes_allowed);
|
|
|
|
+ VM_BUG_ON(nid >= MAX_NUMNODES);
|
|
|
|
+
|
|
|
|
+ return nid;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int get_valid_node_allowed(int nid, nodemask_t *nodes_allowed)
|
|
|
|
+{
|
|
|
|
+ if (!node_isset(nid, *nodes_allowed))
|
|
|
|
+ nid = next_node_allowed(nid, nodes_allowed);
|
|
|
|
+ return nid;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * returns the previously saved node ["this node"] from which to
|
|
|
|
+ * allocate a persistent huge page for the pool and advance the
|
|
|
|
+ * next node from which to allocate, handling wrap at end of node
|
|
|
|
+ * mask.
|
|
|
|
+ */
|
|
|
|
+static int hstate_next_node_to_alloc(struct hstate *h,
|
|
|
|
+ nodemask_t *nodes_allowed)
|
|
|
|
+{
|
|
|
|
+ int nid;
|
|
|
|
+
|
|
|
|
+ VM_BUG_ON(!nodes_allowed);
|
|
|
|
+
|
|
|
|
+ nid = get_valid_node_allowed(h->next_nid_to_alloc, nodes_allowed);
|
|
|
|
+ h->next_nid_to_alloc = next_node_allowed(nid, nodes_allowed);
|
|
|
|
+
|
|
|
|
+ return nid;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * helper for free_pool_huge_page() - return the previously saved
|
|
|
|
+ * node ["this node"] from which to free a huge page. Advance the
|
|
|
|
+ * next node id whether or not we find a free huge page to free so
|
|
|
|
+ * that the next attempt to free addresses the next node.
|
|
|
|
+ */
|
|
|
|
+static int hstate_next_node_to_free(struct hstate *h, nodemask_t *nodes_allowed)
|
|
|
|
+{
|
|
|
|
+ int nid;
|
|
|
|
+
|
|
|
|
+ VM_BUG_ON(!nodes_allowed);
|
|
|
|
+
|
|
|
|
+ nid = get_valid_node_allowed(h->next_nid_to_free, nodes_allowed);
|
|
|
|
+ h->next_nid_to_free = next_node_allowed(nid, nodes_allowed);
|
|
|
|
+
|
|
|
|
+ return nid;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#define for_each_node_mask_to_alloc(hs, nr_nodes, node, mask) \
|
|
|
|
+ for (nr_nodes = nodes_weight(*mask); \
|
|
|
|
+ nr_nodes > 0 && \
|
|
|
|
+ ((node = hstate_next_node_to_alloc(hs, mask)) || 1); \
|
|
|
|
+ nr_nodes--)
|
|
|
|
+
|
|
|
|
+#define for_each_node_mask_to_free(hs, nr_nodes, node, mask) \
|
|
|
|
+ for (nr_nodes = nodes_weight(*mask); \
|
|
|
|
+ nr_nodes > 0 && \
|
|
|
|
+ ((node = hstate_next_node_to_free(hs, mask)) || 1); \
|
|
|
|
+ nr_nodes--)
|
|
|
|
+
|
|
static void update_and_free_page(struct hstate *h, struct page *page)
|
|
static void update_and_free_page(struct hstate *h, struct page *page)
|
|
{
|
|
{
|
|
int i;
|
|
int i;
|
|
@@ -786,79 +859,6 @@ static struct page *alloc_fresh_huge_page_node(struct hstate *h, int nid)
|
|
return page;
|
|
return page;
|
|
}
|
|
}
|
|
|
|
|
|
-/*
|
|
|
|
- * common helper functions for hstate_next_node_to_{alloc|free}.
|
|
|
|
- * We may have allocated or freed a huge page based on a different
|
|
|
|
- * nodes_allowed previously, so h->next_node_to_{alloc|free} might
|
|
|
|
- * be outside of *nodes_allowed. Ensure that we use an allowed
|
|
|
|
- * node for alloc or free.
|
|
|
|
- */
|
|
|
|
-static int next_node_allowed(int nid, nodemask_t *nodes_allowed)
|
|
|
|
-{
|
|
|
|
- nid = next_node(nid, *nodes_allowed);
|
|
|
|
- if (nid == MAX_NUMNODES)
|
|
|
|
- nid = first_node(*nodes_allowed);
|
|
|
|
- VM_BUG_ON(nid >= MAX_NUMNODES);
|
|
|
|
-
|
|
|
|
- return nid;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static int get_valid_node_allowed(int nid, nodemask_t *nodes_allowed)
|
|
|
|
-{
|
|
|
|
- if (!node_isset(nid, *nodes_allowed))
|
|
|
|
- nid = next_node_allowed(nid, nodes_allowed);
|
|
|
|
- return nid;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/*
|
|
|
|
- * returns the previously saved node ["this node"] from which to
|
|
|
|
- * allocate a persistent huge page for the pool and advance the
|
|
|
|
- * next node from which to allocate, handling wrap at end of node
|
|
|
|
- * mask.
|
|
|
|
- */
|
|
|
|
-static int hstate_next_node_to_alloc(struct hstate *h,
|
|
|
|
- nodemask_t *nodes_allowed)
|
|
|
|
-{
|
|
|
|
- int nid;
|
|
|
|
-
|
|
|
|
- VM_BUG_ON(!nodes_allowed);
|
|
|
|
-
|
|
|
|
- nid = get_valid_node_allowed(h->next_nid_to_alloc, nodes_allowed);
|
|
|
|
- h->next_nid_to_alloc = next_node_allowed(nid, nodes_allowed);
|
|
|
|
-
|
|
|
|
- return nid;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/*
|
|
|
|
- * helper for free_pool_huge_page() - return the previously saved
|
|
|
|
- * node ["this node"] from which to free a huge page. Advance the
|
|
|
|
- * next node id whether or not we find a free huge page to free so
|
|
|
|
- * that the next attempt to free addresses the next node.
|
|
|
|
- */
|
|
|
|
-static int hstate_next_node_to_free(struct hstate *h, nodemask_t *nodes_allowed)
|
|
|
|
-{
|
|
|
|
- int nid;
|
|
|
|
-
|
|
|
|
- VM_BUG_ON(!nodes_allowed);
|
|
|
|
-
|
|
|
|
- nid = get_valid_node_allowed(h->next_nid_to_free, nodes_allowed);
|
|
|
|
- h->next_nid_to_free = next_node_allowed(nid, nodes_allowed);
|
|
|
|
-
|
|
|
|
- return nid;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-#define for_each_node_mask_to_alloc(hs, nr_nodes, node, mask) \
|
|
|
|
- for (nr_nodes = nodes_weight(*mask); \
|
|
|
|
- nr_nodes > 0 && \
|
|
|
|
- ((node = hstate_next_node_to_alloc(hs, mask)) || 1); \
|
|
|
|
- nr_nodes--)
|
|
|
|
-
|
|
|
|
-#define for_each_node_mask_to_free(hs, nr_nodes, node, mask) \
|
|
|
|
- for (nr_nodes = nodes_weight(*mask); \
|
|
|
|
- nr_nodes > 0 && \
|
|
|
|
- ((node = hstate_next_node_to_free(hs, mask)) || 1); \
|
|
|
|
- nr_nodes--)
|
|
|
|
-
|
|
|
|
static int alloc_fresh_huge_page(struct hstate *h, nodemask_t *nodes_allowed)
|
|
static int alloc_fresh_huge_page(struct hstate *h, nodemask_t *nodes_allowed)
|
|
{
|
|
{
|
|
struct page *page;
|
|
struct page *page;
|