OSDN Git Service

Merge patch "RISC-V: Add ptrace support for vectors"
[tomoyo/tomoyo-test1.git] / mm / swapfile.c
index b15112b..e52f486 100644 (file)
 #include <linux/memcontrol.h>
 #include <linux/poll.h>
 #include <linux/oom.h>
-#include <linux/frontswap.h>
 #include <linux/swapfile.h>
 #include <linux/export.h>
 #include <linux/swap_slots.h>
 #include <linux/sort.h>
 #include <linux/completion.h>
 #include <linux/suspend.h>
+#include <linux/zswap.h>
 
 #include <asm/tlbflush.h>
 #include <linux/swapops.h>
 #include <linux/swap_cgroup.h>
+#include "internal.h"
 #include "swap.h"
 
 static bool swap_count_continued(struct swap_info_struct *, pgoff_t,
@@ -95,7 +96,7 @@ static PLIST_HEAD(swap_active_head);
 static struct plist_head *swap_avail_heads;
 static DEFINE_SPINLOCK(swap_avail_lock);
 
-struct swap_info_struct *swap_info[MAX_SWAPFILES];
+static struct swap_info_struct *swap_info[MAX_SWAPFILES];
 
 static DEFINE_MUTEX(swapon_mutex);
 
@@ -714,10 +715,8 @@ static void add_to_avail_list(struct swap_info_struct *p)
        int nid;
 
        spin_lock(&swap_avail_lock);
-       for_each_node(nid) {
-               WARN_ON(!plist_node_empty(&p->avail_lists[nid]));
+       for_each_node(nid)
                plist_add(&p->avail_lists[nid], &swap_avail_heads[nid]);
-       }
        spin_unlock(&swap_avail_lock);
 }
 
@@ -746,7 +745,7 @@ static void swap_range_free(struct swap_info_struct *si, unsigned long offset,
                swap_slot_free_notify = NULL;
        while (offset <= end) {
                arch_swap_invalidate_page(si->type, offset);
-               frontswap_invalidate_page(si->type, offset);
+               zswap_invalidate(si->type, offset);
                if (swap_slot_free_notify)
                        swap_slot_free_notify(si->bdev, offset);
                offset++;
@@ -1537,7 +1536,7 @@ unlock_out:
 
 static bool folio_swapped(struct folio *folio)
 {
-       swp_entry_t entry = folio_swap_entry(folio);
+       swp_entry_t entry = folio->swap;
        struct swap_info_struct *si = _swap_info_get(entry);
 
        if (!si)
@@ -1773,13 +1772,20 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd,
                        swp_entry = make_hwpoison_entry(swapcache);
                        page = swapcache;
                } else {
-                       swp_entry = make_swapin_error_entry();
+                       swp_entry = make_poisoned_swp_entry();
                }
                new_pte = swp_entry_to_pte(swp_entry);
                ret = 0;
                goto setpte;
        }
 
+       /*
+        * Some architectures may have to restore extra metadata to the page
+        * when reading from swap. This metadata may be indexed by swap entry
+        * so this must be called before swap_free().
+        */
+       arch_swap_restore(entry, page_folio(page));
+
        /* See do_swap_page() */
        BUG_ON(!PageAnon(page) && PageMappedToDisk(page));
        BUG_ON(PageAnon(page) && PageAnonExclusive(page));
@@ -2330,16 +2336,18 @@ static void _enable_swap_info(struct swap_info_struct *p)
         * swap_info_struct.
         */
        plist_add(&p->list, &swap_active_head);
-       add_to_avail_list(p);
+
+       /* add to available list iff swap device is not full */
+       if (p->highest_bit)
+               add_to_avail_list(p);
 }
 
 static void enable_swap_info(struct swap_info_struct *p, int prio,
                                unsigned char *swap_map,
-                               struct swap_cluster_info *cluster_info,
-                               unsigned long *frontswap_map)
+                               struct swap_cluster_info *cluster_info)
 {
-       if (IS_ENABLED(CONFIG_FRONTSWAP))
-               frontswap_init(p->type, frontswap_map);
+       zswap_swapon(p->type);
+
        spin_lock(&swap_lock);
        spin_lock(&p->lock);
        setup_swap_info(p, prio, swap_map, cluster_info);
@@ -2382,7 +2390,6 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
        struct swap_info_struct *p = NULL;
        unsigned char *swap_map;
        struct swap_cluster_info *cluster_info;
-       unsigned long *frontswap_map;
        struct file *swap_file, *victim;
        struct address_space *mapping;
        struct inode *inode;
@@ -2507,12 +2514,10 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
        p->swap_map = NULL;
        cluster_info = p->cluster_info;
        p->cluster_info = NULL;
-       frontswap_map = frontswap_map_get(p);
        spin_unlock(&p->lock);
        spin_unlock(&swap_lock);
        arch_swap_invalidate_area(p->type);
-       frontswap_invalidate_area(p->type);
-       frontswap_map_set(p, NULL);
+       zswap_swapoff(p->type);
        mutex_unlock(&swapon_mutex);
        free_percpu(p->percpu_cluster);
        p->percpu_cluster = NULL;
@@ -2520,7 +2525,6 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
        p->cluster_next_cpu = NULL;
        vfree(swap_map);
        kvfree(cluster_info);
-       kvfree(frontswap_map);
        /* Destroy swap account information */
        swap_cgroup_swapoff(p->type);
        exit_swap_address_space(p->type);
@@ -2632,8 +2636,8 @@ static int swap_show(struct seq_file *swap, void *v)
                return 0;
        }
 
