diff options
-rw-r--r-- | mm/list_lru.c | 29 |
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); |
86 | restart: | 78 | restart: |
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); |