aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mm/list_lru.c29
1 files changed, 12 insertions, 17 deletions
diff --git a/mm/list_lru.c b/mm/list_lru.c
index 1efe4ecc02b1..e77c29f4c243 100644
--- a/mm/list_lru.c
+++ b/mm/list_lru.c
@@ -73,19 +73,19 @@ list_lru_walk_node(struct list_lru *lru, int nid, list_lru_walk_cb isolate,
73 struct list_lru_node *nlru = &lru->node[nid]; 73 struct list_lru_node *nlru = &lru->node[nid];
74 struct list_head *item, *n; 74 struct list_head *item, *n;
75 unsigned long isolated = 0; 75 unsigned long isolated = 0;
76 /*
77 * If we don't keep state of at which pass we are, we can loop at
78 * LRU_RETRY, since we have no guarantees that the caller will be able
79 * to do something other than retry on the next pass. We handle this by
80 * allowing at most one retry per object. This should not be altered
81 * by any condition other than LRU_RETRY.
82 */
83 bool first_pass = true;
84 76
85 spin_lock(&nlru->lock); 77 spin_lock(&nlru->lock);
86restart: 78restart:
87 list_for_each_safe(item, n, &nlru->list) { 79 list_for_each_safe(item, n, &nlru->list) {
88 enum lru_status ret; 80 enum lru_status ret;
81
82 /*
83 * decrement nr_to_walk first so that we don't livelock if we
84 * get stuck on large numbesr of LRU_RETRY items
85 */
86 if (--(*nr_to_walk) == 0)
87 break;
88
89 ret = isolate(item, &nlru->lock, cb_arg); 89 ret = isolate(item, &nlru->lock, cb_arg);
90 switch (ret) { 90 switch (ret) {
91 case LRU_REMOVED: 91 case LRU_REMOVED:
@@ -100,19 +100,14 @@ restart:
100 case LRU_SKIP: 100 case LRU_SKIP:
101 break; 101 break;
102 case LRU_RETRY: 102 case LRU_RETRY:
103 if (!first_pass) { 103 /*
104 first_pass = true; 104 * The lru lock has been dropped, our list traversal is
105 break; 105 * now invalid and so we have to restart from scratch.
106 } 106 */
107 first_pass = false;
108 goto restart; 107 goto restart;
109 default: 108 default:
110 BUG(); 109 BUG();
111 } 110 }
112
113 if ((*nr_to_walk)-- == 0)
114 break;
115
116 } 111 }
117 112
118 spin_unlock(&nlru->lock); 113 spin_unlock(&nlru->lock);