Beispiel #1
0
/*
 * 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;
}
Beispiel #2
0
/*
 * pool_params_from_header -- parse pool params from pool header
 */
void
pool_params_from_header(struct pool_params *params, const struct pool_hdr *hdr)
{
	memcpy(params->signature, hdr->signature, sizeof(params->signature));

	/*
	 * Check if file is a part of pool set by comparing the UUID with the
	 * next part UUID. If it is the same it means the pool consist of a
	 * single file.
	 */
	int uuid_eq_next = uuidcmp(hdr->uuid, hdr->next_part_uuid);
	int uuid_eq_prev = uuidcmp(hdr->uuid, hdr->prev_part_uuid);
	params->is_part = !params->is_poolset && (uuid_eq_next || uuid_eq_prev);

	params->type = pool_hdr_get_type(hdr);
}
Beispiel #3
0
/*
 * check_replica_cycles -- (internal) check if healthy replicas form cycles
 *	shorter than the number of all replicas
 */
static int
check_replica_cycles(struct pool_set *set,
		struct poolset_health_status *set_hs)
{
	LOG(3, "set %p, set_hs %p", set, set_hs);
	unsigned first_healthy;
	unsigned count_healthy = 0;
	for (unsigned r = 0; r < set->nreplicas; ++r) {
		if (!replica_is_replica_healthy(r, set_hs)) {
			count_healthy = 0;
			continue;
		}

		if (count_healthy == 0)
			first_healthy = r;

		++count_healthy;
		struct pool_hdr *hdrh =
				PART(REP(set, first_healthy), 0).hdr;
		struct pool_hdr *hdr = PART(REP(set, r), 0).hdr;
		if (uuidcmp(hdrh->uuid, hdr->next_repl_uuid) == 0 &&
				count_healthy < set->nreplicas) {
			/*
			 * healthy replicas form a cycle shorter than
			 * the number of all replicas; for the user it
			 * means that:
			 */
			ERR("there exist healthy replicas which come"
				" from a different poolset file");
			return -1;
		}
	}
	return 0;
}
Beispiel #4
0
/*
 * 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->nhdrs; ++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
			 */
			return -1;
		} else {
			/*
			 * it is sufficient to check only one part
			 * from internally consistent replica
			 */
			break;
		}
	}
	return 0;
}
Beispiel #5
0
/*
 * is_uuid_already_used -- (internal) check if given uuid is assigned to
 *                         any of the earlier replicas
 */
static int
is_uuid_already_used(uuid_t uuid, struct pool_set *set, unsigned repn)
{
	for (unsigned r = 0; r < repn; ++r) {
		if (uuidcmp(uuid, PART(REP(set, r), 0).uuid) == 0)
			return 1;
	}
	return 0;
}
Beispiel #6
0
/*
 * pool_hdr_uuid_links -- (internal) check UUID links values
 */
