/* * update_parts_linkage -- (internal) set uuids linking recreated parts within * a replica */ static int update_parts_linkage(struct pool_set *set, unsigned repn, struct poolset_health_status *set_hs) { LOG(3, "set %p, repn %u, set_hs %p", set, repn, set_hs); struct pool_replica *rep = REP(set, repn); for (unsigned p = 0; p < rep->nhdrs; ++p) { struct pool_hdr *hdrp = HDR(rep, p); struct pool_hdr *prev_hdrp = HDRP(rep, p); struct pool_hdr *next_hdrp = HDRN(rep, p); /* set uuids in the current part */ memcpy(hdrp->prev_part_uuid, PARTP(rep, p).uuid, POOL_HDR_UUID_LEN); memcpy(hdrp->next_part_uuid, PARTN(rep, p).uuid, POOL_HDR_UUID_LEN); util_checksum(hdrp, sizeof(*hdrp), &hdrp->checksum, 1, POOL_HDR_CSUM_END_OFF); /* set uuids in the previous part */ memcpy(prev_hdrp->next_part_uuid, PART(rep, p).uuid, POOL_HDR_UUID_LEN); util_checksum(prev_hdrp, sizeof(*prev_hdrp), &prev_hdrp->checksum, 1, POOL_HDR_CSUM_END_OFF); /* set uuids in the next part */ memcpy(next_hdrp->prev_part_uuid, PART(rep, p).uuid, POOL_HDR_UUID_LEN); util_checksum(next_hdrp, sizeof(*next_hdrp), &next_hdrp->checksum, 1, POOL_HDR_CSUM_END_OFF); /* store pool's header */ util_persist(PART(rep, p).is_dev_dax, hdrp, sizeof(*hdrp)); util_persist(PARTP(rep, p).is_dev_dax, prev_hdrp, sizeof(*prev_hdrp)); util_persist(PARTN(rep, p).is_dev_dax, next_hdrp, sizeof(*next_hdrp)); } return 0; }
/* * check_uuids_between_parts -- (internal) check if uuids between adjacent * parts are consistent for a given replica */ static int check_uuids_between_parts(struct pool_set *set, unsigned repn, struct poolset_health_status *set_hs) { LOG(3, "set %p, repn %u, set_hs %p", set, repn, set_hs); struct pool_replica *rep = REP(set, repn); /* check poolset_uuid consistency between replica's parts */ LOG(4, "checking consistency of poolset uuid in replica %u", repn); uuid_t poolset_uuid; int uuid_stored = 0; unsigned part_stored = UNDEF_PART; for (unsigned p = 0; p < rep->nhdrs; ++p) { /* skip broken parts */ if (replica_is_part_broken(repn, p, set_hs)) continue; if (!uuid_stored) { memcpy(poolset_uuid, HDR(rep, p)->poolset_uuid, POOL_HDR_UUID_LEN); uuid_stored = 1; part_stored = p; continue; } if (uuidcmp(HDR(rep, p)->poolset_uuid, poolset_uuid)) { ERR("different poolset uuids in parts from the same" " replica (repn %u, parts %u and %u); cannot" " synchronize", repn, part_stored, p); errno = EINVAL; return -1; } } /* check if all uuids for adjacent replicas are the same across parts */ LOG(4, "checking consistency of adjacent replicas' uuids in replica %u", repn); unsigned unbroken_p = UNDEF_PART; for (unsigned p = 0; p < rep->nhdrs; ++p) { /* skip broken parts */ if (replica_is_part_broken(repn, p, set_hs)) continue; if (unbroken_p == UNDEF_PART) { unbroken_p = p; continue; } struct pool_hdr *hdrp = HDR(rep, p); int prev_differ = uuidcmp(HDR(rep, unbroken_p)->prev_repl_uuid, hdrp->prev_repl_uuid); int next_differ = uuidcmp(HDR(rep, unbroken_p)->next_repl_uuid, hdrp->next_repl_uuid); if (prev_differ || next_differ) { ERR("different adjacent replica UUID between parts" " (repn %u, parts %u and %u);" " cannot synchronize", repn, unbroken_p, p); errno = EINVAL; return -1; } } /* check parts linkage */ LOG(4, "checking parts linkage in replica %u", repn); for (unsigned p = 0; p < rep->nhdrs; ++p) { /* skip broken parts */ if (replica_is_part_broken(repn, p, set_hs)) continue; struct pool_hdr *hdrp = HDR(rep, p); struct pool_hdr *next_hdrp = HDRN(rep, p); int next_is_broken = replica_is_part_broken(repn, p + 1, set_hs); if (!next_is_broken) { int next_decoupled = uuidcmp(next_hdrp->prev_part_uuid, hdrp->uuid) || uuidcmp(hdrp->next_part_uuid, next_hdrp->uuid); if (next_decoupled) { ERR("two consecutive unbroken parts are not" " linked to each other (repn %u, parts" " %u and %u); cannot synchronize", repn, p, p + 1); errno = EINVAL; return -1; } } } return 0; }
/* * fill_struct_broken_part_uuids -- (internal) set part uuids in pool_set * structure */ static int fill_struct_broken_part_uuids(struct pool_set *set, unsigned repn, struct poolset_health_status *set_hs, unsigned flags) { LOG(3, "set %p, repn %u, set_hs %p, flags %u", set, repn, set_hs, flags); struct pool_replica *rep = REP(set, repn); struct pool_hdr *hdrp; for (unsigned p = 0; p < rep->nparts; ++p) { /* skip unbroken parts */ if (!replica_is_part_broken(repn, p, set_hs)) continue; /* check if part was damaged or was added by transform */ if (replica_is_poolset_transformed(flags)) { /* generate new uuid for this part */ if (util_uuid_generate(rep->part[p].uuid) < 0) { ERR("cannot generate pool set part UUID"); errno = EINVAL; return -1; } continue; } if (!replica_is_part_broken(repn, p - 1, set_hs)) { /* try to get part uuid from the previous part */ hdrp = HDRP(rep, p); memcpy(rep->part[p].uuid, hdrp->next_part_uuid, POOL_HDR_UUID_LEN); } else if (!replica_is_part_broken(repn, p + 1, set_hs)) { /* try to get part uuid from the next part */ hdrp = HDRN(rep, p); memcpy(rep->part[p].uuid, hdrp->prev_part_uuid, POOL_HDR_UUID_LEN); } else if (p == 0 && !replica_is_part_broken(repn - 1, 0, set_hs)) { /* try to get part uuid from the previous replica */ hdrp = HDR(REPP(set, repn), 0); if (is_uuid_already_used(hdrp->next_repl_uuid, set, repn)) { ERR("repeated uuid - some replicas were created" " with a different poolset file"); errno = EINVAL; return -1; } memcpy(rep->part[p].uuid, hdrp->next_repl_uuid, POOL_HDR_UUID_LEN); } else if (p == 0 && !replica_is_part_broken(repn + 1, 0, set_hs)) { /* try to get part uuid from the next replica */ hdrp = HDR(REPN(set, repn), 0); if (is_uuid_already_used(hdrp->prev_repl_uuid, set, repn)) { ERR("repeated uuid - some replicas were created" " with a different poolset file"); errno = EINVAL; return -1; } memcpy(rep->part[p].uuid, hdrp->prev_repl_uuid, POOL_HDR_UUID_LEN); } else { /* generate new uuid for this part */ if (util_uuid_generate(rep->part[p].uuid) < 0) { ERR("cannot generate pool set part UUID"); errno = EINVAL; return -1; } } } return 0; }