/* * replica_check_poolset_health -- check if a given poolset can be considered as * healthy, and store the status in a helping structure */ int replica_check_poolset_health(struct pool_set *set, struct poolset_health_status **set_hsp, unsigned flags) { if (replica_create_poolset_health_status(set, set_hsp)) { LOG(1, "Creating poolset health status failed"); return -1; } struct poolset_health_status *set_hs = *set_hsp; /* check if part files exist, and if not - create them, and open them */ check_and_open_poolset_part_files(set, set_hs, flags); /* map all headers */ map_all_unbroken_headers(set, set_hs); /* check if checksums are correct for parts in all replicas */ check_checksums(set, set_hs); /* check if uuids in parts across each replica are consistent */ if (check_replicas_consistency(set, set_hs)) { LOG(1, "Replica consistency check failed"); goto err; } /* check poolset_uuid values between replicas */ if (check_poolset_uuids(set, set_hs)) { LOG(1, "Poolset uuids check failed"); goto err; } /* check if uuids for adjacent replicas are consistent */ if (check_uuids_between_replicas(set, set_hs)) { LOG(1, "Replica uuids check failed"); goto err; } if (check_store_all_sizes(set, set_hs)) { LOG(1, "Reading pool sizes failed"); goto err; } unmap_all_headers(set); util_poolset_fdclose(set); return 0; err: unmap_all_headers(set); util_poolset_fdclose(set); replica_free_poolset_health_status(set_hs); return -1; }
/* * replica_check_poolset_health -- check if a given poolset can be considered as * healthy, and store the status in a helping structure */ int replica_check_poolset_health(struct pool_set *set, struct poolset_health_status **set_hsp, unsigned flags) { LOG(3, "set %p, set_hsp %p, flags %u", set, set_hsp, flags); if (replica_create_poolset_health_status(set, set_hsp)) { LOG(1, "creating poolset health status failed"); return -1; } struct poolset_health_status *set_hs = *set_hsp; /* check if part files exist, and if not - create them, and open them */ check_and_open_poolset_part_files(set, set_hs, flags); /* map all headers */ map_all_unbroken_headers(set, set_hs); /* check if checksums are correct for parts in all replicas */ check_checksums(set, set_hs); /* check if option flags are consistent */ if (check_options(set, set_hs)) { LOG(1, "flags check failed"); goto err; } if (check_shutdown_state(set, set_hs)) { LOG(1, "replica shutdown_state check failed"); goto err; } /* check if uuids in parts across each replica are consistent */ if (check_replicas_consistency(set, set_hs)) { LOG(1, "replica consistency check failed"); goto err; } /* check poolset_uuid values between replicas */ if (check_poolset_uuids(set, set_hs)) { LOG(1, "poolset uuids check failed"); goto err; } /* check if uuids for adjacent replicas are consistent */ if (check_uuids_between_replicas(set, set_hs)) { LOG(1, "replica uuids check failed"); goto err; } /* check if healthy replicas make up another poolset */ if (check_replica_cycles(set, set_hs)) { LOG(1, "replica cycles check failed"); goto err; } /* check if replicas are large enough */ if (check_replica_sizes(set, set_hs)) { LOG(1, "replica sizes check failed"); goto err; } if (check_store_all_sizes(set, set_hs)) { LOG(1, "reading pool sizes failed"); goto err; } unmap_all_headers(set); util_poolset_fdclose_always(set); return 0; err: errno = EINVAL; unmap_all_headers(set); util_poolset_fdclose_always(set); replica_free_poolset_health_status(set_hs); return -1; }
/* * transform_replica -- transforming one poolset into another */ int replica_transform(struct pool_set *set_in, struct pool_set *set_out, unsigned flags) { LOG(3, "set_in %p, set_out %p", set_in, set_out); int ret = 0; /* validate user arguments */ if (validate_args(set_in, set_out)) return -1; /* check if the source poolset is healthy */ struct poolset_health_status *set_in_hs = NULL; if (replica_check_poolset_health(set_in, &set_in_hs, flags)) { ERR("source poolset health check failed"); return -1; } if (!replica_is_poolset_healthy(set_in_hs)) { ERR("source poolset is broken"); ret = -1; errno = EINVAL; goto free_hs_in; } struct poolset_health_status *set_out_hs = NULL; if (replica_create_poolset_health_status(set_out, &set_out_hs)) { ERR("creating poolset health status failed"); ret = -1; goto free_hs_in; } /* check if the poolsets are transformable */ struct poolset_compare_status *set_in_cs = NULL; struct poolset_compare_status *set_out_cs = NULL; if (compare_poolsets(set_in, set_out, &set_in_cs, &set_out_cs)) { ERR("comparing poolsets failed"); ret = -1; goto free_hs_out; } enum transform_op operation = identify_transform_operation(set_in_cs, set_out_cs, set_in_hs, set_out_hs); if (operation == NOT_TRANSFORMABLE) { LOG(1, "poolsets are not transformable"); ret = -1; errno = EINVAL; goto free_cs; } if (operation == RM_HDRS) { if (!is_dry_run(flags) && remove_hdrs(set_in, set_out, set_in_hs, flags)) { ERR("removing headers failed; falling back to the " "input poolset"); if (replica_sync(set_in, set_in_hs, flags | IS_TRANSFORMED)) { LOG(1, "falling back to the input poolset " "failed"); } else { LOG(1, "falling back to the input poolset " "succeeded"); } ret = -1; } goto free_cs; } if (operation == ADD_HDRS) { if (!is_dry_run(flags) && add_hdrs(set_in, set_out, set_in_hs, flags)) { ERR("adding headers failed; falling back to the " "input poolset"); if (replica_sync(set_in, set_in_hs, flags | IS_TRANSFORMED)) { LOG(1, "falling back to the input poolset " "failed"); } else { LOG(1, "falling back to the input poolset " "succeeded"); } ret = -1; } goto free_cs; } if (operation == ADD_REPLICAS) { /* * check if any of the parts that are to be added already exists */ if (do_added_parts_exist(set_out, set_out_hs)) { ERR("some parts being added already exist"); ret = -1; errno = EINVAL; goto free_cs; } } /* signal that sync is called by transform */ if (replica_sync(set_out, set_out_hs, flags | IS_TRANSFORMED)) { ret = -1; goto free_cs; } if (operation == RM_REPLICAS) { if (!is_dry_run(flags) && delete_replicas(set_in, set_in_cs)) ret = -1; } free_cs: Free(set_in_cs); Free(set_out_cs); free_hs_out: replica_free_poolset_health_status(set_out_hs); free_hs_in: replica_free_poolset_health_status(set_in_hs); return ret; }