goto out;
 }
 
+static void enable_swap_info(struct swap_info_struct *p, int prio,
+                               unsigned char *swap_map)
+{
+       int i, prev;
+
+       spin_lock(&swap_lock);
+       if (prio >= 0)
+               p->prio = prio;
+       else
+               p->prio = --least_priority;
+       p->swap_map = swap_map;
+       p->flags |= SWP_WRITEOK;
+       nr_swap_pages += p->pages;
+       total_swap_pages += p->pages;
+
+       /* insert swap space into swap_list: */
+       prev = -1;
+       for (i = swap_list.head; i >= 0; i = swap_info[i]->next) {
+               if (p->prio >= swap_info[i]->prio)
+                       break;
+               prev = i;
+       }
+       p->next = i;
+       if (prev < 0)
+               swap_list.head = swap_list.next = p->type;
+       else
+               swap_info[prev]->next = p->type;
+       spin_unlock(&swap_lock);
+}
+
 SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
 {
        struct swap_info_struct *p = NULL;
        current->flags &= ~PF_OOM_ORIGIN;
 
        if (err) {
+               /*
+                * reading p->prio and p->swap_map outside the lock is
+                * safe here because only sys_swapon and sys_swapoff
+                * change them, and there can be no other sys_swapon or
+                * sys_swapoff for this swap_info_struct at this point.
+                */
                /* re-insert swap space back into swap_list */
-               spin_lock(&swap_lock);
-               if (p->prio < 0)
-                       p->prio = --least_priority;
-               p->flags |= SWP_WRITEOK;
-               nr_swap_pages += p->pages;
-               total_swap_pages += p->pages;
-
-               prev = -1;
-               for (i = swap_list.head; i >= 0; i = swap_info[i]->next) {
-                       if (p->prio >= swap_info[i]->prio)
-                               break;
-                       prev = i;
-               }
-               p->next = i;
-               if (prev < 0)
-                       swap_list.head = swap_list.next = type;
-               else
-                       swap_info[prev]->next = type;
-               spin_unlock(&swap_lock);
+               enable_swap_info(p, p->prio, p->swap_map);
                goto out_dput;
        }
 
        char *name;
        struct file *swap_file = NULL;
        struct address_space *mapping;
-       int i, prev;
+       int i;
+       int prio;
        int error;
        union swap_header *swap_header;
        int nr_extents;
        }
 
        mutex_lock(&swapon_mutex);
-       spin_lock(&swap_lock);
+       prio = -1;
        if (swap_flags & SWAP_FLAG_PREFER)
-               p->prio =
+               prio =
                  (swap_flags & SWAP_FLAG_PRIO_MASK) >> SWAP_FLAG_PRIO_SHIFT;
-       else
-               p->prio = --least_priority;
-       p->swap_map = swap_map;
-       p->flags |= SWP_WRITEOK;
-       nr_swap_pages += p->pages;
-       total_swap_pages += p->pages;
-
-       /* insert swap space into swap_list: */
-       prev = -1;
-       for (i = swap_list.head; i >= 0; i = swap_info[i]->next) {
-               if (p->prio >= swap_info[i]->prio)
-                       break;
-               prev = i;
-       }
-       p->next = i;
-       if (prev < 0)
-               swap_list.head = swap_list.next = p->type;
-       else
-               swap_info[prev]->next = p->type;
-       spin_unlock(&swap_lock);
+       enable_swap_info(p, prio, swap_map);
 
        printk(KERN_INFO "Adding %uk swap on %s.  "
                        "Priority:%d extents:%d across:%lluk %s%s\n",