/* * sync_replica -- synchronize data across replicas within a poolset */ int replica_sync(struct pool_set *set, struct poolset_health_status *s_hs, unsigned flags) { LOG(3, "set %p, flags %u", set, flags); int ret = 0; struct poolset_health_status *set_hs = NULL; /* check if we already know the poolset health status */ if (s_hs == NULL) { /* validate poolset before checking its health */ if (validate_args(set)) return -1; /* examine poolset's health */ if (replica_check_poolset_health(set, &set_hs, flags)) { ERR("poolset health check failed"); return -1; } /* check if poolset is broken; if not, nothing to do */ if (replica_is_poolset_healthy(set_hs)) { LOG(1, "Poolset is healthy"); goto out; } } else { set_hs = s_hs; } /* find one good replica; it will be the source of data */ unsigned healthy_replica = replica_find_healthy_replica(set_hs); if (healthy_replica == UNDEF_REPLICA) { ERR("no healthy replica found"); ret = -1; goto out; } /* in dry-run mode we can stop here */ if (is_dry_run(flags)) { LOG(1, "Sync in dry-run mode finished successfully"); goto out; } /* recreate broken parts */ if (recreate_broken_parts(set, set_hs, flags)) { ERR("recreating broken parts failed"); ret = -1; goto out; } /* open all part files */ if (replica_open_poolset_part_files(set)) { ERR("opening poolset part files failed"); ret = -1; goto out; } /* map all replicas */ if (util_poolset_open(set)) { ERR("opening poolset failed"); ret = -1; goto out; } /* this is required for opening remote pools */ set->poolsize = set_hs->replica[healthy_replica]->pool_size; /* open all remote replicas */ if (open_remote_replicas(set, set_hs)) { ERR("opening remote replicas failed"); ret = -1; goto out; } /* update uuid fields in the set structure with part headers */ if (fill_struct_uuids(set, healthy_replica, set_hs, flags)) { ERR("gathering uuids failed"); ret = -1; goto out; } /* create headers for broken parts */ if (!is_dry_run(flags)) { if (create_headers_for_broken_parts(set, healthy_replica, set_hs)) { ERR("creating headers for broken parts failed"); ret = -1; goto out; } } if (is_dry_run(flags)) goto out; /* create all remote replicas */ if (create_remote_replicas(set, set_hs, flags)) { ERR("creating remote replicas failed"); ret = -1; goto out; } /* check and copy data if possible */ if (copy_data_to_broken_parts(set, healthy_replica, flags, set_hs)) { ERR("copying data to broken parts failed"); ret = -1; goto out; } /* update uuids of replicas and parts */ if (update_uuids(set, set_hs)) { ERR("updating uuids failed"); ret = -1; goto out; } /* grant permissions to all created parts */ if (grant_created_parts_perm(set, healthy_replica, set_hs)) { ERR("granting permissions to created parts failed"); ret = -1; } out: if (s_hs == NULL) replica_free_poolset_health_status(set_hs); return ret; }
/* * sync_replica -- synchronize data across replicas within a poolset */ int sync_replica(struct pool_set *set, unsigned flags) { ASSERTne(set, NULL); /* examine poolset's health */ struct poolset_health_status *set_hs = NULL; if (replica_check_poolset_health(set, &set_hs, flags)) { ERR("poolset health check failed"); return -1; } /* check if poolset is broken; if not, nothing to do */ if (replica_is_poolset_healthy(set_hs)) { LOG(1, "Poolset is healthy"); goto OK_close; } /* find one good replica; it will be the source of data */ unsigned healthy_replica = replica_find_healthy_replica(set_hs); if (healthy_replica == UNDEF_REPLICA) { ERR("no healthy replica found"); goto err; } /* in dry-run mode we can stop here */ if (is_dry_run(flags)) { LOG(1, "Sync in dry-run mode finished successfully"); goto OK_close; } /* recreate broken parts */ if (recreate_broken_parts(set, set_hs, flags)) { ERR("recreating broken parts failed"); goto err; } /* open all part files */ if (replica_open_poolset_part_files(set)) { ERR("opening poolset part files failed"); goto err; } /* map all replicas */ if (util_poolset_open(set)) { ERR("opening poolset failed"); goto err; } /* this is required for opening remote pools */ set->poolsize = set_hs->replica[healthy_replica]->pool_size; /* open all remote replicas */ if (open_remote_replicas(set, set_hs)) { ERR("opening remote replicas failed"); goto err; } /* update uuid fields in the set structure with part headers */ if (fill_struct_uuids(set, healthy_replica, set_hs, flags)) { ERR("gathering uuids failed"); goto err; } /* create headers for broken parts */ if (!is_dry_run(flags)) { if (create_headers_for_broken_parts(set, healthy_replica, set_hs)) { ERR("creating headers for broken parts failed"); goto err; } } if (is_dry_run(flags)) goto OK_close; /* update uuids of replicas and parts */ update_uuids(set, set_hs); /* create all remote replicas */ if (create_remote_replicas(set, set_hs)) { ERR("creating remote replicas failed"); goto err; } /* check and copy data if possible */ if (copy_data_to_broken_parts(set, healthy_replica, flags, set_hs)) { ERR("copying data to broken parts failed"); goto err; } /* grant permissions to all created parts */ if (grant_broken_parts_perm(set, healthy_replica, set_hs)) { ERR("granting permissions to broken parts failed"); goto err; } OK_close: replica_free_poolset_health_status(set_hs); return 0; err: replica_free_poolset_health_status(set_hs); return -1; }
/* * add_hdrs_replica -- (internal) add lacking headers to the replica * * when the operation fails and returns -1, the replica remains untouched */ static int add_hdrs_replica(struct pool_set *set_in, struct pool_set *set_out, unsigned repn) { LOG(3, "set %p, repn %u", set_in, repn); int ret = 0; /* open all part files of the input replica */ if (replica_open_replica_part_files(set_in, repn)) { LOG(1, "opening replica %u, part files failed", repn); ret = -1; goto out; } /* share part file descriptors between poolset structures */ copy_part_fds(set_out, set_in); /* map the whole input replica */ if (util_replica_open(set_in, repn, MAP_SHARED)) { LOG(1, "opening input replica failed: replica %u", repn); ret = -1; goto out_close; } /* map the whole output replica */ if (util_replica_open(set_out, repn, MAP_SHARED)) { LOG(1, "opening output replica failed: replica %u", repn); ret = -1; goto out_unmap_in; } /* generate new uuids for lacking headers */ if (fill_replica_struct_uuids(set_out, repn)) { LOG(1, "generating lacking uuids for parts failed: replica %u", repn); ret = -1; goto out_unmap_out; } /* copy data between the two mappings of the replica */ if (REP(set_in, repn)->nparts > 1) copy_replica_data_bw(set_out, set_in, repn); /* create the missing headers */ if (create_missing_headers(set_out, repn)) { LOG(1, "creating lacking headers failed: replica %u", repn); /* * copy the data back, so we could fall back to the original * state */ if (REP(set_in, repn)->nparts > 1) copy_replica_data_fw(set_in, set_out, repn); ret = -1; goto out_unmap_out; } /* make changes to the first part's header */ update_replica_header(set_out, repn); /* store new uuids in all headers and update linkage in the replica */ update_uuids(set_out, repn); out_unmap_out: util_replica_close(set_out, repn); out_unmap_in: util_replica_close(set_in, repn); out_close: util_replica_fdclose(REP(set_in, repn)); out: return ret; }