/* * create_headers_for_broken_parts -- (internal) create headers for all new * parts created in place of the broken ones */ static int create_headers_for_broken_parts(struct pool_set *set, unsigned src_replica, struct poolset_health_status *set_hs) { struct pool_hdr *src_hdr = HDR(REP(set, src_replica), 0); for (unsigned r = 0; r < set_hs->nreplicas; ++r) { /* skip unbroken replicas */ if (!replica_is_replica_broken(r, set_hs)) continue; for (unsigned p = 0; p < set_hs->replica[r]->nparts; p++) { /* skip unbroken parts */ if (!replica_is_part_broken(r, p, set_hs)) continue; if (util_header_create(set, r, p, src_hdr->signature, src_hdr->major, src_hdr->compat_features, src_hdr->incompat_features, src_hdr->ro_compat_features, NULL, NULL, NULL) != 0) { LOG(1, "part headers create failed for" " replica %u part %u", r, p); errno = EINVAL; return -1; } } } return 0; }
/* * create_headers_for_broken_parts -- (internal) create headers for all new * parts created in place of the broken ones */ static int create_headers_for_broken_parts(struct pool_set *set, unsigned src_replica, struct poolset_health_status *set_hs) { LOG(3, "set %p, src_replica %u, set_hs %p", set, src_replica, set_hs); struct pool_hdr *src_hdr = HDR(REP(set, src_replica), 0); for (unsigned r = 0; r < set_hs->nreplicas; ++r) { /* skip unbroken replicas */ if (!replica_is_replica_broken(r, set_hs)) continue; for (unsigned p = 0; p < set_hs->replica[r]->nhdrs; p++) { /* skip unbroken parts */ if (!replica_is_part_broken(r, p, set_hs)) continue; struct pool_attr attr; util_pool_hdr2attr(&attr, src_hdr); if (util_header_create(set, r, p, &attr, 0) != 0) { LOG(1, "part headers create failed for" " replica %u part %u", r, p); errno = EINVAL; return -1; } } } return 0; }
/* * create_missing_headers -- (internal) create headers for all parts but the * first one */ static int create_missing_headers(struct pool_set *set, unsigned repn) { LOG(3, "set %p, repn %u", set, repn); struct pool_hdr *src_hdr = HDR(REP(set, repn), 0); for (unsigned p = 1; p < set->replica[repn]->nhdrs; ++p) { struct pool_attr attr; util_pool_hdr2attr(&attr, src_hdr); attr.incompat_features &= (uint32_t)(~POOL_FEAT_SINGLEHDR); if (util_header_create(set, repn, p, &attr, 1) != 0) { LOG(1, "part headers create failed for" " replica %u part %u", repn, p); errno = EINVAL; return -1; } } return 0; }
/* * util_replica_create -- (internal) create a new memory pool replica */ static int util_replica_create(struct pool_set *set, unsigned repidx, int flags, size_t hdrsize, const char *sig, uint32_t major, uint32_t compat, uint32_t incompat, uint32_t ro_compat) { LOG(3, "set %p repidx %u flags %d hdrsize %zu sig %s major %u " "compat %#x incompat %#x ro_comapt %#x", set, repidx, flags, hdrsize, sig, major, compat, incompat, ro_compat); struct pool_replica *rep = set->replica[repidx]; rep->repsize -= (rep->nparts - 1) * hdrsize; /* determine a hint address for mmap() */ void *addr = util_map_hint(rep->repsize); /* XXX - randomize */ if (addr == NULL) { ERR("cannot find a contiguous region of given size"); return -1; } /* map the first part and reserve space for remaining parts */ if (util_map_part(&rep->part[0], addr, rep->repsize, 0, flags) != 0) { LOG(2, "pool mapping failed - part #0"); return -1; } VALGRIND_REGISTER_PMEM_MAPPING(rep->part[0].addr, rep->part[0].size); VALGRIND_REGISTER_PMEM_FILE(rep->part[0].fd, rep->part[0].addr, rep->part[0].size, 0); /* map all headers - don't care about the address */ for (unsigned p = 0; p < rep->nparts; p++) { if (util_map_hdr(&rep->part[p], hdrsize, 0, flags) != 0) { LOG(2, "header mapping failed - part #%d", p); goto err; } } /* create headers, set UUID's */ for (unsigned p = 0; p < rep->nparts; p++) { if (util_header_create(set, repidx, p, hdrsize, sig, major, compat, incompat, ro_compat) != 0) { LOG(2, "header creation failed - part #%d", p); goto err; } } /* unmap all headers */ for (unsigned p = 0; p < rep->nparts; p++) util_unmap_hdr(&rep->part[p]); set->zeroed &= rep->part[0].created; size_t mapsize = rep->part[0].filesize & ~(Pagesize - 1); addr = (char *)rep->part[0].addr + mapsize; /* * map the remaining parts of the usable pool space (4K-aligned) */ for (unsigned p = 1; p < rep->nparts; p++) { /* map data part */ if (util_map_part(&rep->part[p], addr, 0, hdrsize, flags | MAP_FIXED) != 0) { LOG(2, "usable space mapping failed - part #%d", p); goto err; } VALGRIND_REGISTER_PMEM_FILE(rep->part[p].fd, rep->part[p].addr, rep->part[p].size, hdrsize); mapsize += rep->part[p].size; set->zeroed &= rep->part[p].created; addr = (char *)addr + rep->part[p].size; } rep->is_pmem = pmem_is_pmem(rep->part[0].addr, rep->part[0].size); ASSERTeq(mapsize, rep->repsize); /* calculate pool size - choose the smallest replica size */ if (rep->repsize < set->poolsize) set->poolsize = rep->repsize; LOG(3, "replica addr %p", rep->part[0].addr); return 0; err: LOG(4, "error clean up"); int oerrno = errno; for (unsigned p = 0; p < rep->nparts; p++) util_unmap_hdr(&rep->part[p]); util_unmap_part(&rep->part[0]); errno = oerrno; return -1; }
/* * util_replica_create -- (internal) create a new memory pool replica */ static int util_replica_create(struct pool_set *set, unsigned repidx, int flags, const char *sig, uint32_t major, uint32_t compat, uint32_t incompat, uint32_t ro_compat, const unsigned char *prev_repl_uuid, const unsigned char *next_repl_uuid, const unsigned char *arch_flags) { LOG(3, "set %p repidx %u flags %d sig %.8s major %u " "compat %#x incompat %#x ro_comapt %#x" "prev_repl_uuid %p next_repl_uuid %p arch_flags %p", set, repidx, flags, sig, major, compat, incompat, ro_compat, prev_repl_uuid, next_repl_uuid, arch_flags); struct pool_replica *rep = set->replica[repidx]; /* determine a hint address for mmap() */ void *addr = util_map_hint(rep->repsize, 0); if (addr == MAP_FAILED) { ERR("cannot find a contiguous region of given size"); return -1; } /* map the first part and reserve space for remaining parts */ /* XXX investigate this idea of reserving space on Windows */ if (util_map_part(&rep->part[0], addr, rep->repsize, 0, flags) != 0) { LOG(2, "pool mapping failed - part #0"); return -1; } VALGRIND_REGISTER_PMEM_MAPPING(rep->part[0].addr, rep->part[0].size); VALGRIND_REGISTER_PMEM_FILE(rep->part[0].fd, rep->part[0].addr, rep->part[0].size, 0); /* map all headers - don't care about the address */ for (unsigned p = 0; p < rep->nparts; p++) { if (util_map_hdr(&rep->part[p], flags) != 0) { LOG(2, "header mapping failed - part #%d", p); goto err; } } /* create headers, set UUID's */ for (unsigned p = 0; p < rep->nparts; p++) { if (util_header_create(set, repidx, p, sig, major, compat, incompat, ro_compat, prev_repl_uuid, next_repl_uuid, arch_flags) != 0) { LOG(2, "header creation failed - part #%d", p); goto err; } } /* unmap all headers */ for (unsigned p = 0; p < rep->nparts; p++) util_unmap_hdr(&rep->part[p]); set->zeroed &= rep->part[0].created; size_t mapsize = rep->part[0].filesize & ~(Pagesize - 1); addr = (char *)rep->part[0].addr + mapsize; /* * map the remaining parts of the usable pool space (4K-aligned) */ for (unsigned p = 1; p < rep->nparts; p++) { /* map data part */ if (util_map_part(&rep->part[p], addr, 0, POOL_HDR_SIZE, flags | MAP_FIXED) != 0) { LOG(2, "usable space mapping failed - part #%d", p); goto err; } VALGRIND_REGISTER_PMEM_FILE(rep->part[p].fd, rep->part[p].addr, rep->part[p].size, POOL_HDR_SIZE); mapsize += rep->part[p].size; set->zeroed &= rep->part[p].created; addr = (char *)addr + rep->part[p].size; } rep->is_pmem = pmem_is_pmem(rep->part[0].addr, rep->part[0].size); ASSERTeq(mapsize, rep->repsize); LOG(3, "replica addr %p", rep->part[0].addr); return 0; err: LOG(4, "error clean up"); int oerrno = errno; for (unsigned p = 0; p < rep->nparts; p++) util_unmap_hdr(&rep->part[p]); util_unmap_part(&rep->part[0]); errno = oerrno; return -1; }