]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - net/ceph/osdmap.c
x86/bugs: Make cpu_show_common() static
[mirror_ubuntu-artful-kernel.git] / net / ceph / osdmap.c
index f358d0bfa76b35cb978e9e92b57aea38a4e3b391..79d14d70b7ea7e032ecffec839b2f44ee4fe7cdc 100644 (file)
@@ -2445,19 +2445,34 @@ static void apply_upmap(struct ceph_osdmap *osdmap,
 
        pg = lookup_pg_mapping(&osdmap->pg_upmap_items, pgid);
        if (pg) {
-               for (i = 0; i < raw->size; i++) {
-                       for (j = 0; j < pg->pg_upmap_items.len; j++) {
-                               int from = pg->pg_upmap_items.from_to[j][0];
-                               int to = pg->pg_upmap_items.from_to[j][1];
-
-                               if (from == raw->osds[i]) {
-                                       if (!(to != CRUSH_ITEM_NONE &&
-                                             to < osdmap->max_osd &&
-                                             osdmap->osd_weight[to] == 0))
-                                               raw->osds[i] = to;
+               /*
+                * Note: this approach does not allow a bidirectional swap,
+                * e.g., [[1,2],[2,1]] applied to [0,1,2] -> [0,2,1].
+                */
+               for (i = 0; i < pg->pg_upmap_items.len; i++) {
+                       int from = pg->pg_upmap_items.from_to[i][0];
+                       int to = pg->pg_upmap_items.from_to[i][1];
+                       int pos = -1;
+                       bool exists = false;
+
+                       /* make sure replacement doesn't already appear */
+                       for (j = 0; j < raw->size; j++) {
+                               int osd = raw->osds[j];
+
+                               if (osd == to) {
+                                       exists = true;
                                        break;
                                }
+                               /* ignore mapping if target is marked out */
+                               if (osd == from && pos < 0 &&
+                                   !(to != CRUSH_ITEM_NONE &&
+                                     to < osdmap->max_osd &&
+                                     osdmap->osd_weight[to] == 0)) {
+                                       pos = j;
+                               }
                        }
+                       if (!exists && pos >= 0)
+                               raw->osds[pos] = to;
                }
        }
 }