This source file includes following definitions.
- size_to_chunks
- alloc_slots
- slots_to_pool
- handle_to_slots
- free_handle
- z3fold_init_fs_context
- z3fold_mount
- z3fold_unmount
- z3fold_register_migration
- z3fold_unregister_migration
- init_z3fold_page
- free_z3fold_page
- z3fold_page_lock
- z3fold_page_trylock
- z3fold_page_unlock
- __idx
- __encode_handle
- encode_handle
- handle_to_z3fold_header
- handle_to_chunks
- handle_to_buddy
- zhdr_to_pool
- __release_z3fold_page
- release_z3fold_page
- release_z3fold_page_locked
- release_z3fold_page_locked_list
- free_pages_work
- num_free_chunks
- add_to_unbuddied
- mchunk_memmove
- z3fold_compact_page
- do_compact_page
- compact_page_work
- __z3fold_alloc
- z3fold_create_pool
- z3fold_destroy_pool
- z3fold_alloc
- z3fold_free
- z3fold_reclaim_page
- z3fold_map
- z3fold_unmap
- z3fold_get_pool_size
- z3fold_page_isolate
- z3fold_page_migrate
- z3fold_page_putback
- z3fold_zpool_evict
- z3fold_zpool_create
- z3fold_zpool_destroy
- z3fold_zpool_malloc
- z3fold_zpool_free
- z3fold_zpool_shrink
- z3fold_zpool_map
- z3fold_zpool_unmap
- z3fold_zpool_total_size
- init_z3fold
- exit_z3fold
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
25
26 #include <linux/atomic.h>
27 #include <linux/sched.h>
28 #include <linux/cpumask.h>
29 #include <linux/list.h>
30 #include <linux/mm.h>
31 #include <linux/module.h>
32 #include <linux/page-flags.h>
33 #include <linux/migrate.h>
34 #include <linux/node.h>
35 #include <linux/compaction.h>
36 #include <linux/percpu.h>
37 #include <linux/mount.h>
38 #include <linux/pseudo_fs.h>
39 #include <linux/fs.h>
40 #include <linux/preempt.h>
41 #include <linux/workqueue.h>
42 #include <linux/slab.h>
43 #include <linux/spinlock.h>
44 #include <linux/zpool.h>
45 #include <linux/magic.h>
46
47
48
49
50
51
52
53
54
55
56
57 #define NCHUNKS_ORDER 6
58
59 #define CHUNK_SHIFT (PAGE_SHIFT - NCHUNKS_ORDER)
60 #define CHUNK_SIZE (1 << CHUNK_SHIFT)
61 #define ZHDR_SIZE_ALIGNED round_up(sizeof(struct z3fold_header), CHUNK_SIZE)
62 #define ZHDR_CHUNKS (ZHDR_SIZE_ALIGNED >> CHUNK_SHIFT)
63 #define TOTAL_CHUNKS (PAGE_SIZE >> CHUNK_SHIFT)
64 #define NCHUNKS ((PAGE_SIZE - ZHDR_SIZE_ALIGNED) >> CHUNK_SHIFT)
65
66 #define BUDDY_MASK (0x3)
67 #define BUDDY_SHIFT 2
68 #define SLOTS_ALIGN (0x40)
69
70
71
72
73 struct z3fold_pool;
74 struct z3fold_ops {
75 int (*evict)(struct z3fold_pool *pool, unsigned long handle);
76 };
77
78 enum buddy {
79 HEADLESS = 0,
80 FIRST,
81 MIDDLE,
82 LAST,
83 BUDDIES_MAX = LAST
84 };
85
86 struct z3fold_buddy_slots {
87
88
89
90
91 unsigned long slot[BUDDY_MASK + 1];
92 unsigned long pool;
93 };
94 #define HANDLE_FLAG_MASK (0x03)
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113 struct z3fold_header {
114 struct list_head buddy;
115 spinlock_t page_lock;
116 struct kref refcount;
117 struct work_struct work;
118 struct z3fold_buddy_slots *slots;
119 struct z3fold_pool *pool;
120 short cpu;
121 unsigned short first_chunks;
122 unsigned short middle_chunks;
123 unsigned short last_chunks;
124 unsigned short start_middle;
125 unsigned short first_num:2;
126 unsigned short mapped_count:2;
127 };
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152 struct z3fold_pool {
153 const char *name;
154 spinlock_t lock;
155 spinlock_t stale_lock;
156 struct list_head *unbuddied;
157 struct list_head lru;
158 struct list_head stale;
159 atomic64_t pages_nr;
160 struct kmem_cache *c_handle;
161 const struct z3fold_ops *ops;
162 struct zpool *zpool;
163 const struct zpool_ops *zpool_ops;
164 struct workqueue_struct *compact_wq;
165 struct workqueue_struct *release_wq;
166 struct work_struct work;
167 struct inode *inode;
168 };
169
170
171
172
173 enum z3fold_page_flags {
174 PAGE_HEADLESS = 0,
175 MIDDLE_CHUNK_MAPPED,
176 NEEDS_COMPACTING,
177 PAGE_STALE,
178 PAGE_CLAIMED,
179 };
180
181
182
183
184
185
186 static int size_to_chunks(size_t size)
187 {
188 return (size + CHUNK_SIZE - 1) >> CHUNK_SHIFT;
189 }
190
191 #define for_each_unbuddied_list(_iter, _begin) \
192 for ((_iter) = (_begin); (_iter) < NCHUNKS; (_iter)++)
193
194 static void compact_page_work(struct work_struct *w);
195
196 static inline struct z3fold_buddy_slots *alloc_slots(struct z3fold_pool *pool,
197 gfp_t gfp)
198 {
199 struct z3fold_buddy_slots *slots;
200
201 slots = kmem_cache_alloc(pool->c_handle,
202 (gfp & ~(__GFP_HIGHMEM | __GFP_MOVABLE)));
203
204 if (slots) {
205 memset(slots->slot, 0, sizeof(slots->slot));
206 slots->pool = (unsigned long)pool;
207 }
208
209 return slots;
210 }
211
212 static inline struct z3fold_pool *slots_to_pool(struct z3fold_buddy_slots *s)
213 {
214 return (struct z3fold_pool *)(s->pool & ~HANDLE_FLAG_MASK);
215 }
216
217 static inline struct z3fold_buddy_slots *handle_to_slots(unsigned long handle)
218 {
219 return (struct z3fold_buddy_slots *)(handle & ~(SLOTS_ALIGN - 1));
220 }
221
222 static inline void free_handle(unsigned long handle)
223 {
224 struct z3fold_buddy_slots *slots;
225 int i;
226 bool is_free;
227
228 if (handle & (1 << PAGE_HEADLESS))
229 return;
230
231 WARN_ON(*(unsigned long *)handle == 0);
232 *(unsigned long *)handle = 0;
233 slots = handle_to_slots(handle);
234 is_free = true;
235 for (i = 0; i <= BUDDY_MASK; i++) {
236 if (slots->slot[i]) {
237 is_free = false;
238 break;
239 }
240 }
241
242 if (is_free) {
243 struct z3fold_pool *pool = slots_to_pool(slots);
244
245 kmem_cache_free(pool->c_handle, slots);
246 }
247 }
248
249 static int z3fold_init_fs_context(struct fs_context *fc)
250 {
251 return init_pseudo(fc, Z3FOLD_MAGIC) ? 0 : -ENOMEM;
252 }
253
254 static struct file_system_type z3fold_fs = {
255 .name = "z3fold",
256 .init_fs_context = z3fold_init_fs_context,
257 .kill_sb = kill_anon_super,
258 };
259
260 static struct vfsmount *z3fold_mnt;
261 static int z3fold_mount(void)
262 {
263 int ret = 0;
264
265 z3fold_mnt = kern_mount(&z3fold_fs);
266 if (IS_ERR(z3fold_mnt))
267 ret = PTR_ERR(z3fold_mnt);
268
269 return ret;
270 }
271
272 static void z3fold_unmount(void)
273 {
274 kern_unmount(z3fold_mnt);
275 }
276
277 static const struct address_space_operations z3fold_aops;
278 static int z3fold_register_migration(struct z3fold_pool *pool)
279 {
280 pool->inode = alloc_anon_inode(z3fold_mnt->mnt_sb);
281 if (IS_ERR(pool->inode)) {
282 pool->inode = NULL;
283 return 1;
284 }
285
286 pool->inode->i_mapping->private_data = pool;
287 pool->inode->i_mapping->a_ops = &z3fold_aops;
288 return 0;
289 }
290
291 static void z3fold_unregister_migration(struct z3fold_pool *pool)
292 {
293 if (pool->inode)
294 iput(pool->inode);
295 }
296
297
298 static struct z3fold_header *init_z3fold_page(struct page *page, bool headless,
299 struct z3fold_pool *pool, gfp_t gfp)
300 {
301 struct z3fold_header *zhdr = page_address(page);
302 struct z3fold_buddy_slots *slots;
303
304 INIT_LIST_HEAD(&page->lru);
305 clear_bit(PAGE_HEADLESS, &page->private);
306 clear_bit(MIDDLE_CHUNK_MAPPED, &page->private);
307 clear_bit(NEEDS_COMPACTING, &page->private);
308 clear_bit(PAGE_STALE, &page->private);
309 clear_bit(PAGE_CLAIMED, &page->private);
310 if (headless)
311 return zhdr;
312
313 slots = alloc_slots(pool, gfp);
314 if (!slots)
315 return NULL;
316
317 spin_lock_init(&zhdr->page_lock);
318 kref_init(&zhdr->refcount);
319 zhdr->first_chunks = 0;
320 zhdr->middle_chunks = 0;
321 zhdr->last_chunks = 0;
322 zhdr->first_num = 0;
323 zhdr->start_middle = 0;
324 zhdr->cpu = -1;
325 zhdr->slots = slots;
326 zhdr->pool = pool;
327 INIT_LIST_HEAD(&zhdr->buddy);
328 INIT_WORK(&zhdr->work, compact_page_work);
329 return zhdr;
330 }
331
332
333 static void free_z3fold_page(struct page *page, bool headless)
334 {
335 if (!headless) {
336 lock_page(page);
337 __ClearPageMovable(page);
338 unlock_page(page);
339 }
340 ClearPagePrivate(page);
341 __free_page(page);
342 }
343
344
345 static inline void z3fold_page_lock(struct z3fold_header *zhdr)
346 {
347 spin_lock(&zhdr->page_lock);
348 }
349
350
351 static inline int z3fold_page_trylock(struct z3fold_header *zhdr)
352 {
353 return spin_trylock(&zhdr->page_lock);
354 }
355
356
357 static inline void z3fold_page_unlock(struct z3fold_header *zhdr)
358 {
359 spin_unlock(&zhdr->page_lock);
360 }
361
362
363 static inline int __idx(struct z3fold_header *zhdr, enum buddy bud)
364 {
365 return (bud + zhdr->first_num) & BUDDY_MASK;
366 }
367
368
369
370
371
372 static unsigned long __encode_handle(struct z3fold_header *zhdr,
373 struct z3fold_buddy_slots *slots,
374 enum buddy bud)
375 {
376 unsigned long h = (unsigned long)zhdr;
377 int idx = 0;
378
379
380
381
382
383 if (bud == HEADLESS)
384 return h | (1 << PAGE_HEADLESS);
385
386
387 idx = __idx(zhdr, bud);
388 h += idx;
389 if (bud == LAST)
390 h |= (zhdr->last_chunks << BUDDY_SHIFT);
391
392 slots->slot[idx] = h;
393 return (unsigned long)&slots->slot[idx];
394 }
395
396 static unsigned long encode_handle(struct z3fold_header *zhdr, enum buddy bud)
397 {
398 return __encode_handle(zhdr, zhdr->slots, bud);
399 }
400
401
402 static inline struct z3fold_header *handle_to_z3fold_header(unsigned long h)
403 {
404 unsigned long addr = h;
405
406 if (!(addr & (1 << PAGE_HEADLESS)))
407 addr = *(unsigned long *)h;
408
409 return (struct z3fold_header *)(addr & PAGE_MASK);
410 }
411
412
413 static unsigned short handle_to_chunks(unsigned long handle)
414 {
415 unsigned long addr = *(unsigned long *)handle;
416
417 return (addr & ~PAGE_MASK) >> BUDDY_SHIFT;
418 }
419
420
421
422
423
424
425 static enum buddy handle_to_buddy(unsigned long handle)
426 {
427 struct z3fold_header *zhdr;
428 unsigned long addr;
429
430 WARN_ON(handle & (1 << PAGE_HEADLESS));
431 addr = *(unsigned long *)handle;
432 zhdr = (struct z3fold_header *)(addr & PAGE_MASK);
433 return (addr - zhdr->first_num) & BUDDY_MASK;
434 }
435
436 static inline struct z3fold_pool *zhdr_to_pool(struct z3fold_header *zhdr)
437 {
438 return zhdr->pool;
439 }
440
441 static void __release_z3fold_page(struct z3fold_header *zhdr, bool locked)
442 {
443 struct page *page = virt_to_page(zhdr);
444 struct z3fold_pool *pool = zhdr_to_pool(zhdr);
445
446 WARN_ON(!list_empty(&zhdr->buddy));
447 set_bit(PAGE_STALE, &page->private);
448 clear_bit(NEEDS_COMPACTING, &page->private);
449 spin_lock(&pool->lock);
450 if (!list_empty(&page->lru))
451 list_del_init(&page->lru);
452 spin_unlock(&pool->lock);
453 if (locked)
454 z3fold_page_unlock(zhdr);
455 spin_lock(&pool->stale_lock);
456 list_add(&zhdr->buddy, &pool->stale);
457 queue_work(pool->release_wq, &pool->work);
458 spin_unlock(&pool->stale_lock);
459 }
460
461 static void __attribute__((__unused__))
462 release_z3fold_page(struct kref *ref)
463 {
464 struct z3fold_header *zhdr = container_of(ref, struct z3fold_header,
465 refcount);
466 __release_z3fold_page(zhdr, false);
467 }
468
469 static void release_z3fold_page_locked(struct kref *ref)
470 {
471 struct z3fold_header *zhdr = container_of(ref, struct z3fold_header,
472 refcount);
473 WARN_ON(z3fold_page_trylock(zhdr));
474 __release_z3fold_page(zhdr, true);
475 }
476
477 static void release_z3fold_page_locked_list(struct kref *ref)
478 {
479 struct z3fold_header *zhdr = container_of(ref, struct z3fold_header,
480 refcount);
481 struct z3fold_pool *pool = zhdr_to_pool(zhdr);
482 spin_lock(&pool->lock);
483 list_del_init(&zhdr->buddy);
484 spin_unlock(&pool->lock);
485
486 WARN_ON(z3fold_page_trylock(zhdr));
487 __release_z3fold_page(zhdr, true);
488 }
489
490 static void free_pages_work(struct work_struct *w)
491 {
492 struct z3fold_pool *pool = container_of(w, struct z3fold_pool, work);
493
494 spin_lock(&pool->stale_lock);
495 while (!list_empty(&pool->stale)) {
496 struct z3fold_header *zhdr = list_first_entry(&pool->stale,
497 struct z3fold_header, buddy);
498 struct page *page = virt_to_page(zhdr);
499
500 list_del(&zhdr->buddy);
501 if (WARN_ON(!test_bit(PAGE_STALE, &page->private)))
502 continue;
503 spin_unlock(&pool->stale_lock);
504 cancel_work_sync(&zhdr->work);
505 free_z3fold_page(page, false);
506 cond_resched();
507 spin_lock(&pool->stale_lock);
508 }
509 spin_unlock(&pool->stale_lock);
510 }
511
512
513
514
515
516 static int num_free_chunks(struct z3fold_header *zhdr)
517 {
518 int nfree;
519
520
521
522
523
524 if (zhdr->middle_chunks != 0) {
525 int nfree_before = zhdr->first_chunks ?
526 0 : zhdr->start_middle - ZHDR_CHUNKS;
527 int nfree_after = zhdr->last_chunks ?
528 0 : TOTAL_CHUNKS -
529 (zhdr->start_middle + zhdr->middle_chunks);
530 nfree = max(nfree_before, nfree_after);
531 } else
532 nfree = NCHUNKS - zhdr->first_chunks - zhdr->last_chunks;
533 return nfree;
534 }
535
536
537 static inline void add_to_unbuddied(struct z3fold_pool *pool,
538 struct z3fold_header *zhdr)
539 {
540 if (zhdr->first_chunks == 0 || zhdr->last_chunks == 0 ||
541 zhdr->middle_chunks == 0) {
542 struct list_head *unbuddied = get_cpu_ptr(pool->unbuddied);
543
544 int freechunks = num_free_chunks(zhdr);
545 spin_lock(&pool->lock);
546 list_add(&zhdr->buddy, &unbuddied[freechunks]);
547 spin_unlock(&pool->lock);
548 zhdr->cpu = smp_processor_id();
549 put_cpu_ptr(pool->unbuddied);
550 }
551 }
552
553 static inline void *mchunk_memmove(struct z3fold_header *zhdr,
554 unsigned short dst_chunk)
555 {
556 void *beg = zhdr;
557 return memmove(beg + (dst_chunk << CHUNK_SHIFT),
558 beg + (zhdr->start_middle << CHUNK_SHIFT),
559 zhdr->middle_chunks << CHUNK_SHIFT);
560 }
561
562 #define BIG_CHUNK_GAP 3
563
564 static int z3fold_compact_page(struct z3fold_header *zhdr)
565 {
566 struct page *page = virt_to_page(zhdr);
567
568 if (test_bit(MIDDLE_CHUNK_MAPPED, &page->private))
569 return 0;
570
571 if (unlikely(PageIsolated(page)))
572 return 0;
573
574 if (zhdr->middle_chunks == 0)
575 return 0;
576
577 if (zhdr->first_chunks == 0 && zhdr->last_chunks == 0) {
578
579 mchunk_memmove(zhdr, ZHDR_CHUNKS);
580 zhdr->first_chunks = zhdr->middle_chunks;
581 zhdr->middle_chunks = 0;
582 zhdr->start_middle = 0;
583 zhdr->first_num++;
584 return 1;
585 }
586
587
588
589
590
591 if (zhdr->first_chunks != 0 && zhdr->last_chunks == 0 &&
592 zhdr->start_middle - (zhdr->first_chunks + ZHDR_CHUNKS) >=
593 BIG_CHUNK_GAP) {
594 mchunk_memmove(zhdr, zhdr->first_chunks + ZHDR_CHUNKS);
595 zhdr->start_middle = zhdr->first_chunks + ZHDR_CHUNKS;
596 return 1;
597 } else if (zhdr->last_chunks != 0 && zhdr->first_chunks == 0 &&
598 TOTAL_CHUNKS - (zhdr->last_chunks + zhdr->start_middle
599 + zhdr->middle_chunks) >=
600 BIG_CHUNK_GAP) {
601 unsigned short new_start = TOTAL_CHUNKS - zhdr->last_chunks -
602 zhdr->middle_chunks;
603 mchunk_memmove(zhdr, new_start);
604 zhdr->start_middle = new_start;
605 return 1;
606 }
607
608 return 0;
609 }
610
611 static void do_compact_page(struct z3fold_header *zhdr, bool locked)
612 {
613 struct z3fold_pool *pool = zhdr_to_pool(zhdr);
614 struct page *page;
615
616 page = virt_to_page(zhdr);
617 if (locked)
618 WARN_ON(z3fold_page_trylock(zhdr));
619 else
620 z3fold_page_lock(zhdr);
621 if (WARN_ON(!test_and_clear_bit(NEEDS_COMPACTING, &page->private))) {
622 z3fold_page_unlock(zhdr);
623 return;
624 }
625 spin_lock(&pool->lock);
626 list_del_init(&zhdr->buddy);
627 spin_unlock(&pool->lock);
628
629 if (kref_put(&zhdr->refcount, release_z3fold_page_locked)) {
630 atomic64_dec(&pool->pages_nr);
631 return;
632 }
633
634 if (unlikely(PageIsolated(page) ||
635 test_bit(PAGE_CLAIMED, &page->private) ||
636 test_bit(PAGE_STALE, &page->private))) {
637 z3fold_page_unlock(zhdr);
638 return;
639 }
640
641 z3fold_compact_page(zhdr);
642 add_to_unbuddied(pool, zhdr);
643 z3fold_page_unlock(zhdr);
644 }
645
646 static void compact_page_work(struct work_struct *w)
647 {
648 struct z3fold_header *zhdr = container_of(w, struct z3fold_header,
649 work);
650
651 do_compact_page(zhdr, false);
652 }
653
654
655 static inline struct z3fold_header *__z3fold_alloc(struct z3fold_pool *pool,
656 size_t size, bool can_sleep)
657 {
658 struct z3fold_header *zhdr = NULL;
659 struct page *page;
660 struct list_head *unbuddied;
661 int chunks = size_to_chunks(size), i;
662
663 lookup:
664
665 unbuddied = get_cpu_ptr(pool->unbuddied);
666 for_each_unbuddied_list(i, chunks) {
667 struct list_head *l = &unbuddied[i];
668
669 zhdr = list_first_entry_or_null(READ_ONCE(l),
670 struct z3fold_header, buddy);
671
672 if (!zhdr)
673 continue;
674
675
676 spin_lock(&pool->lock);
677 l = &unbuddied[i];
678 if (unlikely(zhdr != list_first_entry(READ_ONCE(l),
679 struct z3fold_header, buddy)) ||
680 !z3fold_page_trylock(zhdr)) {
681 spin_unlock(&pool->lock);
682 zhdr = NULL;
683 put_cpu_ptr(pool->unbuddied);
684 if (can_sleep)
685 cond_resched();
686 goto lookup;
687 }
688 list_del_init(&zhdr->buddy);
689 zhdr->cpu = -1;
690 spin_unlock(&pool->lock);
691
692 page = virt_to_page(zhdr);
693 if (test_bit(NEEDS_COMPACTING, &page->private)) {
694 z3fold_page_unlock(zhdr);
695 zhdr = NULL;
696 put_cpu_ptr(pool->unbuddied);
697 if (can_sleep)
698 cond_resched();
699 goto lookup;
700 }
701
702
703
704
705
706
707
708 kref_get(&zhdr->refcount);
709 break;
710 }
711 put_cpu_ptr(pool->unbuddied);
712
713 if (!zhdr) {
714 int cpu;
715
716
717 for_each_online_cpu(cpu) {
718 struct list_head *l;
719
720 unbuddied = per_cpu_ptr(pool->unbuddied, cpu);
721 spin_lock(&pool->lock);
722 l = &unbuddied[chunks];
723
724 zhdr = list_first_entry_or_null(READ_ONCE(l),
725 struct z3fold_header, buddy);
726
727 if (!zhdr || !z3fold_page_trylock(zhdr)) {
728 spin_unlock(&pool->lock);
729 zhdr = NULL;
730 continue;
731 }
732 list_del_init(&zhdr->buddy);
733 zhdr->cpu = -1;
734 spin_unlock(&pool->lock);
735
736 page = virt_to_page(zhdr);
737 if (test_bit(NEEDS_COMPACTING, &page->private)) {
738 z3fold_page_unlock(zhdr);
739 zhdr = NULL;
740 if (can_sleep)
741 cond_resched();
742 continue;
743 }
744 kref_get(&zhdr->refcount);
745 break;
746 }
747 }
748
749 return zhdr;
750 }
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765 static struct z3fold_pool *z3fold_create_pool(const char *name, gfp_t gfp,
766 const struct z3fold_ops *ops)
767 {
768 struct z3fold_pool *pool = NULL;
769 int i, cpu;
770
771 pool = kzalloc(sizeof(struct z3fold_pool), gfp);
772 if (!pool)
773 goto out;
774 pool->c_handle = kmem_cache_create("z3fold_handle",
775 sizeof(struct z3fold_buddy_slots),
776 SLOTS_ALIGN, 0, NULL);
777 if (!pool->c_handle)
778 goto out_c;
779 spin_lock_init(&pool->lock);
780 spin_lock_init(&pool->stale_lock);
781 pool->unbuddied = __alloc_percpu(sizeof(struct list_head)*NCHUNKS, 2);
782 if (!pool->unbuddied)
783 goto out_pool;
784 for_each_possible_cpu(cpu) {
785 struct list_head *unbuddied =
786 per_cpu_ptr(pool->unbuddied, cpu);
787 for_each_unbuddied_list(i, 0)
788 INIT_LIST_HEAD(&unbuddied[i]);
789 }
790 INIT_LIST_HEAD(&pool->lru);
791 INIT_LIST_HEAD(&pool->stale);
792 atomic64_set(&pool->pages_nr, 0);
793 pool->name = name;
794 pool->compact_wq = create_singlethread_workqueue(pool->name);
795 if (!pool->compact_wq)
796 goto out_unbuddied;
797 pool->release_wq = create_singlethread_workqueue(pool->name);
798 if (!pool->release_wq)
799 goto out_wq;
800 if (z3fold_register_migration(pool))
801 goto out_rwq;
802 INIT_WORK(&pool->work, free_pages_work);
803 pool->ops = ops;
804 return pool;
805
806 out_rwq:
807 destroy_workqueue(pool->release_wq);
808 out_wq:
809 destroy_workqueue(pool->compact_wq);
810 out_unbuddied:
811 free_percpu(pool->unbuddied);
812 out_pool:
813 kmem_cache_destroy(pool->c_handle);
814 out_c:
815 kfree(pool);
816 out:
817 return NULL;
818 }
819
820
821
822
823
824
825
826 static void z3fold_destroy_pool(struct z3fold_pool *pool)
827 {
828 kmem_cache_destroy(pool->c_handle);
829
830
831
832
833
834
835
836
837
838
839 destroy_workqueue(pool->compact_wq);
840 destroy_workqueue(pool->release_wq);
841 z3fold_unregister_migration(pool);
842 kfree(pool);
843 }
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864 static int z3fold_alloc(struct z3fold_pool *pool, size_t size, gfp_t gfp,
865 unsigned long *handle)
866 {
867 int chunks = size_to_chunks(size);
868 struct z3fold_header *zhdr = NULL;
869 struct page *page = NULL;
870 enum buddy bud;
871 bool can_sleep = gfpflags_allow_blocking(gfp);
872
873 if (!size)
874 return -EINVAL;
875
876 if (size > PAGE_SIZE)
877 return -ENOSPC;
878
879 if (size > PAGE_SIZE - ZHDR_SIZE_ALIGNED - CHUNK_SIZE)
880 bud = HEADLESS;
881 else {
882 retry:
883 zhdr = __z3fold_alloc(pool, size, can_sleep);
884 if (zhdr) {
885 if (zhdr->first_chunks == 0) {
886 if (zhdr->middle_chunks != 0 &&
887 chunks >= zhdr->start_middle)
888 bud = LAST;
889 else
890 bud = FIRST;
891 } else if (zhdr->last_chunks == 0)
892 bud = LAST;
893 else if (zhdr->middle_chunks == 0)
894 bud = MIDDLE;
895 else {
896 if (kref_put(&zhdr->refcount,
897 release_z3fold_page_locked))
898 atomic64_dec(&pool->pages_nr);
899 else
900 z3fold_page_unlock(zhdr);
901 pr_err("No free chunks in unbuddied\n");
902 WARN_ON(1);
903 goto retry;
904 }
905 page = virt_to_page(zhdr);
906 goto found;
907 }
908 bud = FIRST;
909 }
910
911 page = NULL;
912 if (can_sleep) {
913 spin_lock(&pool->stale_lock);
914 zhdr = list_first_entry_or_null(&pool->stale,
915 struct z3fold_header, buddy);
916
917
918
919
920
921 if (zhdr) {
922 list_del(&zhdr->buddy);
923 spin_unlock(&pool->stale_lock);
924 cancel_work_sync(&zhdr->work);
925 page = virt_to_page(zhdr);
926 } else {
927 spin_unlock(&pool->stale_lock);
928 }
929 }
930 if (!page)
931 page = alloc_page(gfp);
932
933 if (!page)
934 return -ENOMEM;
935
936 zhdr = init_z3fold_page(page, bud == HEADLESS, pool, gfp);
937 if (!zhdr) {
938 __free_page(page);
939 return -ENOMEM;
940 }
941 atomic64_inc(&pool->pages_nr);
942
943 if (bud == HEADLESS) {
944 set_bit(PAGE_HEADLESS, &page->private);
945 goto headless;
946 }
947 if (can_sleep) {
948 lock_page(page);
949 __SetPageMovable(page, pool->inode->i_mapping);
950 unlock_page(page);
951 } else {
952 if (trylock_page(page)) {
953 __SetPageMovable(page, pool->inode->i_mapping);
954 unlock_page(page);
955 }
956 }
957 z3fold_page_lock(zhdr);
958
959 found:
960 if (bud == FIRST)
961 zhdr->first_chunks = chunks;
962 else if (bud == LAST)
963 zhdr->last_chunks = chunks;
964 else {
965 zhdr->middle_chunks = chunks;
966 zhdr->start_middle = zhdr->first_chunks + ZHDR_CHUNKS;
967 }
968 add_to_unbuddied(pool, zhdr);
969
970 headless:
971 spin_lock(&pool->lock);
972
973 if (!list_empty(&page->lru))
974 list_del(&page->lru);
975
976 list_add(&page->lru, &pool->lru);
977
978 *handle = encode_handle(zhdr, bud);
979 spin_unlock(&pool->lock);
980 if (bud != HEADLESS)
981 z3fold_page_unlock(zhdr);
982
983 return 0;
984 }
985
986
987
988
989
990
991
992
993
994
995
996 static void z3fold_free(struct z3fold_pool *pool, unsigned long handle)
997 {
998 struct z3fold_header *zhdr;
999 struct page *page;
1000 enum buddy bud;
1001 bool page_claimed;
1002
1003 zhdr = handle_to_z3fold_header(handle);
1004 page = virt_to_page(zhdr);
1005 page_claimed = test_and_set_bit(PAGE_CLAIMED, &page->private);
1006
1007 if (test_bit(PAGE_HEADLESS, &page->private)) {
1008
1009
1010
1011
1012
1013 if (!page_claimed) {
1014 spin_lock(&pool->lock);
1015 list_del(&page->lru);
1016 spin_unlock(&pool->lock);
1017 free_z3fold_page(page, true);
1018 atomic64_dec(&pool->pages_nr);
1019 }
1020 return;
1021 }
1022
1023
1024 z3fold_page_lock(zhdr);
1025 bud = handle_to_buddy(handle);
1026
1027 switch (bud) {
1028 case FIRST:
1029 zhdr->first_chunks = 0;
1030 break;
1031 case MIDDLE:
1032 zhdr->middle_chunks = 0;
1033 break;
1034 case LAST:
1035 zhdr->last_chunks = 0;
1036 break;
1037 default:
1038 pr_err("%s: unknown bud %d\n", __func__, bud);
1039 WARN_ON(1);
1040 z3fold_page_unlock(zhdr);
1041 return;
1042 }
1043
1044 free_handle(handle);
1045 if (kref_put(&zhdr->refcount, release_z3fold_page_locked_list)) {
1046 atomic64_dec(&pool->pages_nr);
1047 return;
1048 }
1049 if (page_claimed) {
1050
1051 z3fold_page_unlock(zhdr);
1052 return;
1053 }
1054 if (unlikely(PageIsolated(page)) ||
1055 test_and_set_bit(NEEDS_COMPACTING, &page->private)) {
1056 z3fold_page_unlock(zhdr);
1057 clear_bit(PAGE_CLAIMED, &page->private);
1058 return;
1059 }
1060 if (zhdr->cpu < 0 || !cpu_online(zhdr->cpu)) {
1061 spin_lock(&pool->lock);
1062 list_del_init(&zhdr->buddy);
1063 spin_unlock(&pool->lock);
1064 zhdr->cpu = -1;
1065 kref_get(&zhdr->refcount);
1066 do_compact_page(zhdr, true);
1067 clear_bit(PAGE_CLAIMED, &page->private);
1068 return;
1069 }
1070 kref_get(&zhdr->refcount);
1071 queue_work_on(zhdr->cpu, pool->compact_wq, &zhdr->work);
1072 clear_bit(PAGE_CLAIMED, &page->private);
1073 z3fold_page_unlock(zhdr);
1074 }
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112 static int z3fold_reclaim_page(struct z3fold_pool *pool, unsigned int retries)
1113 {
1114 int i, ret = 0;
1115 struct z3fold_header *zhdr = NULL;
1116 struct page *page = NULL;
1117 struct list_head *pos;
1118 struct z3fold_buddy_slots slots;
1119 unsigned long first_handle = 0, middle_handle = 0, last_handle = 0;
1120
1121 spin_lock(&pool->lock);
1122 if (!pool->ops || !pool->ops->evict || retries == 0) {
1123 spin_unlock(&pool->lock);
1124 return -EINVAL;
1125 }
1126 for (i = 0; i < retries; i++) {
1127 if (list_empty(&pool->lru)) {
1128 spin_unlock(&pool->lock);
1129 return -EINVAL;
1130 }
1131 list_for_each_prev(pos, &pool->lru) {
1132 page = list_entry(pos, struct page, lru);
1133
1134
1135
1136
1137 if (test_and_set_bit(PAGE_CLAIMED, &page->private)) {
1138 page = NULL;
1139 continue;
1140 }
1141
1142 if (unlikely(PageIsolated(page))) {
1143 clear_bit(PAGE_CLAIMED, &page->private);
1144 page = NULL;
1145 continue;
1146 }
1147 zhdr = page_address(page);
1148 if (test_bit(PAGE_HEADLESS, &page->private))
1149 break;
1150
1151 if (!z3fold_page_trylock(zhdr)) {
1152 clear_bit(PAGE_CLAIMED, &page->private);
1153 zhdr = NULL;
1154 continue;
1155 }
1156 kref_get(&zhdr->refcount);
1157 list_del_init(&zhdr->buddy);
1158 zhdr->cpu = -1;
1159 break;
1160 }
1161
1162 if (!zhdr)
1163 break;
1164
1165 list_del_init(&page->lru);
1166 spin_unlock(&pool->lock);
1167
1168 if (!test_bit(PAGE_HEADLESS, &page->private)) {
1169
1170
1171
1172
1173
1174
1175 first_handle = 0;
1176 last_handle = 0;
1177 middle_handle = 0;
1178 if (zhdr->first_chunks)
1179 first_handle = __encode_handle(zhdr, &slots,
1180 FIRST);
1181 if (zhdr->middle_chunks)
1182 middle_handle = __encode_handle(zhdr, &slots,
1183 MIDDLE);
1184 if (zhdr->last_chunks)
1185 last_handle = __encode_handle(zhdr, &slots,
1186 LAST);
1187
1188
1189
1190
1191 z3fold_page_unlock(zhdr);
1192 } else {
1193 first_handle = __encode_handle(zhdr, &slots, HEADLESS);
1194 last_handle = middle_handle = 0;
1195 }
1196
1197
1198 if (middle_handle) {
1199 ret = pool->ops->evict(pool, middle_handle);
1200 if (ret)
1201 goto next;
1202 }
1203 if (first_handle) {
1204 ret = pool->ops->evict(pool, first_handle);
1205 if (ret)
1206 goto next;
1207 }
1208 if (last_handle) {
1209 ret = pool->ops->evict(pool, last_handle);
1210 if (ret)
1211 goto next;
1212 }
1213 next:
1214 if (test_bit(PAGE_HEADLESS, &page->private)) {
1215 if (ret == 0) {
1216 free_z3fold_page(page, true);
1217 atomic64_dec(&pool->pages_nr);
1218 return 0;
1219 }
1220 spin_lock(&pool->lock);
1221 list_add(&page->lru, &pool->lru);
1222 spin_unlock(&pool->lock);
1223 clear_bit(PAGE_CLAIMED, &page->private);
1224 } else {
1225 z3fold_page_lock(zhdr);
1226 if (kref_put(&zhdr->refcount,
1227 release_z3fold_page_locked)) {
1228 atomic64_dec(&pool->pages_nr);
1229 return 0;
1230 }
1231
1232
1233
1234
1235
1236 spin_lock(&pool->lock);
1237 list_add(&page->lru, &pool->lru);
1238 spin_unlock(&pool->lock);
1239 z3fold_page_unlock(zhdr);
1240 clear_bit(PAGE_CLAIMED, &page->private);
1241 }
1242
1243
1244 spin_lock(&pool->lock);
1245 }
1246 spin_unlock(&pool->lock);
1247 return -EAGAIN;
1248 }
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260 static void *z3fold_map(struct z3fold_pool *pool, unsigned long handle)
1261 {
1262 struct z3fold_header *zhdr;
1263 struct page *page;
1264 void *addr;
1265 enum buddy buddy;
1266
1267 zhdr = handle_to_z3fold_header(handle);
1268 addr = zhdr;
1269 page = virt_to_page(zhdr);
1270
1271 if (test_bit(PAGE_HEADLESS, &page->private))
1272 goto out;
1273
1274 z3fold_page_lock(zhdr);
1275 buddy = handle_to_buddy(handle);
1276 switch (buddy) {
1277 case FIRST:
1278 addr += ZHDR_SIZE_ALIGNED;
1279 break;
1280 case MIDDLE:
1281 addr += zhdr->start_middle << CHUNK_SHIFT;
1282 set_bit(MIDDLE_CHUNK_MAPPED, &page->private);
1283 break;
1284 case LAST:
1285 addr += PAGE_SIZE - (handle_to_chunks(handle) << CHUNK_SHIFT);
1286 break;
1287 default:
1288 pr_err("unknown buddy id %d\n", buddy);
1289 WARN_ON(1);
1290 addr = NULL;
1291 break;
1292 }
1293
1294 if (addr)
1295 zhdr->mapped_count++;
1296 z3fold_page_unlock(zhdr);
1297 out:
1298 return addr;
1299 }
1300
1301
1302
1303
1304
1305
1306 static void z3fold_unmap(struct z3fold_pool *pool, unsigned long handle)
1307 {
1308 struct z3fold_header *zhdr;
1309 struct page *page;
1310 enum buddy buddy;
1311
1312 zhdr = handle_to_z3fold_header(handle);
1313 page = virt_to_page(zhdr);
1314
1315 if (test_bit(PAGE_HEADLESS, &page->private))
1316 return;
1317
1318 z3fold_page_lock(zhdr);
1319 buddy = handle_to_buddy(handle);
1320 if (buddy == MIDDLE)
1321 clear_bit(MIDDLE_CHUNK_MAPPED, &page->private);
1322 zhdr->mapped_count--;
1323 z3fold_page_unlock(zhdr);
1324 }
1325
1326
1327
1328
1329
1330
1331
1332 static u64 z3fold_get_pool_size(struct z3fold_pool *pool)
1333 {
1334 return atomic64_read(&pool->pages_nr);
1335 }
1336
1337 static bool z3fold_page_isolate(struct page *page, isolate_mode_t mode)
1338 {
1339 struct z3fold_header *zhdr;
1340 struct z3fold_pool *pool;
1341
1342 VM_BUG_ON_PAGE(!PageMovable(page), page);
1343 VM_BUG_ON_PAGE(PageIsolated(page), page);
1344
1345 if (test_bit(PAGE_HEADLESS, &page->private) ||
1346 test_bit(PAGE_CLAIMED, &page->private))
1347 return false;
1348
1349 zhdr = page_address(page);
1350 z3fold_page_lock(zhdr);
1351 if (test_bit(NEEDS_COMPACTING, &page->private) ||
1352 test_bit(PAGE_STALE, &page->private))
1353 goto out;
1354
1355 pool = zhdr_to_pool(zhdr);
1356
1357 if (zhdr->mapped_count == 0) {
1358 kref_get(&zhdr->refcount);
1359 if (!list_empty(&zhdr->buddy))
1360 list_del_init(&zhdr->buddy);
1361 spin_lock(&pool->lock);
1362 if (!list_empty(&page->lru))
1363 list_del(&page->lru);
1364 spin_unlock(&pool->lock);
1365 z3fold_page_unlock(zhdr);
1366 return true;
1367 }
1368 out:
1369 z3fold_page_unlock(zhdr);
1370 return false;
1371 }
1372
1373 static int z3fold_page_migrate(struct address_space *mapping, struct page *newpage,
1374 struct page *page, enum migrate_mode mode)
1375 {
1376 struct z3fold_header *zhdr, *new_zhdr;
1377 struct z3fold_pool *pool;
1378 struct address_space *new_mapping;
1379
1380 VM_BUG_ON_PAGE(!PageMovable(page), page);
1381 VM_BUG_ON_PAGE(!PageIsolated(page), page);
1382 VM_BUG_ON_PAGE(!PageLocked(newpage), newpage);
1383
1384 zhdr = page_address(page);
1385 pool = zhdr_to_pool(zhdr);
1386
1387 if (!z3fold_page_trylock(zhdr)) {
1388 return -EAGAIN;
1389 }
1390 if (zhdr->mapped_count != 0) {
1391 z3fold_page_unlock(zhdr);
1392 return -EBUSY;
1393 }
1394 if (work_pending(&zhdr->work)) {
1395 z3fold_page_unlock(zhdr);
1396 return -EAGAIN;
1397 }
1398 new_zhdr = page_address(newpage);
1399 memcpy(new_zhdr, zhdr, PAGE_SIZE);
1400 newpage->private = page->private;
1401 page->private = 0;
1402 z3fold_page_unlock(zhdr);
1403 spin_lock_init(&new_zhdr->page_lock);
1404 INIT_WORK(&new_zhdr->work, compact_page_work);
1405
1406
1407
1408
1409 INIT_LIST_HEAD(&new_zhdr->buddy);
1410 new_mapping = page_mapping(page);
1411 __ClearPageMovable(page);
1412 ClearPagePrivate(page);
1413
1414 get_page(newpage);
1415 z3fold_page_lock(new_zhdr);
1416 if (new_zhdr->first_chunks)
1417 encode_handle(new_zhdr, FIRST);
1418 if (new_zhdr->last_chunks)
1419 encode_handle(new_zhdr, LAST);
1420 if (new_zhdr->middle_chunks)
1421 encode_handle(new_zhdr, MIDDLE);
1422 set_bit(NEEDS_COMPACTING, &newpage->private);
1423 new_zhdr->cpu = smp_processor_id();
1424 spin_lock(&pool->lock);
1425 list_add(&newpage->lru, &pool->lru);
1426 spin_unlock(&pool->lock);
1427 __SetPageMovable(newpage, new_mapping);
1428 z3fold_page_unlock(new_zhdr);
1429
1430 queue_work_on(new_zhdr->cpu, pool->compact_wq, &new_zhdr->work);
1431
1432 page_mapcount_reset(page);
1433 put_page(page);
1434 return 0;
1435 }
1436
1437 static void z3fold_page_putback(struct page *page)
1438 {
1439 struct z3fold_header *zhdr;
1440 struct z3fold_pool *pool;
1441
1442 zhdr = page_address(page);
1443 pool = zhdr_to_pool(zhdr);
1444
1445 z3fold_page_lock(zhdr);
1446 if (!list_empty(&zhdr->buddy))
1447 list_del_init(&zhdr->buddy);
1448 INIT_LIST_HEAD(&page->lru);
1449 if (kref_put(&zhdr->refcount, release_z3fold_page_locked)) {
1450 atomic64_dec(&pool->pages_nr);
1451 return;
1452 }
1453 spin_lock(&pool->lock);
1454 list_add(&page->lru, &pool->lru);
1455 spin_unlock(&pool->lock);
1456 z3fold_page_unlock(zhdr);
1457 }
1458
1459 static const struct address_space_operations z3fold_aops = {
1460 .isolate_page = z3fold_page_isolate,
1461 .migratepage = z3fold_page_migrate,
1462 .putback_page = z3fold_page_putback,
1463 };
1464
1465
1466
1467
1468
1469 static int z3fold_zpool_evict(struct z3fold_pool *pool, unsigned long handle)
1470 {
1471 if (pool->zpool && pool->zpool_ops && pool->zpool_ops->evict)
1472 return pool->zpool_ops->evict(pool->zpool, handle);
1473 else
1474 return -ENOENT;
1475 }
1476
1477 static const struct z3fold_ops z3fold_zpool_ops = {
1478 .evict = z3fold_zpool_evict
1479 };
1480
1481 static void *z3fold_zpool_create(const char *name, gfp_t gfp,
1482 const struct zpool_ops *zpool_ops,
1483 struct zpool *zpool)
1484 {
1485 struct z3fold_pool *pool;
1486
1487 pool = z3fold_create_pool(name, gfp,
1488 zpool_ops ? &z3fold_zpool_ops : NULL);
1489 if (pool) {
1490 pool->zpool = zpool;
1491 pool->zpool_ops = zpool_ops;
1492 }
1493 return pool;
1494 }
1495
1496 static void z3fold_zpool_destroy(void *pool)
1497 {
1498 z3fold_destroy_pool(pool);
1499 }
1500
1501 static int z3fold_zpool_malloc(void *pool, size_t size, gfp_t gfp,
1502 unsigned long *handle)
1503 {
1504 return z3fold_alloc(pool, size, gfp, handle);
1505 }
1506 static void z3fold_zpool_free(void *pool, unsigned long handle)
1507 {
1508 z3fold_free(pool, handle);
1509 }
1510
1511 static int z3fold_zpool_shrink(void *pool, unsigned int pages,
1512 unsigned int *reclaimed)
1513 {
1514 unsigned int total = 0;
1515 int ret = -EINVAL;
1516
1517 while (total < pages) {
1518 ret = z3fold_reclaim_page(pool, 8);
1519 if (ret < 0)
1520 break;
1521 total++;
1522 }
1523
1524 if (reclaimed)
1525 *reclaimed = total;
1526
1527 return ret;
1528 }
1529
1530 static void *z3fold_zpool_map(void *pool, unsigned long handle,
1531 enum zpool_mapmode mm)
1532 {
1533 return z3fold_map(pool, handle);
1534 }
1535 static void z3fold_zpool_unmap(void *pool, unsigned long handle)
1536 {
1537 z3fold_unmap(pool, handle);
1538 }
1539
1540 static u64 z3fold_zpool_total_size(void *pool)
1541 {
1542 return z3fold_get_pool_size(pool) * PAGE_SIZE;
1543 }
1544
1545 static struct zpool_driver z3fold_zpool_driver = {
1546 .type = "z3fold",
1547 .owner = THIS_MODULE,
1548 .create = z3fold_zpool_create,
1549 .destroy = z3fold_zpool_destroy,
1550 .malloc = z3fold_zpool_malloc,
1551 .free = z3fold_zpool_free,
1552 .shrink = z3fold_zpool_shrink,
1553 .map = z3fold_zpool_map,
1554 .unmap = z3fold_zpool_unmap,
1555 .total_size = z3fold_zpool_total_size,
1556 };
1557
1558 MODULE_ALIAS("zpool-z3fold");
1559
1560 static int __init init_z3fold(void)
1561 {
1562 int ret;
1563
1564
1565 BUILD_BUG_ON(ZHDR_SIZE_ALIGNED > PAGE_SIZE);
1566 ret = z3fold_mount();
1567 if (ret)
1568 return ret;
1569
1570 zpool_register_driver(&z3fold_zpool_driver);
1571
1572 return 0;
1573 }
1574
1575 static void __exit exit_z3fold(void)
1576 {
1577 z3fold_unmount();
1578 zpool_unregister_driver(&z3fold_zpool_driver);
1579 }
1580
1581 module_init(init_z3fold);
1582 module_exit(exit_z3fold);
1583
1584 MODULE_LICENSE("GPL");
1585 MODULE_AUTHOR("Vitaly Wool <vitalywool@gmail.com>");
1586 MODULE_DESCRIPTION("3-Fold Allocator for Compressed Pages");