Exemple #1
0
/*
 * 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;
}
Exemple #2
0
/*
 * 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)) {
		LOG(1, "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) {
		LOG(1, "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)) {
		LOG(1, "Recreating broken parts failed");
		goto err;
	}

	/* open all part files */
	if (replica_open_poolset_part_files(set)) {
		LOG(1, "Opening poolset part files failed");
		goto err;
	}

	/* map all replicas */
	if (util_poolset_open(set)) {
		LOG(1, "Opening poolset failed");
		goto err;
	}

	/* update uuid fields in the set structure with part headers */
	if (fill_struct_uuids(set, healthy_replica, set_hs, flags)) {
		LOG(1, "Gathering uuids failed");
		goto err;
	}

	/* check and copy data if possible */
	if (copy_data_to_broken_parts(set, healthy_replica, flags, set_hs)) {
		LOG(1, "Copying data to broken parts failed");
		goto err;
	}

	/* create headers for broken parts */
	if (!is_dry_run(flags)) {
		if (create_headers_for_broken_parts(set, healthy_replica,
				set_hs)) {
			LOG(1, "Creating headers for broken parts failed");
			goto err;
		}
	}

	/* grant permissions to all created parts */
	if (grant_broken_parts_perm(set, healthy_replica, set_hs)) {
		LOG(1, "Granting permissions to broken parts failed");
		goto err;
	}

	/* update uuids of replicas and parts */
	if (!is_dry_run(flags))
		update_uuids(set, set_hs);

OK_close:
	replica_free_poolset_health_status(set_hs);
	return 0;

err:
	replica_free_poolset_health_status(set_hs);
	return -1;
}
Exemple #3
0
/*
 * 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;
}
Exemple #4
0
/*
 * pmempool_transform -- alter poolset structure
 */
int
pmempool_transform(const char *poolset_file_src,
		const char *poolset_file_dst, unsigned flags)
{
	ASSERTne(poolset_file_src, NULL);
	ASSERTne(poolset_file_dst, NULL);

	/* check if the source poolset has correct signature */
	if (util_is_poolset_file(poolset_file_src) != 1) {
		ERR("source file is not a poolset file");
		goto err;
	}

	/* check if the destination poolset has correct signature */
	if (util_is_poolset_file(poolset_file_dst) != 1) {
		ERR("destination file is not a poolset file");
		goto err;
	}

	/* open the source poolset file */
	int fd_in = util_file_open(poolset_file_src, NULL, 0, O_RDONLY);
	if (fd_in < 0) {
		ERR("cannot open source poolset file");
		goto err;
	}

	/* parse the source poolset file */
	struct pool_set *set_in = NULL;
	if (util_poolset_parse(&set_in, poolset_file_src, fd_in)) {
		ERR("parsing source poolset failed");
		close(fd_in);
		goto err;
	}
	close(fd_in);

	/* open the destination poolset file */
	int fd_out = util_file_open(poolset_file_dst, NULL, 0, O_RDONLY);
	if (fd_out < 0) {
		ERR("cannot open destination poolset file");
		goto err;
	}

	/* parse the destination poolset file */
	struct pool_set *set_out = NULL;
	if (util_poolset_parse(&set_out, poolset_file_dst, fd_out)) {
		ERR("parsing destination poolset failed");
		close(fd_out);
		goto err_free_poolin;
	}
	close(fd_out);

	/* check if the source poolset is of a correct type */
	if (pool_set_type(set_in) != POOL_TYPE_OBJ) {
		ERR("source poolset is of a wrong type");
		goto err_free_poolout;
	}

	/* 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");
		goto err_free_poolout;
	}
	if (!replica_is_poolset_healthy(set_in_hs)) {
		ERR("source poolset is broken");
		replica_free_poolset_health_status(set_in_hs);
		goto err_free_poolout;
	}
	replica_free_poolset_health_status(set_in_hs);

	/* transform poolset */
	if (transform_replica(set_in, set_out, flags)) {
		ERR("transformation failed");
		goto err_free_poolin;
	}

	util_poolset_close(set_in, 0);
	util_poolset_close(set_out, 0);
	return 0;

err_free_poolout:
	util_poolset_close(set_out, 0);

err_free_poolin:
	util_poolset_close(set_in, 0);

err:
	if (errno == 0)
		errno = EINVAL;

	return -1;
}