aboutsummaryrefslogtreecommitdiffstats
path: root/mm/zswap.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/zswap.c')
-rw-r--r--mm/zswap.c195
1 files changed, 99 insertions, 96 deletions
diff --git a/mm/zswap.c b/mm/zswap.c
index d93510c6aa2d..5a63f78a5601 100644
--- a/mm/zswap.c
+++ b/mm/zswap.c
@@ -217,6 +217,7 @@ static struct zswap_entry *zswap_entry_cache_alloc(gfp_t gfp)
217 if (!entry) 217 if (!entry)
218 return NULL; 218 return NULL;
219 entry->refcount = 1; 219 entry->refcount = 1;
220 RB_CLEAR_NODE(&entry->rbnode);
220 return entry; 221 return entry;
221} 222}
222 223
@@ -225,19 +226,6 @@ static void zswap_entry_cache_free(struct zswap_entry *entry)
225 kmem_cache_free(zswap_entry_cache, entry); 226 kmem_cache_free(zswap_entry_cache, entry);
226} 227}
227 228
228/* caller must hold the tree lock */
229static void zswap_entry_get(struct zswap_entry *entry)
230{
231 entry->refcount++;
232}
233
234/* caller must hold the tree lock */
235static int zswap_entry_put(struct zswap_entry *entry)
236{
237 entry->refcount--;
238 return entry->refcount;
239}
240
241/********************************* 229/*********************************
242* rbtree functions 230* rbtree functions
243**********************************/ 231**********************************/
@@ -285,6 +273,61 @@ static int zswap_rb_insert(struct rb_root *root, struct zswap_entry *entry,
285 return 0; 273 return 0;
286} 274}
287 275
276static void zswap_rb_erase(struct rb_root *root, struct zswap_entry *entry)
277{
278 if (!RB_EMPTY_NODE(&entry->rbnode)) {
279 rb_erase(&entry->rbnode, root);
280 RB_CLEAR_NODE(&entry->rbnode);
281 }
282}
283
284/*
285 * Carries out the common pattern of freeing and entry's zsmalloc allocation,
286 * freeing the entry itself, and decrementing the number of stored pages.
287 */
288static void zswap_free_entry(struct zswap_tree *tree,
289 struct zswap_entry *entry)
290{
291 zbud_free(tree->pool, entry->handle);
292 zswap_entry_cache_free(entry);
293 atomic_dec(&zswap_stored_pages);
294 zswap_pool_pages = zbud_get_pool_size(tree->pool);
295}
296
297/* caller must hold the tree lock */
298static void zswap_entry_get(struct zswap_entry *entry)
299{
300 entry->refcount++;
301}
302
303/* caller must hold the tree lock
304* remove from the tree and free it, if nobody reference the entry
305*/
306static void zswap_entry_put(struct zswap_tree *tree,
307 struct zswap_entry *entry)
308{
309 int refcount = --entry->refcount;
310
311 BUG_ON(refcount < 0);
312 if (refcount == 0) {
313 zswap_rb_erase(&tree->rbroot, entry);
314 zswap_free_entry(tree, entry);
315 }
316}
317
318/* caller must hold the tree lock */
319static struct zswap_entry *zswap_entry_find_get(struct rb_root *root,
320 pgoff_t offset)
321{
322 struct zswap_entry *entry = NULL;
323
324 entry = zswap_rb_search(root, offset);
325 if (entry)
326 zswap_entry_get(entry);
327
328 return entry;
329}
330
288/********************************* 331/*********************************
289* per-cpu code 332* per-cpu code
290**********************************/ 333**********************************/
@@ -368,18 +411,6 @@ static bool zswap_is_full(void)
368 zswap_pool_pages); 411 zswap_pool_pages);
369} 412}
370 413
371/*
372 * Carries out the common pattern of freeing and entry's zsmalloc allocation,
373 * freeing the entry itself, and decrementing the number of stored pages.
374 */
375static void zswap_free_entry(struct zswap_tree *tree, struct zswap_entry *entry)
376{
377 zbud_free(tree->pool, entry->handle);
378 zswap_entry_cache_free(entry);
379 atomic_dec(&zswap_stored_pages);
380 zswap_pool_pages = zbud_get_pool_size(tree->pool);
381}
382
383/********************************* 414/*********************************
384* writeback code 415* writeback code
385**********************************/ 416**********************************/
@@ -387,7 +418,7 @@ static void zswap_free_entry(struct zswap_tree *tree, struct zswap_entry *entry)
387enum zswap_get_swap_ret { 418enum zswap_get_swap_ret {
388 ZSWAP_SWAPCACHE_NEW, 419 ZSWAP_SWAPCACHE_NEW,
389 ZSWAP_SWAPCACHE_EXIST, 420 ZSWAP_SWAPCACHE_EXIST,
390 ZSWAP_SWAPCACHE_NOMEM 421 ZSWAP_SWAPCACHE_FAIL,
391}; 422};
392 423
393/* 424/*
@@ -401,9 +432,10 @@ enum zswap_get_swap_ret {
401 * added to the swap cache, and returned in retpage. 432 * added to the swap cache, and returned in retpage.
402 * 433 *
403 * If success, the swap cache page is returned in retpage 434 * If success, the swap cache page is returned in retpage
404 * Returns 0 if page was already in the swap cache, page is not locked 435 * Returns ZSWAP_SWAPCACHE_EXIST if page was already in the swap cache
405 * Returns 1 if the new page needs to be populated, page is locked 436 * Returns ZSWAP_SWAPCACHE_NEW if the new page needs to be populated,
406 * Returns <0 on error 437 * the new page is added to swapcache and locked
438 * Returns ZSWAP_SWAPCACHE_FAIL on error
407 */ 439 */
408static int zswap_get_swap_cache_page(swp_entry_t entry, 440static int zswap_get_swap_cache_page(swp_entry_t entry,
409 struct page **retpage) 441 struct page **retpage)
@@ -475,7 +507,7 @@ static int zswap_get_swap_cache_page(swp_entry_t entry,
475 if (new_page) 507 if (new_page)
476 page_cache_release(new_page); 508 page_cache_release(new_page);
477 if (!found_page) 509 if (!found_page)
478 return ZSWAP_SWAPCACHE_NOMEM; 510 return ZSWAP_SWAPCACHE_FAIL;
479 *retpage = found_page; 511 *retpage = found_page;
480 return ZSWAP_SWAPCACHE_EXIST; 512 return ZSWAP_SWAPCACHE_EXIST;
481} 513}
@@ -502,7 +534,7 @@ static int zswap_writeback_entry(struct zbud_pool *pool, unsigned long handle)
502 struct page *page; 534 struct page *page;
503 u8 *src, *dst; 535 u8 *src, *dst;
504 unsigned int dlen; 536 unsigned int dlen;
505 int ret, refcount; 537 int ret;
506 struct writeback_control wbc = { 538 struct writeback_control wbc = {
507 .sync_mode = WB_SYNC_NONE, 539 .sync_mode = WB_SYNC_NONE,
508 }; 540 };
@@ -517,23 +549,22 @@ static int zswap_writeback_entry(struct zbud_pool *pool, unsigned long handle)
517 549
518 /* find and ref zswap entry */ 550 /* find and ref zswap entry */
519 spin_lock(&tree->lock); 551 spin_lock(&tree->lock);
520 entry = zswap_rb_search(&tree->rbroot, offset); 552 entry = zswap_entry_find_get(&tree->rbroot, offset);
521 if (!entry) { 553 if (!entry) {
522 /* entry was invalidated */ 554 /* entry was invalidated */
523 spin_unlock(&tree->lock); 555 spin_unlock(&tree->lock);
524 return 0; 556 return 0;
525 } 557 }
526 zswap_entry_get(entry);
527 spin_unlock(&tree->lock); 558 spin_unlock(&tree->lock);
528 BUG_ON(offset != entry->offset); 559 BUG_ON(offset != entry->offset);
529 560
530 /* try to allocate swap cache page */ 561 /* try to allocate swap cache page */
531 switch (zswap_get_swap_cache_page(swpentry, &page)) { 562 switch (zswap_get_swap_cache_page(swpentry, &page)) {
532 case ZSWAP_SWAPCACHE_NOMEM: /* no memory */ 563 case ZSWAP_SWAPCACHE_FAIL: /* no memory or invalidate happened */
533 ret = -ENOMEM; 564 ret = -ENOMEM;
534 goto fail; 565 goto fail;
535 566
536 case ZSWAP_SWAPCACHE_EXIST: /* page is unlocked */ 567 case ZSWAP_SWAPCACHE_EXIST:
537 /* page is already in the swap cache, ignore for now */ 568 /* page is already in the swap cache, ignore for now */
538 page_cache_release(page); 569 page_cache_release(page);
539 ret = -EEXIST; 570 ret = -EEXIST;
@@ -556,43 +587,44 @@ static int zswap_writeback_entry(struct zbud_pool *pool, unsigned long handle)
556 SetPageUptodate(page); 587 SetPageUptodate(page);
557 } 588 }
558 589
590 /* move it to the tail of the inactive list after end_writeback */
591 SetPageReclaim(page);
592
559 /* start writeback */ 593 /* start writeback */
560 __swap_writepage(page, &wbc, end_swap_bio_write); 594 __swap_writepage(page, &wbc, end_swap_bio_write);
561 page_cache_release(page); 595 page_cache_release(page);
562 zswap_written_back_pages++; 596 zswap_written_back_pages++;
563 597
564 spin_lock(&tree->lock); 598 spin_lock(&tree->lock);
565
566 /* drop local reference */ 599 /* drop local reference */
567 zswap_entry_put(entry); 600 zswap_entry_put(tree, entry);
568 /* drop the initial reference from entry creation */
569 refcount = zswap_entry_put(entry);
570 601
571 /* 602 /*
572 * There are three possible values for refcount here: 603 * There are two possible situations for entry here:
573 * (1) refcount is 1, load is in progress, unlink from rbtree, 604 * (1) refcount is 1(normal case), entry is valid and on the tree
574 * load will free 605 * (2) refcount is 0, entry is freed and not on the tree
575 * (2) refcount is 0, (normal case) entry is valid, 606 * because invalidate happened during writeback
576 * remove from rbtree and free entry 607 * search the tree and free the entry if find entry
577 * (3) refcount is -1, invalidate happened during writeback, 608 */
578 * free entry 609 if (entry == zswap_rb_search(&tree->rbroot, offset))
579 */ 610 zswap_entry_put(tree, entry);
580 if (refcount >= 0) {
581 /* no invalidate yet, remove from rbtree */
582 rb_erase(&entry->rbnode, &tree->rbroot);
583 }
584 spin_unlock(&tree->lock); 611 spin_unlock(&tree->lock);
585 if (refcount <= 0) {
586 /* free the entry */
587 zswap_free_entry(tree, entry);
588 return 0;
589 }
590 return -EAGAIN;
591 612
613 goto end;
614
615 /*
616 * if we get here due to ZSWAP_SWAPCACHE_EXIST
617 * a load may happening concurrently
618 * it is safe and okay to not free the entry
619 * if we free the entry in the following put
620 * it it either okay to return !0
621 */
592fail: 622fail:
593 spin_lock(&tree->lock); 623 spin_lock(&tree->lock);
594 zswap_entry_put(entry); 624 zswap_entry_put(tree, entry);
595 spin_unlock(&tree->lock); 625 spin_unlock(&tree->lock);
626
627end:
596 return ret; 628 return ret;
597} 629}
598 630
@@ -676,11 +708,8 @@ static int zswap_frontswap_store(unsigned type, pgoff_t offset,
676 if (ret == -EEXIST) { 708 if (ret == -EEXIST) {
677 zswap_duplicate_entry++; 709 zswap_duplicate_entry++;
678 /* remove from rbtree */ 710 /* remove from rbtree */
679 rb_erase(&dupentry->rbnode, &tree->rbroot); 711 zswap_rb_erase(&tree->rbroot, dupentry);
680 if (!zswap_entry_put(dupentry)) { 712 zswap_entry_put(tree, dupentry);
681 /* free */
682 zswap_free_entry(tree, dupentry);
683 }
684 } 713 }
685 } while (ret == -EEXIST); 714 } while (ret == -EEXIST);
686 spin_unlock(&tree->lock); 715 spin_unlock(&tree->lock);
@@ -709,17 +738,16 @@ static int zswap_frontswap_load(unsigned type, pgoff_t offset,
709 struct zswap_entry *entry; 738 struct zswap_entry *entry;
710 u8 *src, *dst; 739 u8 *src, *dst;
711 unsigned int dlen; 740 unsigned int dlen;
712 int refcount, ret; 741 int ret;
713 742
714 /* find */ 743 /* find */
715 spin_lock(&tree->lock); 744 spin_lock(&tree->lock);
716 entry = zswap_rb_search(&tree->rbroot, offset); 745 entry = zswap_entry_find_get(&tree->rbroot, offset);
717 if (!entry) { 746 if (!entry) {
718 /* entry was written back */ 747 /* entry was written back */
719 spin_unlock(&tree->lock); 748 spin_unlock(&tree->lock);
720 return -1; 749 return -1;
721 } 750 }
722 zswap_entry_get(entry);
723 spin_unlock(&tree->lock); 751 spin_unlock(&tree->lock);
724 752
725 /* decompress */ 753 /* decompress */
@@ -734,22 +762,9 @@ static int zswap_frontswap_load(unsigned type, pgoff_t offset,
734 BUG_ON(ret); 762 BUG_ON(ret);
735 763
736 spin_lock(&tree->lock); 764 spin_lock(&tree->lock);
737 refcount = zswap_entry_put(entry); 765 zswap_entry_put(tree, entry);
738 if (likely(refcount)) {
739 spin_unlock(&tree->lock);
740 return 0;
741 }
742 spin_unlock(&tree->lock); 766 spin_unlock(&tree->lock);
743 767
744 /*
745 * We don't have to unlink from the rbtree because
746 * zswap_writeback_entry() or zswap_frontswap_invalidate page()
747 * has already done this for us if we are the last reference.
748 */
749 /* free */
750
751 zswap_free_entry(tree, entry);
752
753 return 0; 768 return 0;
754} 769}
755 770
@@ -758,7 +773,6 @@ static void zswap_frontswap_invalidate_page(unsigned type, pgoff_t offset)
758{ 773{
759 struct zswap_tree *tree = zswap_trees[type]; 774 struct zswap_tree *tree = zswap_trees[type];
760 struct zswap_entry *entry; 775 struct zswap_entry *entry;
761 int refcount;
762 776
763 /* find */ 777 /* find */
764 spin_lock(&tree->lock); 778 spin_lock(&tree->lock);
@@ -770,20 +784,12 @@ static void zswap_frontswap_invalidate_page(unsigned type, pgoff_t offset)
770 } 784 }
771 785
772 /* remove from rbtree */ 786 /* remove from rbtree */
773 rb_erase(&entry->rbnode, &tree->rbroot); 787 zswap_rb_erase(&tree->rbroot, entry);
774 788
775 /* drop the initial reference from entry creation */ 789 /* drop the initial reference from entry creation */
776 refcount = zswap_entry_put(entry); 790 zswap_entry_put(tree, entry);
777 791
778 spin_unlock(&tree->lock); 792 spin_unlock(&tree->lock);
779
780 if (refcount) {
781 /* writeback in progress, writeback will free */
782 return;
783 }
784
785 /* free */
786 zswap_free_entry(tree, entry);
787} 793}
788 794
789/* frees all zswap entries for the given swap type */ 795/* frees all zswap entries for the given swap type */
@@ -797,11 +803,8 @@ static void zswap_frontswap_invalidate_area(unsigned type)
797 803
798 /* walk the tree and free everything */ 804 /* walk the tree and free everything */
799 spin_lock(&tree->lock); 805 spin_lock(&tree->lock);
800 rbtree_postorder_for_each_entry_safe(entry, n, &tree->rbroot, rbnode) { 806 rbtree_postorder_for_each_entry_safe(entry, n, &tree->rbroot, rbnode)
801 zbud_free(tree->pool, entry->handle); 807 zswap_free_entry(tree, entry);
802 zswap_entry_cache_free(entry);
803 atomic_dec(&zswap_stored_pages);
804 }
805 tree->rbroot = RB_ROOT; 808 tree->rbroot = RB_ROOT;
806 spin_unlock(&tree->lock); 809 spin_unlock(&tree->lock);
807 810