These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / mm / swapfile.c
index a7e7210..5887731 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
@@ -2032,7 +2074,7 @@ static int swap_show(struct seq_file *swap, void *v)
        }
 
        file = si->swap_file;
-       len = seq_path(swap, &file->f_path, " \t\n\\");
+       len = seq_file_path(swap, file, " \t\n\\");
        seq_printf(swap, "%*s%s\t%u\t%u\t%d\n",
                        len < 40 ? 40 - len : 1, " ",
                        S_ISBLK(file_inode(file)->i_mode) ?
@@ -2143,11 +2185,10 @@ static int claim_swapfile(struct swap_info_struct *p, struct inode *inode)
        if (S_ISBLK(inode->i_mode)) {
                p->bdev = bdgrab(I_BDEV(inode));
                error = blkdev_get(p->bdev,
-                                  FMODE_READ | FMODE_WRITE | FMODE_EXCL,
-                                  sys_swapon);
+                                  FMODE_READ | FMODE_WRITE | FMODE_EXCL, p);
                if (error < 0) {
                        p->bdev = NULL;
-                       return -EINVAL;
+                       return error;
                }
                p->old_block_size = block_size(p->bdev);
                error = set_blocksize(p->bdev, PAGE_SIZE);
@@ -2348,7 +2389,6 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
        struct filename *name;
        struct file *swap_file = NULL;
        struct address_space *mapping;
-       int i;
        int prio;
        int error;
        union swap_header *swap_header;
@@ -2388,19 +2428,8 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
 
        p->swap_file = swap_file;
        mapping = swap_file->f_mapping;
-
-       for (i = 0; i < nr_swapfiles; i++) {
-               struct swap_info_struct *q = swap_info[i];
-
-               if (q == p || !q->swap_file)
-                       continue;
-               if (mapping == q->swap_file->f_mapping) {
-                       error = -EBUSY;
-                       goto bad_swap;
-               }
-       }
-
        inode = mapping->host;
+
        /* If S_ISREG(inode->i_mode) will do mutex_lock(&inode->i_mutex); */
        error = claim_swapfile(p, inode);
        if (unlikely(error))
@@ -2433,6 +2462,8 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
                goto bad_swap;
        }
        if (p->bdev && blk_queue_nonrot(bdev_get_queue(p->bdev))) {
+               int cpu;
+
                p->flags |= SWP_SOLIDSTATE;
                /*
                 * select a random position to start with to help wear leveling
@@ -2451,9 +2482,9 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
                        error = -ENOMEM;
                        goto bad_swap;
                }
-               for_each_possible_cpu(i) {
+               for_each_possible_cpu(cpu) {
                        struct percpu_cluster *cluster;
-                       cluster = per_cpu_ptr(p->percpu_cluster, i);
+                       cluster = per_cpu_ptr(p->percpu_cluster, cpu);
                        cluster_set_null(&cluster->index);
                }
        }