static int
pool_hdr_uuid_links(PMEMpoolcheck *ppc, location *loc)
{
	LOG(3, NULL);

	/*
	 * If the pool header is valid and there is not other parts or replicas
	 * in the poolset its uuid links are also valid.
	 */
	if (loc->hdr_valid && loc->single_repl && loc->single_part)
		return 0;

	uuid_t *links[] = {
		&loc->hdr.next_part_uuid, &loc->hdr.prev_part_uuid,
		&loc->hdr.next_repl_uuid, &loc->hdr.prev_repl_uuid};
	uuid_t *uuids[] = {
		&loc->next_part_hdrp->uuid, &loc->prev_part_hdrp->uuid,
		&loc->next_repl_hdrp->uuid, &loc->prev_repl_hdrp->uuid
	};
	uint32_t questions[] = {
		Q_NEXT_PART_UUID_SET, Q_PREV_PART_UUID_SET,
		Q_NEXT_REPL_UUID_SET, Q_PREV_REPL_UUID_SET
	};
	const char *fields[] = {
		"pool_hdr.next_part_uuid", "pool_hdr.prev_part_uuid",
		"pool_hdr.next_repl_uuid", "pool_hdr.prev_repl_uuid"
	};

	COMPILE_ERROR_ON(ARRAY_SIZE(links) != ARRAY_SIZE(uuids));
	COMPILE_ERROR_ON(ARRAY_SIZE(links) != ARRAY_SIZE(questions));
	COMPILE_ERROR_ON(ARRAY_SIZE(links) != ARRAY_SIZE(fields));
	for (uint64_t i = 0; i < ARRAY_SIZE(links); ++i) {
		if (uuidcmp(*links[i], *uuids[i]) == 0)
			continue;

		if (CHECK_IS(ppc, REPAIR)) {
			CHECK_ASK(ppc, questions[i],
				"%sinvalid %s.|Do you want to set it to a "
				"valid value?", loc->prefix, fields[i]);
		} else {
			ppc->result = CHECK_RESULT_NOT_CONSISTENT;
			return CHECK_ERR(ppc, "%sinvalid %s", loc->prefix,
				fields[i]);
		}
	}

	return check_questions_sequence_validate(ppc);
}
Beispiel #7
0
static bool do_list(void)
{
	struct dsp_ndb_props props;
	unsigned num = 0, i;
	void *proc_handle;
	struct node_info *node_table;
	void **tmp_table;
	unsigned node_count = 0, allocated_count = 0;

	if (!dsp_enum(dsp_handle, 0, &props, sizeof(props), &num)) {
		pr_err("failed to enumerate nodes");
		return false;
	}

	if (!dsp_attach(dsp_handle, 0, NULL, &proc_handle)) {
		pr_err("dsp attach failed");
		return false;
	}

	node_table = calloc(num, sizeof(*node_table));
	for (i = 0; i < num; i++) {
		if (dsp_enum(dsp_handle, i, &props, sizeof(props), &num)) {
			memcpy(&node_table[i].id, &props.node_id, sizeof(props.node_id));
			memcpy(&node_table[i].name, props.ac_name, sizeof(props.ac_name));
			node_table[i].type = props.ntype;
			node_table[i].state = -1;
		}
	}

	tmp_table = calloc(num, sizeof(*tmp_table));
	if (dsp_enum_nodes(dsp_handle, proc_handle, tmp_table, num,
				&node_count, &allocated_count))
	{
		for (i = 0; i < node_count; i++) {
			struct dsp_node_attr attr;
			struct dsp_node node = { .handle = tmp_table[i] };
			if (dsp_node_get_attr(dsp_handle, &node, &attr, sizeof(attr))) {
				unsigned j;
				for (j = 0; j < num; j++) {
					if (uuidcmp(&node_table[j].id, &attr.info.props.node_id)) {
						node_table[j].state = attr.info.state;
						break;
					}
				}
			}
		}
	} else {
Beispiel #8
0
/*
 * 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;
}
Beispiel #9
0
int main (int argc, const char *argv[]) {
    const char *tstr = NULL;
    var *env = var_alloc();
    var *env_collector = var_get_dict_forkey (env, "collector");
    var *env_colors = var_get_array_forkey (env, "colors");
    var_set_int_forkey (env_collector, "listenport", 3333);
    var_set_str_forkey (env_collector, "address", "127.0.0.1");
    var_set_str_forkey (env_collector, "key", "secret");
    var_clear_array (env_colors);
    var_add_str (env_colors, "red");
    var_add_str (env_colors, "green");
    var_add_str (env_colors, "blue");
    
    assert (var_get_int_forkey (env_collector, "listenport") == 3333);
    assert (tstr = var_get_str_forkey (env_collector, "address"));
    assert (strcmp (tstr, "127.0.0.1") == 0);
    assert (tstr = var_get_str_forkey (env_collector, "key"));
    assert (strcmp (tstr, "secret") == 0);
    assert (var_get_count (env_collector) == 3);
    assert (tstr = var_get_str_atindex (env_colors, 0));
    assert (strcmp (tstr, "red") == 0);
    assert (tstr = var_get_str_atindex (env_colors, 1));
    assert (strcmp (tstr, "green") == 0);
    assert (tstr = var_get_str_atindex (env_colors, 2));
    assert (strcmp (tstr, "blue") == 0);
    
    time_t tnow = time (NULL);
    var_set_time_forkey (env, "nowtime", tnow);
    assert (var_get_time_forkey (env, "nowtime") == tnow);
    var_set_unixtime_forkey (env, "unixtime", tnow);
    assert (var_get_time_forkey (env, "unixtime") == tnow);
    
    uuid uuid_in = uuidgen();
    var_set_uuid_forkey (env, "myuuid", uuid_in);
    uuid uuid_out = var_get_uuid_forkey (env, "myuuid");
    assert (uuidcmp (uuid_in, uuid_out));
    
    var_new_generation (env);
    var_set_int_forkey (env_collector, "listenport", 3333);
    var_set_str_forkey (env_collector, "address", "192.168.1.1");
    var_clear_array (env_colors);
    var_add_str (env_colors, "red");
    var_add_str (env_colors, "green");
    var_add_str (env_colors, "blue");
    
    var *lport, *addr, *key;
    lport = var_find_key (env_collector, "listenport");
    addr = var_find_key (env_collector, "address");
    key = var_find_key (env_collector, "key");
    assert (lport);
    assert (addr);
    assert (key);
    
    /* collector.listenport should be unchanged from first generation */
    assert (lport->generation == env->generation);
    assert (lport->lastmodified < env->generation);
    assert (lport->firstseen == lport->lastmodified);
    
    /* collector.addr should be changed this generation */
    assert (addr->generation == env->generation);
    assert (addr->lastmodified == env->generation);
    assert (addr->firstseen == env->firstseen);
    
    /* colors should be changed this generation */
    assert (env_colors->generation == env->generation);
    assert (env_colors->lastmodified == env->generation);
    assert (env_colors->firstseen == env->firstseen);
    
    /* collector.key should be stale */
    assert (key->generation < env->generation);
    
    var_clean_generation (env);
    
    /* collector.key should now be deleted */
    key = var_find_key (env_collector, "key");
    assert (key == NULL);
    return 0;
}
Beispiel #10
0
/*
 * check_uuids_between_parts -- (internal) check if uuids between adjacent
 *                              parts are consistent for a given replica
 */
static void
check_uuids_between_parts(struct pool_set *set, unsigned repn,
		struct poolset_health_status *set_hs)
{
	LOG(3, "set %p, repn %u, set_hs %p", set, repn, set_hs);
	struct pool_replica *rep = REP(set, repn);
	struct replica_health_status *rep_hs = REP(set_hs, repn);

	/* check parts linkage */
	LOG(4, "checking parts linkage in replica %u", repn);
	for (unsigned p = 0; p < rep->nparts; ++p) {
		/* skip broken parts */
		if (replica_is_part_broken(repn, p, set_hs))
			continue;

		struct pool_hdr *hdrp = HDR(rep, p);
		struct pool_hdr *next_hdrp = HDR(rep, p + 1);
		int next_is_broken = replica_is_part_broken(repn, p + 1,
				set_hs);

		if (!next_is_broken) {
			int next_decoupled =
				uuidcmp(next_hdrp->prev_part_uuid,
					hdrp->uuid) ||
				uuidcmp(hdrp->next_part_uuid, next_hdrp->uuid);
			if (next_decoupled) {
				rep_hs->flags |= IS_INCONSISTENT;
				/* skip further checking */
				return;
			}
		}
	}

	/* check if all uuids for adjacent replicas are the same across parts */
	LOG(4, "checking consistency of adjacent replicas' uuids in replica %u",
			repn);
	unsigned unbroken_p = UNDEF_PART;
	for (unsigned p = 0; p < rep->nparts; ++p) {
		/* skip broken parts */
		if (replica_is_part_broken(repn, p, set_hs))
			continue;

		if (unbroken_p == UNDEF_PART) {
			unbroken_p = p;
			continue;
		}

		struct pool_hdr *hdrp = HDR(rep, p);
		int prev_differ = uuidcmp(HDR(rep, unbroken_p)->prev_repl_uuid,
				hdrp->prev_repl_uuid);
		int next_differ = uuidcmp(HDR(rep, unbroken_p)->next_repl_uuid,
				hdrp->next_repl_uuid);

		if (prev_differ || next_differ) {
			ERR("different adjacent replica UUID between parts");
			rep_hs->flags |= IS_INCONSISTENT;
			/* skip further checking */
			return;
		}
	}

	/* check poolset_uuid consistency between replica's parts */
	LOG(4, "checking consistency of poolset uuid in replica %u", repn);
	uuid_t poolset_uuid;
	int uuid_stored = 0;
	for (unsigned p = 0; p < rep->nparts; ++p) {
		/* skip broken parts */
		if (replica_is_part_broken(repn, p, set_hs))
			continue;

		if (!uuid_stored) {
			memcpy(poolset_uuid, HDR(rep, p)->poolset_uuid,
					POOL_HDR_UUID_LEN);
			uuid_stored = 1;
			continue;
		}

		if (uuidcmp(HDR(rep, p)->poolset_uuid, poolset_uuid)) {
			rep_hs->flags |= IS_INCONSISTENT;
			/* skip further checking */
			return;
		}
	}
}
Beispiel #11
0
/*
 * 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;
}
Beispiel #12
0
/*
 * check_uuids_between_parts -- (internal) check if uuids between adjacent
 *                              parts are consistent for a given replica
 */
static int
check_uuids_between_parts(struct pool_set *set, unsigned repn,
		struct poolset_health_status *set_hs)
{
	LOG(3, "set %p, repn %u, set_hs %p", set, repn, set_hs);
	struct pool_replica *rep = REP(set, repn);

	/* check poolset_uuid consistency between replica's parts */
	LOG(4, "checking consistency of poolset uuid in replica %u", repn);
	uuid_t poolset_uuid;
	int uuid_stored = 0;
	unsigned part_stored = UNDEF_PART;
	for (unsigned p = 0; p < rep->nhdrs; ++p) {
		/* skip broken parts */
		if (replica_is_part_broken(repn, p, set_hs))
			continue;

		if (!uuid_stored) {
			memcpy(poolset_uuid, HDR(rep, p)->poolset_uuid,
					POOL_HDR_UUID_LEN);
			uuid_stored = 1;
			part_stored = p;
			continue;
		}

		if (uuidcmp(HDR(rep, p)->poolset_uuid, poolset_uuid)) {
			ERR("different poolset uuids in parts from the same"
				" replica (repn %u, parts %u and %u); cannot"
				" synchronize", repn, part_stored, p);
			errno = EINVAL;
			return -1;
		}
	}

	/* check if all uuids for adjacent replicas are the same across parts */
	LOG(4, "checking consistency of adjacent replicas' uuids in replica %u",
			repn);
	unsigned unbroken_p = UNDEF_PART;
	for (unsigned p = 0; p < rep->nhdrs; ++p) {
		/* skip broken parts */
		if (replica_is_part_broken(repn, p, set_hs))
			continue;

		if (unbroken_p == UNDEF_PART) {
			unbroken_p = p;
			continue;
		}

		struct pool_hdr *hdrp = HDR(rep, p);
		int prev_differ = uuidcmp(HDR(rep, unbroken_p)->prev_repl_uuid,
				hdrp->prev_repl_uuid);
		int next_differ = uuidcmp(HDR(rep, unbroken_p)->next_repl_uuid,
				hdrp->next_repl_uuid);

		if (prev_differ || next_differ) {
			ERR("different adjacent replica UUID between parts"
				" (repn %u, parts %u and %u);"
				" cannot synchronize", repn, unbroken_p, p);
			errno = EINVAL;
			return -1;
		}
	}

	/* check parts linkage */
	LOG(4, "checking parts linkage in replica %u", repn);
	for (unsigned p = 0; p < rep->nhdrs; ++p) {
		/* skip broken parts */
		if (replica_is_part_broken(repn, p, set_hs))
			continue;

		struct pool_hdr *hdrp = HDR(rep, p);
		struct pool_hdr *next_hdrp = HDRN(rep, p);
		int next_is_broken = replica_is_part_broken(repn, p + 1,
				set_hs);

		if (!next_is_broken) {
			int next_decoupled =
				uuidcmp(next_hdrp->prev_part_uuid,
					hdrp->uuid) ||
				uuidcmp(hdrp->next_part_uuid, next_hdrp->uuid);
			if (next_decoupled) {
				ERR("two consecutive unbroken parts are not"
					" linked to each other (repn %u, parts"
					" %u and %u); cannot synchronize",
					repn, p, p + 1);
				errno = EINVAL;
				return -1;
			}
		}
	}
	return 0;
}
Beispiel #13
0
/*
 * pool_hdr_uuid_find -- (internal) check UUID value
 */
static int
pool_hdr_uuid_find(PMEMpoolcheck *ppc, location *loc)
{
	LOG(3, NULL);

	/*
	 * If the pool header is valid and there is not other parts or replicas
	 * in the poolset its uuid is also valid.
	 */
	if (loc->hdr_valid && loc->single_repl && loc->single_part)
		return 0;

	int hdrs_valid[] = {
		loc->next_part_hdr_valid, loc->prev_part_hdr_valid,
		loc->next_repl_hdr_valid, loc->prev_repl_hdr_valid};
	uuid_t *uuids[] = {
		&loc->next_part_hdrp->prev_part_uuid,
		&loc->prev_part_hdrp->next_part_uuid,
		&loc->next_repl_hdrp->prev_repl_uuid,
		&loc->prev_repl_hdrp->next_repl_uuid
	};

	/*
	 * if all valid poolset part files have the same uuid links to this part
	 * file it is valid uuid
	 * if all links have the same uuid and it is single file pool it is also
	 * the valid uuid
	 */
	loc->valid_uuid = NULL;
	if (loc->hdr_valid)
		loc->valid_uuid = &loc->hdr.uuid;
	uuid_t *common_uuid = uuids[0];

	COMPILE_ERROR_ON(ARRAY_SIZE(uuids) != ARRAY_SIZE(hdrs_valid));
	COMPILE_ERROR_ON(COMPARE_TO_FIRST_PART_ONLY >= ARRAY_SIZE(uuids));
	for (unsigned i = 0; i < ARRAY_SIZE(uuids); ++i) {
		if (i > 0 && common_uuid != NULL) {
			if (uuidcmp(*common_uuid, *uuids[i]) != 0) {
				common_uuid = NULL;
			}
		}

		if (i >= COMPARE_TO_FIRST_PART_ONLY && loc->part != 0)
			continue;

		if (!hdrs_valid[i])
			continue;

		if (!loc->valid_uuid) {
			loc->valid_uuid = uuids[i];
		} else if (uuidcmp(*loc->valid_uuid, *uuids[i]) != 0) {
			ppc->result = CHECK_RESULT_NOT_CONSISTENT;
			return CHECK_ERR(ppc, "%sambiguous pool_hdr.uuid",
				loc->prefix);
		}
	}

	if (!loc->valid_uuid && common_uuid)
		loc->valid_uuid = common_uuid;

	if (loc->valid_uuid != NULL) {
		if (uuidcmp(*loc->valid_uuid, loc->hdr.uuid) != 0) {
			CHECK_ASK(ppc, Q_UUID_SET, INVALID_UUID ".|Do you want "
				"to set it to %s from a valid part file?",
				loc->prefix,
				check_get_uuid_str(*loc->valid_uuid));
		}
	} else if (CHECK_IS(ppc, ADVANCED)) {
		CHECK_ASK(ppc, Q_UUID_REGENERATE, INVALID_UUID ".|Do you want "
				"to regenerate it?", loc->prefix);
	} else if (CHECK_IS(ppc, REPAIR)) {
		ppc->result = CHECK_RESULT_CANNOT_REPAIR;
		CHECK_INFO(ppc, "%s" REQUIRE_ADVANCED, loc->prefix);
		return CHECK_ERR(ppc, INVALID_UUID, loc->prefix);
	} else {
		ppc->result = CHECK_RESULT_NOT_CONSISTENT;
		return CHECK_ERR(ppc, INVALID_UUID, loc->prefix);
	}

	return check_questions_sequence_validate(ppc);
}
Beispiel #14
0
/*
 * pool_hdr_poolset_uuid -- (internal) check poolset_uuid field
 */
static int
pool_hdr_poolset_uuid_find(PMEMpoolcheck *ppc, location *loc)
{
	LOG(3, NULL);

	/*
	 * If the pool header is valid and there is not other parts or replicas
	 * in the poolset its poolset_uuid is also valid.
	 */
	if (loc->hdr_valid && loc->single_repl && loc->single_part)
		return 0;

	if (loc->replica != 0 || loc->part != 0)
		goto after_lookup;

	/* for blk pool we can take the UUID from BTT Info header */
	if (ppc->pool->params.type == POOL_TYPE_BLK && ppc->pool->bttc.valid) {
		loc->valid_puuid = &ppc->pool->bttc.btt_info.parent_uuid;
		if (uuidcmp(loc->hdr.poolset_uuid, *loc->valid_puuid) != 0) {
			CHECK_ASK(ppc, Q_POOLSET_UUID_FROM_BTT_INFO,
				"%sinvalid pool_hdr.poolset_uuid.|Do you want "
				"to set it to %s from BTT Info?", loc->prefix,
				check_get_uuid_str(*loc->valid_puuid));
			goto exit_question;
		}
	}

	if (loc->single_part && loc->single_repl) {
		/*
		 * If the pool is not blk pool or BTT Info header is invalid
		 * there is no other way to validate poolset uuid.
		 */
		return 0;
	}

	/*
	 * if all valid poolset part files have the same poolset uuid it is
	 * the valid poolset uuid
	 * if all part files have the same poolset uuid it is valid poolset uuid
	 */
	struct pool_set *poolset = ppc->pool->set_file->poolset;
	unsigned nreplicas = poolset->nreplicas;
	uuid_t *common_puuid = loc->valid_puuid;
	for (unsigned r = 0; r < nreplicas; r++) {
		struct pool_replica *rep = REP(poolset, r);
		for (unsigned p = 0; p < rep->nhdrs; p++) {
			struct pool_hdr *hdr = HDR(rep, p);

			/*
			 * find poolset uuid if it is the same for all part
			 * files
			 */
			if (common_puuid == NULL) {
				if (r == 0 && p == 0) {
					common_puuid = &hdr->poolset_uuid;
				}
			} else if (uuidcmp(*common_puuid, hdr->poolset_uuid)
					!= 0) {
				common_puuid = NULL;
			}

			if (!pool_hdr_valid(hdr))
				continue;

			/*
			 * find poolset uuid if it is the same for all valid
			 * part files
			 */
			if (loc->valid_puuid == NULL) {
				loc->valid_puuid = &hdr->poolset_uuid;
			} else if (uuidcmp(*loc->valid_puuid, hdr->poolset_uuid)
					!= 0) {
				ppc->result = CHECK_RESULT_NOT_CONSISTENT;
				return CHECK_ERR(ppc, "the poolset contains "
					"part files from various poolsets");
			}
		}
	}

	if (!loc->valid_puuid && common_puuid)
		loc->valid_puuid = common_puuid;

	if (loc->valid_puuid)
		goto after_lookup;

	if (CHECK_IS_NOT(ppc, REPAIR)) {
		ppc->result = CHECK_RESULT_NOT_CONSISTENT;
		return CHECK_ERR(ppc, NO_COMMON_POOLSET_UUID, loc->prefix);
	} else if (CHECK_IS_NOT(ppc, ADVANCED)) {
		ppc->result = CHECK_RESULT_CANNOT_REPAIR;
		CHECK_INFO(ppc, "%s" REQUIRE_ADVANCED, loc->prefix);
		return CHECK_ERR(ppc, NO_COMMON_POOLSET_UUID, loc->prefix);
	} else {
		CHECK_ASK(ppc, Q_POOLSET_UUID_REGENERATE, NO_COMMON_POOLSET_UUID
			".|Do you want to regenerate pool_hdr.poolset_uuid?",
			loc->prefix);
		goto exit_question;
	}

after_lookup:
	if (loc->valid_puuid) {
		if (uuidcmp(*loc->valid_puuid, loc->hdr.poolset_uuid) != 0) {
			if (CHECK_IS_NOT(ppc, REPAIR)) {
				ppc->result = CHECK_RESULT_NOT_CONSISTENT;
				return CHECK_ERR(ppc, "%sinvalid "
					"pool_hdr.poolset_uuid", loc->prefix);
			}

			CHECK_ASK(ppc, Q_POOLSET_UUID_SET, "%sinvalid "
				"pool_hdr.poolset_uuid.|Do you want to set "
				"it to %s from a valid part file?", loc->prefix,
				check_get_uuid_str(*loc->valid_puuid));
		}
	}

exit_question:
	return check_questions_sequence_validate(ppc);
}
Beispiel #15
0
int GptAllocFileCopy(HGPT hGPT, char *pszFileName, EFI_PARTITION_ENTRY *pNewEntry)
    {
    int i;
    int iPartition;
    QWORD qwLBA;
    int iErr;
    // To be cleaned up before return
    char *pSect = (char *)NULL;
    // End of clean-up zone
    int nSect;
    FILE *hf = NULL;
    
    // Compute the number of partition entries per sector.
    // int iEntryPerSect = hGPT->iSectorSize / sizeof(EFI_PARTITION_ENTRY);

    // Allocate a buffer to access drive data.
    pSect = (char *)malloc(hGPT->iSectorSize);
    if (!pSect) GptAllocFileCopyFail(-4);
    	
    // Open the partition image file
    hf = fopen(pszFileName, "rb");
    if (!hf) GptAllocFileCopyFail(-10);
    // Compute the number of sectors necessary.
    nSect = (int)((_filelength(_fileno(hf)) + hGPT->iSectorSize - 1) / hGPT->iSectorSize);

    // Search the smallest contiguous block of free sectors large enough.
    pNewEntry->EndingLBA = nSect;
    iPartition = GptAllocSectors(hGPT, pNewEntry);  // Side effect: pNewEntry->PartitionTypeGUID = 0;
    if (iPartition < 0) GptAllocFileCopyFail(iPartition);

#ifdef _DEBUG
    if (iVerbose)
        {
        printf("Allocating partition entry #%d for copying from file %s\n", iPartition, pszFileName);
        }
#endif
	    
    // Write the partition contents
    for (i=0, qwLBA=pNewEntry->StartingLBA; i<nSect; i++, qwLBA++)
        {
        size_t stRead;
	        
        stRead = fread(pSect, 1, hGPT->iSectorSize, hf);
        if (stRead < (size_t)(hGPT->iSectorSize)) memset(pSect+stRead, 0, hGPT->iSectorSize-stRead);
	        
	// ~~jfl 2001/12/19 Use the partition type GUID specified in the file, if any.
	if (i==0)
	    {
	    EFI_BOOT_PROGRAM_HEADER *pHdr = (EFI_BOOT_PROGRAM_HEADER *)pSect;
	    if (CheckCrc(hGPT->iSectorSize, &(pHdr->Header)))
		{
		if (!memcmp(((char *)&(pHdr->Header.Signature))+3, "MBR32", 5))
		    {
		    pNewEntry->PartitionTypeGUID = guidMbrBackup;   // If it's inside the GPT, then it's the backup!
		    }
		else	// Assume it's a relay or a boot program (Including the boot menu).
		    {	// Both have a partition entry behind the header.
		    pNewEntry->PartitionTypeGUID = pHdr->Partition.PartitionTypeGUID;
		    }
		}
	    else if (   (!memcmp(((char *)&(pHdr->Header.Signature))+3, "Relay", 5))
		     && (!uuidcmp(&(pHdr->Partition.PartitionTypeGUID), &guidRelay))
		    )	// It's a relay, but with the header incomplete (CRC not set yet).
		{
		pNewEntry->PartitionTypeGUID = guidRelay;
		// ~~jfl 2002/01/03 Update the partition header while we have it.
		uuid_create((uuid_t *)&(pHdr->Partition.UniquePartitionGUID));	// Generate a new GUID
		SetCrc(&(pHdr->Header));
		}
	    else if (IsMBR(pSect))	// Master Boot Record. Assume it's a hard disk.
		{
		pNewEntry->PartitionTypeGUID = guidHardDiskImage;
		}
	    if (IsNullUuid((uuid_t*)&(pNewEntry->PartitionTypeGUID)))	// Assume anything else is a floppy.
		{
		pNewEntry->PartitionTypeGUID = guidFloppyImage;
		}
	    }

	iErr = GptBlockWrite(hGPT, qwLBA, 1, pSect);
	if (iErr) GptAllocFileCopyFail(-3);
        }

copy_return:
    // Cleanup
    fclose(hf);
    free(pSect);
    
    return iPartition;    
    }