/* * util_file_pread -- reads from a file with an offset */ ssize_t util_file_pread(const char *path, void *buffer, size_t size, off_t offset) { if (!util_file_is_device_dax(path)) { int fd = util_file_open(path, NULL, 0, O_RDONLY); if (fd < 0) return -1; ssize_t read_len = pread(fd, buffer, size, offset); int olderrno = errno; (void) close(fd); errno = olderrno; return read_len; } ssize_t file_size = util_file_get_size(path); if (file_size < 0) return -1; size_t max_size = (size_t)(file_size - offset); if (size > max_size) { LOG(1, "Requested size of read goes beyond the mapped memory"); size = max_size; } void *addr = util_file_map_whole(path); if (addr == NULL) return -1; memcpy(buffer, ADDR_SUM(addr, offset), size); util_unmap(addr, (size_t)file_size); return (ssize_t)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) { 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); } }
/* * util_file_pread -- reads from a file with an offset */ ssize_t util_file_pread(const char *path, void *buffer, size_t size, os_off_t offset) { LOG(3, "path \"%s\" buffer %p size %zu offset %ju", path, buffer, size, offset); enum file_type type = util_file_get_type(path); if (type < 0) return -1; if (type == TYPE_NORMAL) { int fd = util_file_open(path, NULL, 0, O_RDONLY); if (fd < 0) { LOG(2, "failed to open file \"%s\"", path); return -1; } ssize_t read_len = pread(fd, buffer, size, offset); int olderrno = errno; (void) os_close(fd); errno = olderrno; return read_len; } ssize_t file_size = util_file_get_size(path); if (file_size < 0) { LOG(2, "cannot determine file length \"%s\"", path); return -1; } size_t max_size = (size_t)(file_size - offset); if (size > max_size) { LOG(2, "requested size of read goes beyond the file length, " "%zu > %zu", size, max_size); LOG(4, "adjusting size to %zu", max_size); size = max_size; } void *addr = util_file_map_whole(path); if (addr == NULL) { LOG(2, "failed to map entire file \"%s\"", path); return -1; } memcpy(buffer, ADDR_SUM(addr, offset), size); util_unmap(addr, (size_t)file_size); return (ssize_t)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; }