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)) {
		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;
}
Exemple #3
0
/*
 * 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;
}