diff options
-rw-r--r-- | daemons/lvmetad/lvmetad-core.c | 183 |
1 files changed, 31 insertions, 152 deletions
diff --git a/daemons/lvmetad/lvmetad-core.c b/daemons/lvmetad/lvmetad-core.c index 45641a672..188c9b9d9 100644 --- a/daemons/lvmetad/lvmetad-core.c +++ b/daemons/lvmetad/lvmetad-core.c @@ -1869,46 +1869,12 @@ out: return retval; } -static dev_t device_remove(lvmetad_state *s, struct dm_config_tree *pvmeta, dev_t device) -{ - struct dm_config_node *pvmeta_tmp; - struct dm_config_value *v = NULL; - dev_t alt_device = 0, prim_device = 0; - - if ((pvmeta_tmp = dm_config_find_node(pvmeta->root, "pvmeta/devices_alternate"))) - v = pvmeta_tmp->v; - - prim_device = dm_config_find_int64(pvmeta->root, "pvmeta/device", 0); - - /* it is the primary device */ - if (device > 0 && device == prim_device && pvmeta_tmp && pvmeta_tmp->v) - { - alt_device = pvmeta_tmp->v->v.i; - pvmeta_tmp->v = pvmeta_tmp->v->next; - pvmeta_tmp = dm_config_find_node(pvmeta->root, "pvmeta/device"); - pvmeta_tmp->v->v.i = alt_device; - } else if (device != prim_device) - alt_device = prim_device; - - /* it is an alternate device */ - if (device > 0 && v && v->v.i == device) - pvmeta_tmp->v = v->next; - else while (device > 0 && pvmeta_tmp && v) { - if (v->next && v->next->v.i == device) - v->next = v->next->next; - v = v->next; - } - - return alt_device; -} - static response pv_gone(lvmetad_state *s, request r) { const char *arg_pvid = NULL; char *old_pvid = NULL; const char *pvid; int64_t device; - int64_t alt_device = 0; struct dm_config_tree *pvmeta; char *vgid; @@ -1938,17 +1904,7 @@ static response pv_gone(lvmetad_state *s, request r) vgid = dm_hash_lookup(s->pvid_to_vgid, pvid); dm_hash_remove_binary(s->device_to_pvid, &device, sizeof(device)); - - alt_device = device_remove(s, pvmeta, device); - - if (!alt_device) { - /* The PV was not a duplicate, so remove it. */ - dm_hash_remove(s->pvid_to_pvmeta, pvid); - } else { - /* The PV remains on another device. */ - DEBUGLOG(s, "pv_gone %s device %" PRIu64 " has alt_device %" PRIu64, - pvid, device, alt_device); - } + dm_hash_remove(s->pvid_to_pvmeta, pvid); unlock_pvid_to_pvmeta(s); @@ -1970,18 +1926,11 @@ static response pv_gone(lvmetad_state *s, request r) vgid = NULL; } - if (!alt_device) { - dm_config_destroy(pvmeta); - if (old_pvid) - dm_free(old_pvid); - } + dm_config_destroy(pvmeta); + if (old_pvid) + dm_free(old_pvid); - if (alt_device) { - return daemon_reply_simple("OK", - "device = %"PRId64, alt_device, - NULL); - } else - return daemon_reply_simple("OK", NULL ); + return daemon_reply_simple("OK", NULL ); } static response pv_clear_all(lvmetad_state *s, request r) @@ -2100,10 +2049,7 @@ static response pv_found(lvmetad_state *s, request r) struct dm_config_tree *new_pvmeta = NULL; struct dm_config_tree *prev_pvmeta_on_dev = NULL; struct dm_config_tree *vgmeta = NULL; - struct dm_config_node *altdev = NULL; - struct dm_config_value *altdev_v = NULL; const char *arg_pvid = NULL; - const char *arg_pvid_dup = NULL; const char *arg_pvid_lookup = NULL; const char *new_pvid = NULL; const char *new_pvid_dup = NULL; @@ -2281,40 +2227,14 @@ static response pv_found(lvmetad_state *s, request r) } else if (new_pvid && !new_device) { /* * New PV on old device (existing device reused for new PV). - * The previous PV on arg_device may or may not still exist, - * this is determined by device_remove() which checks the - * pvmeta for the previous PV (prev_pvid_on_dev and - * prev_pvmeta_on_dev) to see if arg_device was the only - * device for the PV, or if arg_device was a duplicate for - * the PV. If arg_device was previously a duplicate, then - * the prev PV should be kept, but with arg_device removed. - * If arg_device was the only device for the prev PV, then - * the prev PV should be removed entirely. + * The previous PV on arg_device is replaced by the new one. * - * In either case, don't free prev_pvid or prev_vgid - * strings because they are used at the end to check - * the VG metadata. + * Don't free prev_pvid or prev_vgid strings because they are + * used at the end to check the VG metadata. */ changed |= 1; - if (prev_pvmeta_on_dev && - !device_remove(s, prev_pvmeta_on_dev, arg_device)) { - /* - * The prev PV has no remaining device after - * removing arg_device, so arg_device was not a - * duplicate; remove the prev PV entirely. - * - * (hash_remove in pvid_to_vgid is done at the - * end after the VG metadata is checked) - * - * FIXME: we could check if the new pvid is a new - * duplicate of another existing PV. This can happen: - * start with two different pvs A and B, - * dd if=A of=B, pvscan --cache B. This detects that - * B is removed, but doesn't detect that A is now a - * duplicate. ('pvscan --cache' does detect the - * dup because all pvs are scanned.) - */ + if (prev_pvmeta_on_dev) { DEBUGLOG(s, "pv_found new pvid device_to_pvid %" PRIu64 " to %s removes prev pvid %s", arg_device, new_pvid, prev_pvid_on_dev); @@ -2324,23 +2244,24 @@ static response pv_found(lvmetad_state *s, request r) /* removes arg_device/prev_pvid_on_dev mapping */ dm_hash_remove_binary(s->device_to_pvid, &arg_device, sizeof(arg_device)); - } else { + /* - * The prev PV existing on a remaining alternate - * device after removing arg_device, so arg_device - * was a duplicate; keep the prev PV. - * - * FIXME: if the duplicate devices were path aliases - * to the same underlying device, then keeping the - * prev PV for the remaining alt device isn't nice. + * The new PV replacing the prev PV was copied from + * another existing PV, creating a duplicate PV which + * we ignore. */ - DEBUGLOG(s, "pv_found new pvid device_to_pvid %" PRIu64 " to %s keeping prev pvid %s", - arg_device, new_pvid, prev_pvid_on_dev); - - /* removes arg_device/prev_pvid_on_dev mapping */ - dm_hash_remove_binary(s->device_to_pvid, &arg_device, sizeof(arg_device)); + if (dm_hash_lookup(s->pvid_to_pvmeta, new_pvid)) { + DEBUGLOG(s, "pv_found ignore duplicate device %" PRIu64 " of existing PV for pvid %s", + arg_device, arg_pvid); + unlock_pvid_to_pvmeta(s); + dm_config_destroy(new_pvmeta); + s->flags |= GLFL_DISABLE; + s->flags |= GLFL_DISABLE_REASON_DUPLICATES; + return reply_fail("Ignore duplicate PV"); + } } + if (!(new_pvid_dup = dm_strdup(new_pvid))) goto nomem; @@ -2353,57 +2274,15 @@ static response pv_found(lvmetad_state *s, request r) } else if (new_device && !new_pvid) { /* * Old PV on new device (duplicate) - * . add new_device/arg_pvid mapping - * . leave existing old_device/arg_pvid mapping - * . add new_pvmeta, replacing old_pvmeta - * . modify new_pvmeta, adding an alternate device entry for old_device + * Ignore it. */ - changed |= 1; - - DEBUGLOG(s, "pv_found new device device_to_pvid %" PRIu64 " to %s also %" PRIu64 " to %s", - new_device, arg_pvid, old_device, arg_pvid); - - if (!(arg_pvid_dup = dm_strdup(arg_pvid))) - goto nomem; - - if (!dm_hash_insert_binary(s->device_to_pvid, &new_device, sizeof(new_device), (char *)arg_pvid_dup)) - goto nomem; - - if (!dm_hash_insert(s->pvid_to_pvmeta, arg_pvid, new_pvmeta)) - goto nomem; - - /* Copy existing altdev info, or create new, and add it to new pvmeta. */ - if ((altdev = dm_config_find_node(old_pvmeta->root, "pvmeta/devices_alternate"))) { - if (!(altdev = dm_config_clone_node(new_pvmeta, altdev, 0))) - goto nomem; - chain_node(altdev, new_pvmeta->root, 0); - } else { - if (!(altdev = make_config_node(new_pvmeta, "devices_alternate", new_pvmeta->root, 0))) - goto nomem; - } - - /* Add an altdev entry for old_device. */ - altdev_v = altdev->v; - while (1) { - if (altdev_v && altdev_v->v.i == old_device) - break; - if (altdev_v) - altdev_v = altdev_v->next; - if (!altdev_v) { - if (!(altdev_v = dm_config_create_value(new_pvmeta))) - goto nomem; - altdev_v->next = altdev->v; - altdev->v = altdev_v; - altdev->v->v.i = old_device; - break; - } - }; - altdev_v = altdev->v; - while (altdev_v) { - if (altdev_v->next && altdev_v->next->v.i == new_device) - altdev_v->next = altdev_v->next->next; - altdev_v = altdev_v->next; - } + DEBUGLOG(s, "pv_found ignore duplicate device %" PRIu64 " of existing device %" PRIu64 " for pvid %s", + new_device, old_device, arg_pvid); + unlock_pvid_to_pvmeta(s); + dm_config_destroy(new_pvmeta); + s->flags |= GLFL_DISABLE; + s->flags |= GLFL_DISABLE_REASON_DUPLICATES; + return reply_fail("Ignore duplicate PV"); } unlock_pvid_to_pvmeta(s); |