コード例 #1
0
ファイル: replica.c プロジェクト: stellarhopper/nvml
/*
 * check_uuids_between_replicas -- (internal) check if uuids between internally
 *                                 consistent adjacent replicas are consistent
 */
static int
check_uuids_between_replicas(struct pool_set *set,
		struct poolset_health_status *set_hs)
{
	for (unsigned r = 0; r < set->nreplicas; ++r) {
		/* skip comparing inconsistent pairs of replicas */
		if (!replica_is_replica_consistent(r, set_hs) ||
				!replica_is_replica_consistent(r + 1, set_hs))
			continue;

		struct pool_replica *rep = REP(set, r);
		struct pool_replica *rep_n = REP(set, r + 1);
		struct replica_health_status *rep_hs = REP(set_hs, r);
		struct replica_health_status *rep_n_hs = REP(set_hs, r + 1);

		/* check adjacent replica uuids for yet unbroken parts */
		unsigned p = replica_find_unbroken_part(r, set_hs);
		unsigned p_n = replica_find_unbroken_part(r + 1, set_hs);

		/* if the first part is broken, cannot compare replica uuids */
		if (p > 0) {
			rep_hs->flags |= IS_BROKEN;
			continue;
		}

		/* if the first part is broken, cannot compare replica uuids */
		if (p_n > 0) {
			rep_n_hs->flags |= IS_BROKEN;
			continue;
		}

		/* check if replica uuids are consistent between replicas */
		if (uuidcmp(HDR(rep_n, p_n)->prev_repl_uuid,
				HDR(rep, p)->uuid) || uuidcmp(
				HDR(rep, p)->next_repl_uuid,
				HDR(rep_n, p_n)->uuid)) {

			if (set->nreplicas == 1) {
				rep_hs->flags |= IS_INCONSISTENT;
			} else {
				if (replica_is_replica_broken(r, set_hs)) {
					rep_hs->flags |= IS_BROKEN;
					continue;
				}

				if (replica_is_replica_broken(r + 1, set_hs)) {
					rep_n_hs->flags |= IS_BROKEN;
					continue;
				}

				// two unbroken and internally consistent
				// adjacent replicas have different adjacent
				// replica uuids - mark one as inconsistent
				rep_n_hs->flags |= IS_INCONSISTENT;
				continue;
			}
		}
	}
	return 0;
}
コード例 #2
0
ファイル: sync.c プロジェクト: stellarhopper/nvml
/*
 * create_headers_for_broken_parts -- (internal) create headers for all new
 *                                    parts created in place of the broken ones
 */
static int
create_headers_for_broken_parts(struct pool_set *set, unsigned src_replica,
		struct poolset_health_status *set_hs)
{
	struct pool_hdr *src_hdr = HDR(REP(set, src_replica), 0);
	for (unsigned r = 0; r < set_hs->nreplicas; ++r) {
		/* skip unbroken replicas */
		if (!replica_is_replica_broken(r, set_hs))
			continue;

		for (unsigned p = 0; p < set_hs->replica[r]->nparts; p++) {
			/* skip unbroken parts */
			if (!replica_is_part_broken(r, p, set_hs))
				continue;

			if (util_header_create(set, r, p,
					src_hdr->signature, src_hdr->major,
					src_hdr->compat_features,
					src_hdr->incompat_features,
					src_hdr->ro_compat_features,
					NULL, NULL, NULL) != 0) {
				LOG(1, "part headers create failed for"
						" replica %u part %u", r, p);
				errno = EINVAL;
				return -1;
			}
		}
	}
	return 0;
}
コード例 #3
0
ファイル: replica.c プロジェクト: ChandKV/nvml
/*
 * replica_is_replica_healthy -- check if replica is unbroken and consistent
 */
int
replica_is_replica_healthy(unsigned repn,
		struct poolset_health_status *set_hs)
{
	return !replica_is_replica_broken(repn, set_hs) &&
			replica_is_replica_consistent(repn, set_hs);
}
コード例 #4
0
ファイル: transform.c プロジェクト: GBuella/nvml
/*
 * do_added_parts_exist -- (internal) check if any part of the replicas that are
 *                         to be added (marked as broken) already exists
 */
