Merge branch 'topic/fsl-mega-fast' of git://git.kernel.org/pub/scm/linux/kernel/git...
[firefly-linux-kernel-4.4.55.git] / mm / swapfile.c
index aebc2dd6e64975e2589429a0e22929f96c4d7532..58877312cf6b94b74da00b8913bf8db64d56ab26 100644 (file)
@@ -874,6 +874,48 @@ int page_swapcount(struct page *page)
        return count;
 }
 
+/*
+ * How many references to @entry are currently swapped out?
+ * This considers COUNT_CONTINUED so it returns exact answer.
+ */
+int swp_swapcount(swp_entry_t entry)
+{
+       int count, tmp_count, n;
+       struct swap_info_struct *p;
+       struct page *page;
+       pgoff_t offset;
+       unsigned char *map;
+
+       p = swap_info_get(entry);
+       if (!p)
+               return 0;
+
+       count = swap_count(p->swap_map[swp_offset(entry)]);
+       if (!(count & COUNT_CONTINUED))
+               goto out;
+
+       count &= ~COUNT_CONTINUED;
+       n = SWAP_MAP_MAX + 1;
+
+       offset = swp_offset(entry);
+       page = vmalloc_to_page(p->swap_map + offset);
+       offset &= ~PAGE_MASK;
+       VM_BUG_ON(page_private(page) != SWP_CONTINUED);
+
+       do {
+               page = list_entry(page->lru.next, struct page, lru);
+               map = kmap_atomic(page);
+               tmp_count = map[offset];
+               kunmap_atomic(map);
+
+               count += (tmp_count & ~COUNT_CONTINUED) * n;
+               n *= (SWAP_CONT_MAX + 1);
+       } while (tmp_count & COUNT_CONTINUED);
+out:
+       spin_unlock(&p->lock);
+       return count;
+}
+
 /*
  * We can write to an anon page without COW if there are no other references
  * to it.  And as a side-effect, free up its swap: because the old content