Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : /*
3 : : * Manage cache of swap slots to be used for and returned from
4 : : * swap.
5 : : *
6 : : * Copyright(c) 2016 Intel Corporation.
7 : : *
8 : : * Author: Tim Chen <tim.c.chen@linux.intel.com>
9 : : *
10 : : * We allocate the swap slots from the global pool and put
11 : : * it into local per cpu caches. This has the advantage
12 : : * of no needing to acquire the swap_info lock every time
13 : : * we need a new slot.
14 : : *
15 : : * There is also opportunity to simply return the slot
16 : : * to local caches without needing to acquire swap_info
17 : : * lock. We do not reuse the returned slots directly but
18 : : * move them back to the global pool in a batch. This
19 : : * allows the slots to coaellesce and reduce fragmentation.
20 : : *
21 : : * The swap entry allocated is marked with SWAP_HAS_CACHE
22 : : * flag in map_count that prevents it from being allocated
23 : : * again from the global pool.
24 : : *
25 : : * The swap slots cache is protected by a mutex instead of
26 : : * a spin lock as when we search for slots with scan_swap_map,
27 : : * we can possibly sleep.
28 : : */
29 : :
30 : : #include <linux/swap_slots.h>
31 : : #include <linux/cpu.h>
32 : : #include <linux/cpumask.h>
33 : : #include <linux/vmalloc.h>
34 : : #include <linux/mutex.h>
35 : : #include <linux/mm.h>
36 : :
37 : : static DEFINE_PER_CPU(struct swap_slots_cache, swp_slots);
38 : : static bool swap_slot_cache_active;
39 : : bool swap_slot_cache_enabled;
40 : : static bool swap_slot_cache_initialized;
41 : : static DEFINE_MUTEX(swap_slots_cache_mutex);
42 : : /* Serialize swap slots cache enable/disable operations */
43 : : static DEFINE_MUTEX(swap_slots_cache_enable_mutex);
44 : :
45 : : static void __drain_swap_slots_cache(unsigned int type);
46 : : static void deactivate_swap_slots_cache(void);
47 : : static void reactivate_swap_slots_cache(void);
48 : :
49 : : #define use_swap_slot_cache (swap_slot_cache_active && \
50 : : swap_slot_cache_enabled && swap_slot_cache_initialized)
51 : : #define SLOTS_CACHE 0x1
52 : : #define SLOTS_CACHE_RET 0x2
53 : :
54 : 0 : static void deactivate_swap_slots_cache(void)
55 : : {
56 : 0 : mutex_lock(&swap_slots_cache_mutex);
57 : 0 : swap_slot_cache_active = false;
58 : 0 : __drain_swap_slots_cache(SLOTS_CACHE|SLOTS_CACHE_RET);
59 : 0 : mutex_unlock(&swap_slots_cache_mutex);
60 : 0 : }
61 : :
62 : 0 : static void reactivate_swap_slots_cache(void)
63 : : {
64 : 0 : mutex_lock(&swap_slots_cache_mutex);
65 : 0 : swap_slot_cache_active = true;
66 : 0 : mutex_unlock(&swap_slots_cache_mutex);
67 : 0 : }
68 : :
69 : : /* Must not be called with cpu hot plug lock */
70 : 0 : void disable_swap_slots_cache_lock(void)
71 : : {
72 : 0 : mutex_lock(&swap_slots_cache_enable_mutex);
73 : 0 : swap_slot_cache_enabled = false;
74 [ # # ]: 0 : if (swap_slot_cache_initialized) {
75 : : /* serialize with cpu hotplug operations */
76 : : get_online_cpus();
77 : 0 : __drain_swap_slots_cache(SLOTS_CACHE|SLOTS_CACHE_RET);
78 : : put_online_cpus();
79 : : }
80 : 0 : }
81 : :
82 : : static void __reenable_swap_slots_cache(void)
83 : : {
84 : 404 : swap_slot_cache_enabled = has_usable_swap();
85 : : }
86 : :
87 : 0 : void reenable_swap_slots_cache_unlock(void)
88 : : {
89 : : __reenable_swap_slots_cache();
90 : 0 : mutex_unlock(&swap_slots_cache_enable_mutex);
91 : 0 : }
92 : :
93 : 0 : static bool check_cache_active(void)
94 : : {
95 : : long pages;
96 : :
97 [ # # # # ]: 0 : if (!swap_slot_cache_enabled || !swap_slot_cache_initialized)
98 : : return false;
99 : :
100 : : pages = get_nr_swap_pages();
101 [ # # ]: 0 : if (!swap_slot_cache_active) {
102 [ # # ]: 0 : if (pages > num_online_cpus() *
103 : : THRESHOLD_ACTIVATE_SWAP_SLOTS_CACHE)
104 : 0 : reactivate_swap_slots_cache();
105 : : goto out;
106 : : }
107 : :
108 : : /* if global pool of slot caches too low, deactivate cache */
109 [ # # ]: 0 : if (pages < num_online_cpus() * THRESHOLD_DEACTIVATE_SWAP_SLOTS_CACHE)
110 : 0 : deactivate_swap_slots_cache();
111 : : out:
112 : 0 : return swap_slot_cache_active;
113 : : }
114 : :
115 : 1616 : static int alloc_swap_slot_cache(unsigned int cpu)
116 : : {
117 : : struct swap_slots_cache *cache;
118 : : swp_entry_t *slots, *slots_ret;
119 : :
120 : : /*
121 : : * Do allocation outside swap_slots_cache_mutex
122 : : * as kvzalloc could trigger reclaim and get_swap_page,
123 : : * which can lock swap_slots_cache_mutex.
124 : : */
125 : : slots = kvcalloc(SWAP_SLOTS_CACHE_SIZE, sizeof(swp_entry_t),
126 : : GFP_KERNEL);
127 [ + - ]: 1616 : if (!slots)
128 : : return -ENOMEM;
129 : :
130 : : slots_ret = kvcalloc(SWAP_SLOTS_CACHE_SIZE, sizeof(swp_entry_t),
131 : : GFP_KERNEL);
132 [ - + ]: 1616 : if (!slots_ret) {
133 : 0 : kvfree(slots);
134 : 0 : return -ENOMEM;
135 : : }
136 : :
137 : 1616 : mutex_lock(&swap_slots_cache_mutex);
138 : 1616 : cache = &per_cpu(swp_slots, cpu);
139 [ + - + - ]: 1616 : if (cache->slots || cache->slots_ret)
140 : : /* cache already allocated */
141 : : goto out;
142 [ + - ]: 1616 : if (!cache->lock_initialized) {
143 : 1616 : mutex_init(&cache->alloc_lock);
144 : 1616 : spin_lock_init(&cache->free_lock);
145 : 1616 : cache->lock_initialized = true;
146 : : }
147 : 1616 : cache->nr = 0;
148 : 1616 : cache->cur = 0;
149 : 1616 : cache->n_ret = 0;
150 : : /*
151 : : * We initialized alloc_lock and free_lock earlier. We use
152 : : * !cache->slots or !cache->slots_ret to know if it is safe to acquire
153 : : * the corresponding lock and use the cache. Memory barrier below
154 : : * ensures the assumption.
155 : : */
156 : 1616 : mb();
157 : 1616 : cache->slots = slots;
158 : : slots = NULL;
159 : 1616 : cache->slots_ret = slots_ret;
160 : : slots_ret = NULL;
161 : : out:
162 : 1616 : mutex_unlock(&swap_slots_cache_mutex);
163 [ - + ]: 1616 : if (slots)
164 : 0 : kvfree(slots);
165 [ - + ]: 1616 : if (slots_ret)
166 : 0 : kvfree(slots_ret);
167 : : return 0;
168 : : }
169 : :
170 : 0 : static void drain_slots_cache_cpu(unsigned int cpu, unsigned int type,
171 : : bool free_slots)
172 : : {
173 : : struct swap_slots_cache *cache;
174 : : swp_entry_t *slots = NULL;
175 : :
176 : 0 : cache = &per_cpu(swp_slots, cpu);
177 [ # # # # ]: 0 : if ((type & SLOTS_CACHE) && cache->slots) {
178 : 0 : mutex_lock(&cache->alloc_lock);
179 : 0 : swapcache_free_entries(cache->slots + cache->cur, cache->nr);
180 : 0 : cache->cur = 0;
181 : 0 : cache->nr = 0;
182 [ # # # # ]: 0 : if (free_slots && cache->slots) {
183 : 0 : kvfree(cache->slots);
184 : 0 : cache->slots = NULL;
185 : : }
186 : 0 : mutex_unlock(&cache->alloc_lock);
187 : : }
188 [ # # # # ]: 0 : if ((type & SLOTS_CACHE_RET) && cache->slots_ret) {
189 : : spin_lock_irq(&cache->free_lock);
190 : 0 : swapcache_free_entries(cache->slots_ret, cache->n_ret);
191 : 0 : cache->n_ret = 0;
192 [ # # # # ]: 0 : if (free_slots && cache->slots_ret) {
193 : : slots = cache->slots_ret;
194 : 0 : cache->slots_ret = NULL;
195 : : }
196 : : spin_unlock_irq(&cache->free_lock);
197 [ # # ]: 0 : if (slots)
198 : 0 : kvfree(slots);
199 : : }
200 : 0 : }
201 : :
202 : 0 : static void __drain_swap_slots_cache(unsigned int type)
203 : : {
204 : : unsigned int cpu;
205 : :
206 : : /*
207 : : * This function is called during
208 : : * 1) swapoff, when we have to make sure no
209 : : * left over slots are in cache when we remove
210 : : * a swap device;
211 : : * 2) disabling of swap slot cache, when we run low
212 : : * on swap slots when allocating memory and need
213 : : * to return swap slots to global pool.
214 : : *
215 : : * We cannot acquire cpu hot plug lock here as
216 : : * this function can be invoked in the cpu
217 : : * hot plug path:
218 : : * cpu_up -> lock cpu_hotplug -> cpu hotplug state callback
219 : : * -> memory allocation -> direct reclaim -> get_swap_page
220 : : * -> drain_swap_slots_cache
221 : : *
222 : : * Hence the loop over current online cpu below could miss cpu that
223 : : * is being brought online but not yet marked as online.
224 : : * That is okay as we do not schedule and run anything on a
225 : : * cpu before it has been marked online. Hence, we will not
226 : : * fill any swap slots in slots cache of such cpu.
227 : : * There are no slots on such cpu that need to be drained.
228 : : */
229 [ # # ]: 0 : for_each_online_cpu(cpu)
230 : 0 : drain_slots_cache_cpu(cpu, type, false);
231 : 0 : }
232 : :
233 : 0 : static int free_slot_cache(unsigned int cpu)
234 : : {
235 : 0 : mutex_lock(&swap_slots_cache_mutex);
236 : 0 : drain_slots_cache_cpu(cpu, SLOTS_CACHE | SLOTS_CACHE_RET, true);
237 : 0 : mutex_unlock(&swap_slots_cache_mutex);
238 : 0 : return 0;
239 : : }
240 : :
241 : 404 : int enable_swap_slots_cache(void)
242 : : {
243 : : int ret = 0;
244 : :
245 : 404 : mutex_lock(&swap_slots_cache_enable_mutex);
246 [ - + ]: 404 : if (swap_slot_cache_initialized) {
247 : : __reenable_swap_slots_cache();
248 : : goto out_unlock;
249 : : }
250 : :
251 : : ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "swap_slots_cache",
252 : : alloc_swap_slot_cache, free_slot_cache);
253 [ - + # # : 404 : if (WARN_ONCE(ret < 0, "Cache allocation failed (%s), operating "
+ - ]
254 : : "without swap slots cache.\n", __func__))
255 : : goto out_unlock;
256 : :
257 : 404 : swap_slot_cache_initialized = true;
258 : : __reenable_swap_slots_cache();
259 : : out_unlock:
260 : 404 : mutex_unlock(&swap_slots_cache_enable_mutex);
261 : 404 : return 0;
262 : : }
263 : :
264 : : /* called with swap slot cache's alloc lock held */
265 : 0 : static int refill_swap_slots_cache(struct swap_slots_cache *cache)
266 : : {
267 [ # # # # : 0 : if (!use_swap_slot_cache || cache->nr)
# # # # ]
268 : : return 0;
269 : :
270 : 0 : cache->cur = 0;
271 [ # # ]: 0 : if (swap_slot_cache_active)
272 : 0 : cache->nr = get_swap_pages(SWAP_SLOTS_CACHE_SIZE,
273 : : cache->slots, 1);
274 : :
275 : 0 : return cache->nr;
276 : : }
277 : :
278 : 0 : int free_swap_slot(swp_entry_t entry)
279 : : {
280 : : struct swap_slots_cache *cache;
281 : :
282 : 0 : cache = raw_cpu_ptr(&swp_slots);
283 [ # # # # : 0 : if (likely(use_swap_slot_cache && cache->slots_ret)) {
# # # # #
# # # ]
284 : : spin_lock_irq(&cache->free_lock);
285 : : /* Swap slots cache may be deactivated before acquiring lock */
286 [ # # # # : 0 : if (!use_swap_slot_cache || !cache->slots_ret) {
# # # # ]
287 : : spin_unlock_irq(&cache->free_lock);
288 : : goto direct_free;
289 : : }
290 [ # # ]: 0 : if (cache->n_ret >= SWAP_SLOTS_CACHE_SIZE) {
291 : : /*
292 : : * Return slots to global pool.
293 : : * The current swap_map value is SWAP_HAS_CACHE.
294 : : * Set it to 0 to indicate it is available for
295 : : * allocation in global pool
296 : : */
297 : 0 : swapcache_free_entries(cache->slots_ret, cache->n_ret);
298 : 0 : cache->n_ret = 0;
299 : : }
300 : 0 : cache->slots_ret[cache->n_ret++] = entry;
301 : : spin_unlock_irq(&cache->free_lock);
302 : : } else {
303 : : direct_free:
304 : 0 : swapcache_free_entries(&entry, 1);
305 : : }
306 : :
307 : 0 : return 0;
308 : : }
309 : :
310 : 0 : swp_entry_t get_swap_page(struct page *page)
311 : : {
312 : : swp_entry_t entry, *pentry;
313 : : struct swap_slots_cache *cache;
314 : :
315 : 0 : entry.val = 0;
316 : :
317 : : if (PageTransHuge(page)) {
318 : : if (IS_ENABLED(CONFIG_THP_SWAP))
319 : : get_swap_pages(1, &entry, HPAGE_PMD_NR);
320 : : goto out;
321 : : }
322 : :
323 : : /*
324 : : * Preemption is allowed here, because we may sleep
325 : : * in refill_swap_slots_cache(). But it is safe, because
326 : : * accesses to the per-CPU data structure are protected by the
327 : : * mutex cache->alloc_lock.
328 : : *
329 : : * The alloc path here does not touch cache->slots_ret
330 : : * so cache->free_lock is not taken.
331 : : */
332 : 0 : cache = raw_cpu_ptr(&swp_slots);
333 : :
334 [ # # # # ]: 0 : if (likely(check_cache_active() && cache->slots)) {
335 : 0 : mutex_lock(&cache->alloc_lock);
336 [ # # ]: 0 : if (cache->slots) {
337 : : repeat:
338 [ # # ]: 0 : if (cache->nr) {
339 : 0 : pentry = &cache->slots[cache->cur++];
340 : 0 : entry = *pentry;
341 : 0 : pentry->val = 0;
342 : 0 : cache->nr--;
343 : : } else {
344 [ # # ]: 0 : if (refill_swap_slots_cache(cache))
345 : : goto repeat;
346 : : }
347 : : }
348 : 0 : mutex_unlock(&cache->alloc_lock);
349 [ # # ]: 0 : if (entry.val)
350 : : goto out;
351 : : }
352 : :
353 : 0 : get_swap_pages(1, &entry, 1);
354 : : out:
355 : : if (mem_cgroup_try_charge_swap(page, entry)) {
356 : : put_swap_page(page, entry);
357 : : entry.val = 0;
358 : : }
359 : 0 : return entry;
360 : : }
|