static int
do_added_parts_exist(struct pool_set *set,
		struct poolset_health_status *set_hs)
{
	for (unsigned r = 0; r < set->nreplicas; ++r) {
		/* skip unbroken (i.e. not being added) replicas */
		if (!replica_is_replica_broken(r, set_hs))
			continue;

		struct pool_replica *rep = REP(set, r);

		/* skip remote replicas */
		if (rep->remote)
			continue;

		for (unsigned p = 0; p < rep->nparts; ++p) {
			/* check if part file exists */
			int oerrno = errno;
			if (os_access(rep->part[p].path, F_OK) == 0 &&
					!rep->part[p].is_dev_dax) {
				LOG(1, "part file %s exists",
						rep->part[p].path);
				return 1;
			}
			errno = oerrno;
		}
	}
	return 0;
}
コード例 #5
0
ファイル: sync.c プロジェクト: wojtuss/nvml
/*
 * create_headers_for_broken_parts -- (internal) create headers for all new
 *                                    parts created in place of the broken ones
 */
static int
create_headers_for_broken_parts(struct pool_set *set, unsigned src_replica,
		struct poolset_health_status *set_hs)
{
	LOG(3, "set %p, src_replica %u, set_hs %p", set, src_replica, set_hs);
	struct pool_hdr *src_hdr = HDR(REP(set, src_replica), 0);
	for (unsigned r = 0; r < set_hs->nreplicas; ++r) {
		/* skip unbroken replicas */
		if (!replica_is_replica_broken(r, set_hs))
			continue;

		for (unsigned p = 0; p < set_hs->replica[r]->nhdrs; p++) {
			/* skip unbroken parts */
			if (!replica_is_part_broken(r, p, set_hs))
				continue;

			struct pool_attr attr;
			util_pool_hdr2attr(&attr, src_hdr);
			if (util_header_create(set, r, p, &attr, 0) != 0) {
				LOG(1, "part headers create failed for"
						" replica %u part %u", r, p);
				errno = EINVAL;
				return -1;
			}
		}
	}
	return 0;
}
コード例 #6
0
ファイル: replica.c プロジェクト: stellarhopper/nvml
/*
 * replica_find_healthy_replica -- find a replica number which is a good source
 *                                 of data
 */
unsigned
replica_find_healthy_replica(struct poolset_health_status *set_hs)
{
	if (set_hs->nreplicas == 1) {
		return replica_is_replica_broken(0, set_hs) ? UNDEF_REPLICA : 0;
	} else {
		for (unsigned r = 0; r < set_hs->nreplicas; ++r) {
			if (replica_is_replica_healthy(r, set_hs))
				return r;
		}
		return UNDEF_REPLICA;
	}
}
コード例 #7
0
ファイル: sync.c プロジェクト: tomaszkapela/nvml
/*
 * grant_created_parts_perm -- (internal) set RW permission rights to all
 *                            the parts created in place of the broken ones
 */
static int
grant_created_parts_perm(struct pool_set *set, unsigned src_repn,
		struct poolset_health_status *set_hs)
{
	LOG(3, "set %p, src_repn %u, set_hs %p", set, src_repn, set_hs);

	/* choose the default permissions */
	mode_t def_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;

	/* get permissions of the first part of the source replica */
	mode_t src_mode;
	os_stat_t sb;
	if (os_stat(PART(REP(set, src_repn), 0).path, &sb) != 0) {
		ERR("cannot check file permissions of %s (replica %u, part %u)",
				PART(REP(set, src_repn), 0).path, src_repn, 0);
		src_mode = def_mode;
	} else {
		src_mode = sb.st_mode;
	}

	/* set permissions to all recreated parts */
	for (unsigned r = 0; r < set_hs->nreplicas; ++r) {
		/* skip unbroken replicas */
		if (!replica_is_replica_broken(r, set_hs))
			continue;

		if (set->replica[r]->remote)
			continue;

		for (unsigned p = 0; p < set_hs->replica[r]->nparts; p++) {
			/* skip parts which were not created */
			if (!PART(REP(set, r), p).created)
				continue;

			LOG(4, "setting permissions for part %u, replica %u",
					p, r);

			/* set rights to those of existing part files */
			if (os_chmod(PART(REP(set, r), p).path, src_mode)) {
				ERR("cannot set permission rights for created"
					" parts: replica %u, part %u", r, p);
				errno = EPERM;
				return -1;
			}
		}
	}
	return 0;
}
コード例 #8
0
ファイル: replica.c プロジェクト: ChandKV/nvml
/*
 * check_replica_poolset_uuids - (internal) check if poolset_uuid fields are
 *                               consistent among all parts of a replica;
 *                               the replica is initially considered as
 *                               consistent
 */