-       bytes = si->pages << (PAGE_SHIFT - 10);
-       inuse = READ_ONCE(si->inuse_pages) << (PAGE_SHIFT - 10);
+       bytes = K(si->pages);
+       inuse = K(READ_ONCE(si->inuse_pages));
 
        file = si->swap_file;
        len = seq_file_path(swap, file, " \t\n\\");
@@ -2858,8 +2862,7 @@ static unsigned long read_swap_header(struct swap_info_struct *p,
        }
        if (last_page > maxpages) {
                pr_warn("Truncating oversized swap area, only using %luk out of %luk\n",
-                       maxpages << (PAGE_SHIFT - 10),
-                       last_page << (PAGE_SHIFT - 10));
+                       K(maxpages), K(last_page));
        }
        if (maxpages > last_page) {
                maxpages = last_page + 1;
@@ -2987,7 +2990,6 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
        unsigned long maxpages;
        unsigned char *swap_map = NULL;
        struct swap_cluster_info *cluster_info = NULL;
-       unsigned long *frontswap_map = NULL;
        struct page *page = NULL;
        struct inode *inode = NULL;
        bool inced_nr_rotate_swap = false;
@@ -3127,11 +3129,6 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
                error = nr_extents;
                goto bad_swap_unlock_inode;
        }
-       /* frontswap enabled? set up bit-per-page map for frontswap */
-       if (IS_ENABLED(CONFIG_FRONTSWAP))
-               frontswap_map = kvcalloc(BITS_TO_LONGS(maxpages),
-                                        sizeof(long),
-                                        GFP_KERNEL);
 
        if ((swap_flags & SWAP_FLAG_DISCARD) &&
            p->bdev && bdev_max_discard_sectors(p->bdev)) {
@@ -3184,16 +3181,15 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
        if (swap_flags & SWAP_FLAG_PREFER)
                prio =
                  (swap_flags & SWAP_FLAG_PRIO_MASK) >> SWAP_FLAG_PRIO_SHIFT;
-       enable_swap_info(p, prio, swap_map, cluster_info, frontswap_map);
+       enable_swap_info(p, prio, swap_map, cluster_info);
 
-       pr_info("Adding %uk swap on %s.  Priority:%d extents:%d across:%lluk %s%s%s%s%s\n",
-               p->pages<<(PAGE_SHIFT-10), name->name, p->prio,
-               nr_extents, (unsigned long long)span<<(PAGE_SHIFT-10),
+       pr_info("Adding %uk swap on %s.  Priority:%d extents:%d across:%lluk %s%s%s%s\n",
+               K(p->pages), name->name, p->prio, nr_extents,
+               K((unsigned long long)span),
                (p->flags & SWP_SOLIDSTATE) ? "SS" : "",
                (p->flags & SWP_DISCARDABLE) ? "D" : "",
                (p->flags & SWP_AREA_DISCARD) ? "s" : "",
-               (p->flags & SWP_PAGE_DISCARD) ? "c" : "",
-               (frontswap_map) ? "FS" : "");
+               (p->flags & SWP_PAGE_DISCARD) ? "c" : "");
 
        mutex_unlock(&swapon_mutex);
        atomic_inc(&proc_poll_event);
@@ -3223,7 +3219,6 @@ bad_swap:
        spin_unlock(&swap_lock);
        vfree(swap_map);
        kvfree(cluster_info);
-       kvfree(frontswap_map);
        if (inced_nr_rotate_swap)
                atomic_dec(&nr_rotate_swap);
        if (swap_file)
@@ -3374,7 +3369,7 @@ struct swap_info_struct *swp_swap_info(swp_entry_t entry)
 
 struct swap_info_struct *page_swap_info(struct page *page)
 {
-       swp_entry_t entry = { .val = page_private(page) };
+       swp_entry_t entry = page_swap_entry(page);
        return swp_swap_info(entry);
 }
 
@@ -3389,7 +3384,7 @@ EXPORT_SYMBOL_GPL(swapcache_mapping);
 
 pgoff_t __page_file_index(struct page *page)
 {
-       swp_entry_t swap = { .val = page_private(page) };
+       swp_entry_t swap = page_swap_entry(page);
        return swp_offset(swap);
 }
 EXPORT_SYMBOL_GPL(__page_file_index);