/* * 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) { 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 next part */ hdrp = HDR(rep, p + 1); memcpy(rep->part[p].uuid, hdrp->prev_part_uuid, POOL_HDR_UUID_LEN); } else if (!replica_is_part_broken(repn, p - 1, set_hs)) { /* try to get part uuid from the previous part */ hdrp = HDR(rep, p - 1); memcpy(rep->part[p].uuid, hdrp->next_part_uuid, POOL_HDR_UUID_LEN); } else if (p == 0 && replica_find_unbroken_part(repn + 1, set_hs) == 0) { /* try to get part uuid from the next replica */ hdrp = HDR(REP(set, repn + 1), 0); memcpy(rep->part[p].uuid, hdrp->prev_repl_uuid, POOL_HDR_UUID_LEN); } else if (p == 0 && replica_find_unbroken_part(repn - 1, set_hs) == 0) { /* try to get part uuid from the previous replica */ hdrp = HDR(REP(set, repn - 1), 0); memcpy(rep->part[p].uuid, hdrp->next_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; }
/* * pool_hdr_uuid_fix -- (internal) fix UUID value */ static int pool_hdr_uuid_fix(PMEMpoolcheck *ppc, location *loc, uint32_t question, void *context) { LOG(3, NULL); ASSERTne(loc, NULL); switch (question) { case Q_UUID_SET: CHECK_INFO(ppc, "%ssetting pool_hdr.uuid to %s", loc->prefix, check_get_uuid_str(*loc->valid_uuid)); memcpy(loc->hdr.uuid, loc->valid_uuid, POOL_HDR_UUID_LEN); break; case Q_UUID_REGENERATE: if (util_uuid_generate(loc->hdr.uuid) != 0) { ppc->result = CHECK_RESULT_INTERNAL_ERROR; return CHECK_ERR(ppc, "%suuid generation failed", loc->prefix); } CHECK_INFO(ppc, "%ssetting pool_hdr.uuid to %s", loc->prefix, check_get_uuid_str(loc->hdr.uuid)); break; default: ERR("not implemented question id: %u", question); } return 0; }
/* * fill_replica_struct_uuids -- (internal) gather all uuids required for the * replica in the helper structure */ static int fill_replica_struct_uuids(struct pool_set *set, unsigned repn) { LOG(3, "set %p, repn %u", set, repn); struct pool_replica *rep = REP(set, repn); memcpy(PART(rep, 0)->uuid, HDR(rep, 0)->uuid, POOL_HDR_UUID_LEN); for (unsigned p = 1; p < rep->nhdrs; ++p) { if (util_uuid_generate(rep->part[p].uuid) < 0) { ERR("cannot generate part UUID"); errno = EINVAL; return -1; } } return 0; }
/* * util_pool_create_uuids -- create a new memory pool (set or a single file) * with given uuids * * On success returns 0 and a pointer to a newly allocated structure * containing the info of all the parts of the pool set and replicas. */ int util_pool_create_uuids(struct pool_set **setp, const char *path, size_t poolsize, size_t minsize, const char *sig, uint32_t major, uint32_t compat, uint32_t incompat, uint32_t ro_compat, const unsigned char *poolset_uuid, const unsigned char *first_part_uuid, const unsigned char *prev_repl_uuid, const unsigned char *next_repl_uuid, const unsigned char *arch_flags) { LOG(3, "setp %p path %s poolsize %zu minsize %zu " "sig %.8s major %u compat %#x incompat %#x ro_comapt %#x " "poolset_uuid %p first_part_uuid %p" "prev_repl_uuid %p next_repl_uuid %p arch_flags %p", setp, path, poolsize, minsize, sig, major, compat, incompat, ro_compat, poolset_uuid, first_part_uuid, prev_repl_uuid, next_repl_uuid, arch_flags); int flags = MAP_SHARED; int ret = util_poolset_create(setp, path, poolsize, minsize); if (ret < 0) { LOG(2, "cannot create pool set"); return -1; } struct pool_set *set = *setp; ASSERT(set->nreplicas > 0); set->zeroed = 1; if (poolset_uuid) { memcpy(set->uuid, poolset_uuid, POOL_HDR_UUID_LEN); } else { /* generate pool set UUID */ ret = util_uuid_generate(set->uuid); if (ret < 0) { LOG(2, "cannot generate pool set UUID"); util_poolset_close(*setp, 1); return -1; } } /* generate UUID's for all the parts */ for (unsigned r = 0; r < set->nreplicas; r++) { struct pool_replica *rep = set->replica[r]; for (unsigned i = 0; i < rep->nparts; i++) { ret = util_uuid_generate(rep->part[i].uuid); if (ret < 0) { LOG(2, "cannot generate pool set part UUID"); util_poolset_close(*setp, 1); return -1; } } } /* overwrite UUID of the first part if given */ if (first_part_uuid) { memcpy(set->replica[0]->part[0].uuid, first_part_uuid, POOL_HDR_UUID_LEN); } if (set->nreplicas == 1 && prev_repl_uuid && next_repl_uuid) { if (util_replica_create(set, 0, flags, sig, major, compat, incompat, ro_compat, prev_repl_uuid, next_repl_uuid, arch_flags) != 0) { LOG(2, "replica creation failed"); goto err; } } else { for (unsigned r = 0; r < set->nreplicas; r++) { if (util_replica_create(set, r, flags, sig, major, compat, incompat, ro_compat, NULL, NULL, NULL) != 0) { LOG(2, "replica creation failed"); goto err; } } } return 0; err: LOG(4, "error clean up"); int oerrno = errno; for (unsigned r = 0; r < set->nreplicas; r++) util_replica_close(set, r); util_poolset_close(set, 1); errno = oerrno; return -1; }
/* * 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; }
int main(int argc, char *argv[]) { START(argc, argv, "util_uuid_generate"); uuid_t uuid; uuid_t uuid1; int ret; char conv_uu[POOL_HDR_UUID_STR_LEN]; char uu[POOL_HDR_UUID_STR_LEN]; /* * No string passed in. Generate uuid. */ if (argc == 1) { /* generate a UUID string */ ret = ut_get_uuid_str(uu); UT_ASSERTeq(ret, 0); /* * Convert the the string to a uuid, convert generated * uuid back to a string and compare strings. */ ret = util_uuid_from_string(uu, (struct uuid *)&uuid); UT_ASSERTeq(ret, 0); ret = util_uuid_to_string(uuid, conv_uu); UT_ASSERTeq(ret, 0); UT_ASSERT(strncmp(uu, conv_uu, POOL_HDR_UUID_STR_LEN) == 0); /* * Generate uuid from util_uuid_generate and translate to * string then back to uuid to verify they match. */ memset(uuid, 0, sizeof(uuid_t)); memset(uu, 0, POOL_HDR_UUID_STR_LEN); memset(conv_uu, 0, POOL_HDR_UUID_STR_LEN); ret = util_uuid_generate(uuid); UT_ASSERTeq(ret, 0); ret = util_uuid_to_string(uuid, uu); UT_ASSERTeq(ret, 0); ret = util_uuid_from_string(uu, (struct uuid *)&uuid1); UT_ASSERTeq(ret, 0); UT_ASSERT(memcmp(&uuid, &uuid1, sizeof(uuid_t)) == 0); } else { /* * Caller passed in string. */ if (strcmp(argv[2], "valid") == 0) { ret = util_uuid_from_string(argv[1], (struct uuid *)&uuid); UT_ASSERTeq(ret, 0); ret = util_uuid_to_string(uuid, conv_uu); UT_ASSERTeq(ret, 0); } else { ret = util_uuid_from_string(argv[1], (struct uuid *)&uuid); UT_ASSERT(ret < 0); UT_OUT("util_uuid_generate: invalid uuid string"); } } DONE(NULL); }