diff --git a/include/linux/list_lru.h b/include/linux/list_lru.h index 4d02ad3badab..3ce541753c88 100644 --- a/include/linux/list_lru.h +++ b/include/linux/list_lru.h @@ -27,20 +27,11 @@ struct list_lru_node { } ____cacheline_aligned_in_smp; struct list_lru { - /* - * Because we use a fixed-size array, this struct can be very big if - * MAX_NUMNODES is big. If this becomes a problem this is fixable by - * turning this into a pointer and dynamically allocating this to - * nr_node_ids. This quantity is firwmare-provided, and still would - * provide room for all nodes at the cost of a pointer lookup and an - * extra allocation. Because that allocation will most likely come from - * a different slab cache than the main structure holding this - * structure, we may very well fail. - */ - struct list_lru_node node[MAX_NUMNODES]; + struct list_lru_node *node; nodemask_t active_nodes; }; +void list_lru_destroy(struct list_lru *lru); int list_lru_init(struct list_lru *lru); /** diff --git a/mm/list_lru.c b/mm/list_lru.c index f91c24188573..72467914b856 100644 --- a/mm/list_lru.c +++ b/mm/list_lru.c @@ -8,6 +8,7 @@ #include #include #include +#include bool list_lru_add(struct list_lru *lru, struct list_head *item) { @@ -115,9 +116,14 @@ EXPORT_SYMBOL_GPL(list_lru_walk_node); int list_lru_init(struct list_lru *lru) { int i; + size_t size = sizeof(*lru->node) * nr_node_ids; + + lru->node = kzalloc(size, GFP_KERNEL); + if (!lru->node) + return -ENOMEM; nodes_clear(lru->active_nodes); - for (i = 0; i < MAX_NUMNODES; i++) { + for (i = 0; i < nr_node_ids; i++) { spin_lock_init(&lru->node[i].lock); INIT_LIST_HEAD(&lru->node[i].list); lru->node[i].nr_items = 0; @@ -125,3 +131,9 @@ int list_lru_init(struct list_lru *lru) return 0; } EXPORT_SYMBOL_GPL(list_lru_init); + +void list_lru_destroy(struct list_lru *lru) +{ + kfree(lru->node); +} +EXPORT_SYMBOL_GPL(list_lru_destroy);