]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - mm/swap_cgroup.c
mm/memory-hotplug: switch locking to a percpu rwsem
[karo-tx-linux.git] / mm / swap_cgroup.c
index 3405b4ee1757e3deb196c93e49b9641dad8d56fb..fcd2740f4ed7e6623d62188cf40c7ce406af9630 100644 (file)
@@ -61,21 +61,27 @@ not_enough_page:
        return -ENOMEM;
 }
 
+static struct swap_cgroup *__lookup_swap_cgroup(struct swap_cgroup_ctrl *ctrl,
+                                               pgoff_t offset)
+{
+       struct page *mappage;
+       struct swap_cgroup *sc;
+
+       mappage = ctrl->map[offset / SC_PER_PAGE];
+       sc = page_address(mappage);
+       return sc + offset % SC_PER_PAGE;
+}
+
 static struct swap_cgroup *lookup_swap_cgroup(swp_entry_t ent,
                                        struct swap_cgroup_ctrl **ctrlp)
 {
        pgoff_t offset = swp_offset(ent);
        struct swap_cgroup_ctrl *ctrl;
-       struct page *mappage;
-       struct swap_cgroup *sc;
 
        ctrl = &swap_cgroup_ctrl[swp_type(ent)];
        if (ctrlp)
                *ctrlp = ctrl;
-
-       mappage = ctrl->map[offset / SC_PER_PAGE];
-       sc = page_address(mappage);
-       return sc + offset % SC_PER_PAGE;
+       return __lookup_swap_cgroup(ctrl, offset);
 }
 
 /**
@@ -108,25 +114,39 @@ unsigned short swap_cgroup_cmpxchg(swp_entry_t ent,
 }
 
 /**
- * swap_cgroup_record - record mem_cgroup for this swp_entry.
- * @ent: swap entry to be recorded into
+ * swap_cgroup_record - record mem_cgroup for a set of swap entries
+ * @ent: the first swap entry to be recorded into
  * @id: mem_cgroup to be recorded
+ * @nr_ents: number of swap entries to be recorded
  *
  * Returns old value at success, 0 at failure.
  * (Of course, old value can be 0.)
  */
-unsigned short swap_cgroup_record(swp_entry_t ent, unsigned short id)
+unsigned short swap_cgroup_record(swp_entry_t ent, unsigned short id,
+                                 unsigned int nr_ents)
 {
        struct swap_cgroup_ctrl *ctrl;
        struct swap_cgroup *sc;
        unsigned short old;
        unsigned long flags;
+       pgoff_t offset = swp_offset(ent);
+       pgoff_t end = offset + nr_ents;
 
        sc = lookup_swap_cgroup(ent, &ctrl);
 
        spin_lock_irqsave(&ctrl->lock, flags);
        old = sc->id;
-       sc->id = id;
+       for (;;) {
+               VM_BUG_ON(sc->id != old);
+               sc->id = id;
+               offset++;
+               if (offset == end)
+                       break;
+               if (offset % SC_PER_PAGE)
+                       sc++;
+               else
+                       sc = __lookup_swap_cgroup(ctrl, offset);
+       }
        spin_unlock_irqrestore(&ctrl->lock, flags);
 
        return old;