/* * update_replicas_linkage -- (internal) update uuids linking replicas */ static int update_replicas_linkage(struct pool_set *set, unsigned repn) { LOG(3, "set %p, repn %u", set, repn); struct pool_replica *rep = REP(set, repn); struct pool_replica *prev_r = REPP(set, repn); struct pool_replica *next_r = REPN(set, repn); ASSERT(rep->nparts > 0); ASSERT(prev_r->nparts > 0); ASSERT(next_r->nparts > 0); /* set uuids in the current replica */ for (unsigned p = 0; p < rep->nhdrs; ++p) { struct pool_hdr *hdrp = HDR(rep, p); memcpy(hdrp->prev_repl_uuid, PART(prev_r, 0).uuid, POOL_HDR_UUID_LEN); memcpy(hdrp->next_repl_uuid, PART(next_r, 0).uuid, POOL_HDR_UUID_LEN); util_checksum(hdrp, sizeof(*hdrp), &hdrp->checksum, 1, POOL_HDR_CSUM_END_OFF); /* store pool's header */ util_persist(PART(rep, p).is_dev_dax, hdrp, sizeof(*hdrp)); } /* set uuids in the previous replica */ for (unsigned p = 0; p < prev_r->nhdrs; ++p) { struct pool_hdr *prev_hdrp = HDR(prev_r, p); memcpy(prev_hdrp->next_repl_uuid, PART(rep, 0).uuid, POOL_HDR_UUID_LEN); util_checksum(prev_hdrp, sizeof(*prev_hdrp), &prev_hdrp->checksum, 1, POOL_HDR_CSUM_END_OFF); /* store pool's header */ util_persist(PART(prev_r, p).is_dev_dax, prev_hdrp, sizeof(*prev_hdrp)); } /* set uuids in the next replica */ for (unsigned p = 0; p < next_r->nhdrs; ++p) { struct pool_hdr *next_hdrp = HDR(next_r, p); memcpy(next_hdrp->prev_repl_uuid, PART(rep, 0).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(next_r, p).is_dev_dax, next_hdrp, sizeof(*next_hdrp)); } return 0; }
/* * check_uuids_between_replicas -- (internal) check if uuids between internally * consistent adjacent replicas are consistent */ static int check_uuids_between_replicas(struct pool_set *set, struct poolset_health_status *set_hs) { LOG(3, "set %p, set_hs %p", set, set_hs); for (unsigned r = 0; r < set->nreplicas; ++r) { /* skip comparing inconsistent pairs of replicas */ if (!replica_is_replica_consistent(r, set_hs) || !replica_is_replica_consistent(r + 1, set_hs)) continue; struct pool_replica *rep = REP(set, r); struct pool_replica *rep_n = REPN(set, r); /* get uuids of the two adjacent replicas */ uuid_t *rep_uuidp = NULL; uuid_t *rep_n_uuidp = NULL; unsigned r_n = REPNidx(set_hs, r); if (get_replica_uuid(rep, r, set_hs, &rep_uuidp)) LOG(2, "cannot get replica uuid, replica %u", r); if (get_replica_uuid(rep_n, r_n, set_hs, &rep_n_uuidp)) LOG(2, "cannot get replica uuid, replica %u", r_n); /* * check if replica uuids are consistent between two adjacent * replicas */ unsigned p = replica_find_unbroken_part(r, set_hs); unsigned p_n = replica_find_unbroken_part(r_n, set_hs); if (p_n != UNDEF_PART && rep_uuidp != NULL && uuidcmp(*rep_uuidp, HDR(rep_n, p_n)->prev_repl_uuid)) { ERR( "inconsistent replica uuids between replicas %u and %u", r, r_n); return -1; } if (p != UNDEF_PART && rep_n_uuidp != NULL && uuidcmp(*rep_n_uuidp, HDR(rep, p)->next_repl_uuid)) { ERR( "inconsistent replica uuids between replicas %u and %u", r, r_n); return -1; } /* * check if replica uuids on borders of a broken replica are * consistent */ unsigned r_nn = REPNidx(set_hs, r_n); if (set->nreplicas > 1 && p != UNDEF_PART && replica_is_replica_broken(r_n, set_hs) && replica_is_replica_consistent(r_nn, set_hs)) { unsigned p_nn = replica_find_unbroken_part(r_nn, set_hs); if (p_nn == UNDEF_PART) { LOG(2, "cannot compare uuids on borders of replica %u", r); continue; } struct pool_replica *rep_nn = REP(set, r_nn); if (uuidcmp(HDR(rep, p)->next_repl_uuid, HDR(rep_nn, p_nn)->prev_repl_uuid)) { ERR( "inconsistent replica uuids on borders of replica %u", r); 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; }