static int
check_replica_poolset_uuids(struct pool_set *set, unsigned repn,
		uuid_t poolset_uuid, struct poolset_health_status *set_hs)
{
	LOG(3, "set %p, repn %u, poolset_uuid %p, set_hs %p", set, repn,
			poolset_uuid, set_hs);
	struct pool_replica *rep = REP(set, repn);
	for (unsigned p = 0; p < rep->nparts; ++p) {
		/* skip broken parts */
		if (replica_is_part_broken(repn, p, set_hs))
			continue;

		if (!uuidcmp(HDR(rep, p)->poolset_uuid, poolset_uuid)) {
			/*
			 * two internally consistent replicas have
			 * different poolset_uuid
			 */
			if (replica_is_replica_broken(repn, set_hs)) {
				/* mark broken replica as inconsistent */
				REP(set_hs, repn)->flags |= IS_INCONSISTENT;
			} else {
				/*
				 * two consistent unbroken replicas
				 * - cannot synchronize
				 */
				ERR("inconsistent poolset_uuid values");
				return -1;
			}
		} else {
			/*
			 * it is sufficient to check only one part
			 * from internally consistent replica
			 */
			break;
		}
	}
	return 0;
}
コード例 #9
0
ファイル: replica.c プロジェクト: wojtuss/nvml
/*
 * check_uuids_between_replicas -- (internal) check if uuids between internally
 *                                 consistent adjacent replicas are consistent
 */
static int
check_uuids_between_replicas(struct pool_set *set,
		struct poolset_health_status *set_hs)
{
	LOG(3, "set %p, set_hs %p", set, set_hs);
	for (unsigned r = 0; r < set->nreplicas; ++r) {
		/* skip comparing inconsistent pairs of replicas */
		if (!replica_is_replica_consistent(r, set_hs) ||
				!replica_is_replica_consistent(r + 1, set_hs))
			continue;

		struct pool_replica *rep = REP(set, r);
		struct pool_replica *rep_n = REPN(set, r);

		/* get uuids of the two adjacent replicas */
		uuid_t *rep_uuidp = NULL;
		uuid_t *rep_n_uuidp = NULL;
		unsigned r_n = REPNidx(set_hs, r);
		if (get_replica_uuid(rep, r, set_hs, &rep_uuidp))
			LOG(2, "cannot get replica uuid, replica %u", r);
		if (get_replica_uuid(rep_n, r_n, set_hs, &rep_n_uuidp))
			LOG(2, "cannot get replica uuid, replica %u", r_n);

		/*
		 * check if replica uuids are consistent between two adjacent
		 * replicas
		 */
		unsigned p = replica_find_unbroken_part(r, set_hs);
		unsigned p_n = replica_find_unbroken_part(r_n, set_hs);
		if (p_n != UNDEF_PART && rep_uuidp != NULL &&
				uuidcmp(*rep_uuidp,
					HDR(rep_n, p_n)->prev_repl_uuid)) {
			ERR(
			"inconsistent replica uuids between replicas %u and %u",
				r, r_n);
			return -1;
		}
		if (p != UNDEF_PART && rep_n_uuidp != NULL &&
				uuidcmp(*rep_n_uuidp,
					HDR(rep, p)->next_repl_uuid)) {
			ERR(
			"inconsistent replica uuids between replicas %u and %u",
				r, r_n);
			return -1;
		}

		/*
		 * check if replica uuids on borders of a broken replica are
		 * consistent
		 */
		unsigned r_nn = REPNidx(set_hs, r_n);
		if (set->nreplicas > 1 && p != UNDEF_PART &&
				replica_is_replica_broken(r_n, set_hs) &&
				replica_is_replica_consistent(r_nn, set_hs)) {
			unsigned p_nn =
				replica_find_unbroken_part(r_nn, set_hs);
			if (p_nn == UNDEF_PART) {
				LOG(2,
				"cannot compare uuids on borders of replica %u",
					r);
				continue;
			}
			struct pool_replica *rep_nn = REP(set, r_nn);
			if (uuidcmp(HDR(rep, p)->next_repl_uuid,
					HDR(rep_nn, p_nn)->prev_repl_uuid)) {
				ERR(
				"inconsistent replica uuids on borders of replica %u",
					r);
				return -1;
			}


		}
	}
	return 0;
}