/* * replica_get_part_range_data_len -- get data length in given range */ size_t replica_get_part_range_data_len(struct pool_set *set, unsigned repn, unsigned pstart, unsigned pend) { size_t len = 0; for (unsigned p = pstart; p < pend; ++p) len += replica_get_part_data_len(set, repn, p); return len; }
/* * replica_get_part_range_data_len -- get data length in given range */ size_t replica_get_part_range_data_len(struct pool_set *set, unsigned repn, unsigned pstart, unsigned pend) { LOG(3, "set %p, repn %u, pstart %u, pend %u", set, repn, pstart, pend); size_t len = 0; for (unsigned p = pstart; p < pend; ++p) len += replica_get_part_data_len(set, repn, p); return len; }
/* * copy_data_to_broken_parts -- (internal) copy data to all parts created * in place of the broken ones */ static int copy_data_to_broken_parts(struct pool_set *set, unsigned healthy_replica, unsigned flags, struct poolset_health_status *set_hs) { size_t poolsize = replica_get_pool_size(set, healthy_replica); for (unsigned r = 0; r < set_hs->nreplicas; ++r) { /* skip unbroken and consistent replicas */ if (replica_is_replica_healthy(r, set_hs)) continue; struct pool_replica *rep = REP(set, r); struct pool_replica *rep_h = REP(set, healthy_replica); for (unsigned p = 0; p < rep->nparts; ++p) { /* skip unbroken parts from consistent replicas */ if (!replica_is_part_broken(r, p, set_hs) && replica_is_replica_consistent(r, set_hs)) continue; const struct pool_set_part *part = &rep->part[p]; size_t off = replica_get_part_data_offset(set, r, p); size_t len = replica_get_part_data_len(set, r, p); /* do not allow copying too much data */ if (off >= poolsize) continue; if (off + len > poolsize) len = poolsize - off; void *src_addr = ADDR_SUM(rep_h->part[0].addr, off); /* First part of replica is mapped with header */ size_t fpoff = (p == 0) ? POOL_HDR_SIZE : 0; /* copy all data */ if (!is_dry_run(flags)) { memcpy(ADDR_SUM(part->addr, fpoff), src_addr, len); pmem_msync(ADDR_SUM(part->addr, fpoff), len); } } } return 0; }
/* * copy_replica_data_bw -- (internal) copy data between replicas of two * poolsets, starting from the end of the pool */ static void copy_replica_data_bw(struct pool_set *set_dst, struct pool_set *set_src, unsigned repn) { LOG(3, "set_in %p, set_out %p, repn %u", set_src, set_dst, repn); ssize_t pool_size = replica_get_pool_size(set_src, repn); if (pool_size < 0) { LOG(1, "getting pool size from replica %u failed", repn); pool_size = (ssize_t)set_src->poolsize; } size_t len = (size_t)pool_size - POOL_HDR_SIZE - replica_get_part_data_len(set_src, repn, 0); size_t count = len / POOL_HDR_SIZE; void *src = ADDR_SUM(PART(REP(set_src, repn), 1)->addr, len); void *dst = ADDR_SUM(PART(REP(set_dst, repn), 1)->addr, len); while (count-- > 0) { src = ADDR_SUM(src, -(ssize_t)POOL_HDR_SIZE); dst = ADDR_SUM(dst, -(ssize_t)POOL_HDR_SIZE); pmem_memcpy_persist(dst, src, POOL_HDR_SIZE); } }
/* * copy_data_to_broken_parts -- (internal) copy data to all parts created * in place of the broken ones */ static int copy_data_to_broken_parts(struct pool_set *set, unsigned healthy_replica, unsigned flags, struct poolset_health_status *set_hs) { /* get pool size from healthy replica */ size_t poolsize = set->poolsize; for (unsigned r = 0; r < set_hs->nreplicas; ++r) { /* skip unbroken and consistent replicas */ if (replica_is_replica_healthy(r, set_hs)) continue; struct pool_replica *rep = REP(set, r); struct pool_replica *rep_h = REP(set, healthy_replica); for (unsigned p = 0; p < rep->nparts; ++p) { /* skip unbroken parts from consistent replicas */ if (!replica_is_part_broken(r, p, set_hs) && replica_is_replica_consistent(r, set_hs)) continue; const struct pool_set_part *part = &rep->part[p]; size_t off = replica_get_part_data_offset(set, r, p); size_t len = replica_get_part_data_len(set, r, p); if (rep->remote) len = poolsize - off; /* do not allow copying too much data */ if (off >= poolsize) continue; /* * First part of replica is mapped * with header */ size_t fpoff = (p == 0) ? POOL_HDR_SIZE : 0; void *dst_addr = ADDR_SUM(part->addr, fpoff); if (rep->remote) { int ret = Rpmem_persist(rep->remote->rpp, off - POOL_HDR_SIZE, len, 0); if (ret) { LOG(1, "Copying data to remote node " "failed -- '%s' on '%s'", rep->remote->pool_desc, rep->remote->node_addr); return -1; } } else if (rep_h->remote) { int ret = Rpmem_read(rep_h->remote->rpp, dst_addr, off - POOL_HDR_SIZE, len); if (ret) { LOG(1, "Reading data from remote node " "failed -- '%s' on '%s'", rep_h->remote->pool_desc, rep_h->remote->node_addr); return -1; } } else { if (off + len > poolsize) len = poolsize - off; void *src_addr = ADDR_SUM(rep_h->part[0].addr, off); /* copy all data */ memcpy(dst_addr, src_addr, len); pmem_msync(dst_addr, len); } } } return 0; }