コード例 #1
0
ファイル: check_pool_hdr.c プロジェクト: plebioda/nvml
/*
 * pool_hdr_uuid_fix -- (internal) fix UUID value
 */
static int
pool_hdr_uuid_fix(PMEMpoolcheck *ppc, location *loc, uint32_t question,
	void *context)
{
	LOG(3, NULL);

	ASSERTne(loc, NULL);

	switch (question) {
	case Q_UUID_SET:
		CHECK_INFO(ppc, "%ssetting pool_hdr.uuid to %s", loc->prefix,
			check_get_uuid_str(*loc->valid_uuid));
		memcpy(loc->hdr.uuid, loc->valid_uuid, POOL_HDR_UUID_LEN);
		break;
	case Q_UUID_REGENERATE:
		if (util_uuid_generate(loc->hdr.uuid) != 0) {
			ppc->result = CHECK_RESULT_INTERNAL_ERROR;
			return CHECK_ERR(ppc, "%suuid generation failed",
				loc->prefix);
		}
		CHECK_INFO(ppc, "%ssetting pool_hdr.uuid to %s", loc->prefix,
			check_get_uuid_str(loc->hdr.uuid));
		break;
	default:
		ERR("not implemented question id: %u", question);
	}

	return 0;
}
コード例 #2
0
ファイル: check_pool_hdr.c プロジェクト: plebioda/nvml
/*
 * pool_hdr_nondefault_fix -- (internal) fix custom value fields
 */
static int
pool_hdr_nondefault_fix(PMEMpoolcheck *ppc, location *loc, uint32_t question,
	void *context)
{
	LOG(3, NULL);

	ASSERTne(loc, NULL);
	uint64_t *flags = NULL;

	switch (question) {
	case Q_CRTIME:
		CHECK_INFO(ppc, "%ssetting pool_hdr.crtime to file's modtime: "
			"%s", loc->prefix,
			check_get_time_str(ppc->pool->set_file->mtime));
		util_convert2h_hdr_nocheck(&loc->hdr);
		loc->hdr.crtime = (uint64_t)ppc->pool->set_file->mtime;
		util_convert2le_hdr(&loc->hdr);
		break;
	case Q_ARCH_FLAGS:
		flags = (uint64_t *)&loc->valid_part_hdrp->arch_flags;
		CHECK_INFO(ppc, "%ssetting pool_hdr.arch_flags to 0x%08" PRIx64
				"%08" PRIx64, loc->prefix, flags[0], flags[1]);
		util_convert2h_hdr_nocheck(&loc->hdr);
		memcpy(&loc->hdr.arch_flags, &loc->valid_part_hdrp->arch_flags,
			sizeof(struct arch_flags));
		util_convert2le_hdr(&loc->hdr);
		break;
	default:
		ERR("not implemented question id: %u", question);
	}

	return 0;
}
コード例 #3
0
ファイル: check_sds.c プロジェクト: krzycz/nvml
/*
 * sds_check -- (internal) check shutdown_state
 */
static int
sds_check(PMEMpoolcheck *ppc, location *loc)
{
	LOG(3, NULL);

	CHECK_INFO(ppc, "%s" SDS_CHECK_STR, loc->prefix);

	/* shutdown state is valid */
	if (!sds_check_replica(loc)) {
		CHECK_INFO(ppc, "%s" SDS_OK_STR, loc->prefix);
		loc->step = CHECK_STEP_COMPLETE;
		return 0;
	}

	/* shutdown state is NOT valid and can NOT be repaired */
	if (CHECK_IS_NOT(ppc, REPAIR)) {
		check_end(ppc->data);
		ppc->result = CHECK_RESULT_NOT_CONSISTENT;
		return CHECK_ERR(ppc, "%s%s", loc->prefix,
				SDS_FAIL_MSG(&loc->hdr));
	}

	/* shutdown state is NOT valid but can be repaired */
	CHECK_ASK(ppc, Q_RESET_SDS, "%s%s", loc->prefix,
			SDS_REPAIR_MSG(&loc->hdr));
	return check_questions_sequence_validate(ppc);
}
コード例 #4
0
ファイル: check_cto.c プロジェクト: GBuella/nvml
/*
 * cto_hdr_fix -- (internal) fix pmemcto header
 */
static int
cto_hdr_fix(PMEMpoolcheck *ppc, location *loc, uint32_t question, void *ctx)
{
	LOG(3, NULL);

	switch (question) {
	case Q_CTO_CONSISTENT:
		CHECK_INFO(ppc, "setting pmemcto.consistent flag");
		ppc->pool->hdr.cto.consistent = 1;
		break;
	case Q_CTO_ADDR:
		CHECK_INFO(ppc, "recovering pmemcto.addr");
		ppc->pool->hdr.cto.addr = 0;
		break;
	case Q_CTO_SIZE:
		CHECK_INFO(ppc,
				"setting pmemcto.size to the actual pool size %zu",
				ppc->pool->params.size);
		ppc->pool->hdr.cto.size = ppc->pool->params.size;
		break;
	case Q_CTO_ROOT:
		CHECK_INFO(ppc, "recovering pmemcto.root pointer");
		ppc->pool->hdr.cto.root = 0;
		break;
	default:
		ERR("not implemented question id: %u", question);
	}

	return 0;
}
コード例 #5
0
ファイル: check_pool_hdr.c プロジェクト: plebioda/nvml
/*
 * pool_hdr_preliminary_check -- (internal) check pool header checksum and pool
 *	parameters
 */
static int
pool_hdr_preliminary_check(PMEMpoolcheck *ppc, location *loc)
{
	LOG(3, NULL);

	CHECK_INFO(ppc, "%schecking pool header", loc->prefix);

	if (util_is_zeroed((void *)&loc->hdr, sizeof(loc->hdr))) {
		if (CHECK_IS_NOT(ppc, REPAIR)) {
			check_end(ppc->data);
			ppc->result = CHECK_RESULT_NOT_CONSISTENT;
			return CHECK_ERR(ppc, "%sempty pool hdr", loc->prefix);
		}
	} else if (loc->hdr_valid) {
		enum pool_type type = pool_hdr_get_type(&loc->hdr);
		if (type == POOL_TYPE_UNKNOWN) {
			if (CHECK_IS_NOT(ppc, REPAIR)) {
				check_end(ppc->data);
				ppc->result = CHECK_RESULT_NOT_CONSISTENT;
				return CHECK_ERR(ppc, "%sinvalid signature",
					loc->prefix);
			}

			CHECK_INFO(ppc, "%sinvalid signature", loc->prefix);
		} else {
			/* valid check sum */
			CHECK_INFO(ppc, "%spool header correct",
				loc->prefix);
			loc->step = CHECK_STEP_COMPLETE;
			return 0;
		}
	} else if (CHECK_IS_NOT(ppc, REPAIR)) {
		check_end(ppc->data);
		ppc->result = CHECK_RESULT_NOT_CONSISTENT;
		return CHECK_ERR(ppc, "%sincorrect pool header", loc->prefix);
	} else {
		CHECK_INFO(ppc, "%sincorrect pool header", loc->prefix);
	}

	ASSERT(CHECK_IS(ppc, REPAIR));

	if (ppc->pool->params.type == POOL_TYPE_UNKNOWN) {
		ppc->pool->params.type = pool_hdr_possible_type(ppc);
		if (ppc->pool->params.type == POOL_TYPE_UNKNOWN) {
			ppc->result = CHECK_RESULT_CANNOT_REPAIR;
			return CHECK_ERR(ppc, "cannot determine pool type");
		}
	}

	if (!pool_supported(ppc->pool->params.type)) {
		ppc->result = CHECK_RESULT_CANNOT_REPAIR;
		return CHECK_ERR(ppc, "the repair of %s pools is not supported",
			pool_get_pool_type_str(ppc->pool->params.type));
	}

	return 0;
}
コード例 #6
0
ファイル: check_util.c プロジェクト: JLLLinn/nvml
/*
 * check_push_answer -- process answer and push it to answers queue
 */
int
check_push_answer(PMEMpoolcheck *ppc)
{
	if (ppc->data->check_status_cache == NULL)
		return 0;

	/* check if answer is "yes" or "no" */
	struct check_status *status = ppc->data->check_status_cache;
	if (status->status.str.answer != NULL) {
		if (strcmp(status->status.str.answer, CHECK_ANSWER_YES) == 0)
			status->answer = PMEMPOOL_CHECK_ANSWER_YES;
		else if (strcmp(status->status.str.answer, CHECK_ANSWER_NO)
				== 0)
			status->answer = PMEMPOOL_CHECK_ANSWER_NO;
	}

	if (status->answer == PMEMPOOL_CHECK_ANSWER_EMPTY) {
		/* invalid answer provided */
		status_answer_push(ppc->data, ppc->data->check_status_cache);
		ppc->data->check_status_cache = NULL;
		CHECK_INFO(ppc, "Answer must be either %s or %s",
			CHECK_ANSWER_YES, CHECK_ANSWER_NO);
		return -1;
	}

	/* push answer */
	TAILQ_INSERT_TAIL(&ppc->data->answers,
		ppc->data->check_status_cache, next);
	ppc->data->check_status_cache = NULL;

	return 0;
}
コード例 #7
0
ファイル: check_pool_hdr.c プロジェクト: plebioda/nvml
/*
 * pool_hdr_uuid_links_fix -- (internal) fix UUID links values
 */
static int
pool_hdr_uuid_links_fix(PMEMpoolcheck *ppc, location *loc, uint32_t question,
	void *context)
{
	LOG(3, NULL);

	ASSERTne(loc, NULL);

	switch (question) {
	case Q_NEXT_PART_UUID_SET:
		CHECK_INFO(ppc, "%ssetting pool_hdr.next_part_uuid to %s",
			loc->prefix,
			check_get_uuid_str(loc->next_part_hdrp->uuid));
		memcpy(loc->hdr.next_part_uuid, loc->next_part_hdrp->uuid,
			POOL_HDR_UUID_LEN);
		break;
	case Q_PREV_PART_UUID_SET:
		CHECK_INFO(ppc, "%ssetting pool_hdr.prev_part_uuid to %s",
			loc->prefix,
			check_get_uuid_str(loc->prev_part_hdrp->uuid));
		memcpy(loc->hdr.prev_part_uuid, loc->prev_part_hdrp->uuid,
			POOL_HDR_UUID_LEN);
		break;
	case Q_NEXT_REPL_UUID_SET:
		CHECK_INFO(ppc, "%ssetting pool_hdr.next_repl_uuid to %s",
			loc->prefix,
			check_get_uuid_str(loc->next_repl_hdrp->uuid));
		memcpy(loc->hdr.next_repl_uuid, loc->next_repl_hdrp->uuid,
			POOL_HDR_UUID_LEN);
		break;
	case Q_PREV_REPL_UUID_SET:
		CHECK_INFO(ppc, "%ssetting pool_hdr.prev_repl_uuid to %s",
			loc->prefix,
			check_get_uuid_str(loc->prev_repl_hdrp->uuid));
		memcpy(loc->hdr.prev_repl_uuid, loc->prev_repl_hdrp->uuid,
			POOL_HDR_UUID_LEN);
		break;
	default:
		ERR("not implemented question id: %u", question);
	}

	return 0;
}
コード例 #8
0
ファイル: check_backup.c プロジェクト: tomaszkapela/nvml
/*
 * backup_poolset -- (internal) backup the poolset
 */
static int
backup_poolset(PMEMpoolcheck *ppc, location *loc, int overwrite)
{
	struct pool_replica *srep = ppc->pool->set_file->poolset->replica[0];
	struct pool_replica *drep = loc->set->replica[0];
	for (unsigned p = 0; p < srep->nparts; p++) {
		if (overwrite == 0) {
			CHECK_INFO(ppc, "creating backup file: %s",
				drep->part[p].path);
		}
		if (pool_set_part_copy(&drep->part[p], &srep->part[p],
				overwrite)) {
			location_release(loc);
			ppc->result = CHECK_RESULT_ERROR;
			CHECK_INFO(ppc, "unable to create backup file");
			return CHECK_ERR(ppc, "unable to backup poolset");
		}
	}

	return 0;
}
コード例 #9
0
ファイル: check_backup.c プロジェクト: tomaszkapela/nvml
/*
 * backup_nonpoolset_create -- (internal) create backup
 */
static int
backup_nonpoolset_create(PMEMpoolcheck *ppc, location *loc)
{
	CHECK_INFO(ppc, "creating backup file: %s", ppc->backup_path);

	if (pool_copy(ppc->pool, ppc->backup_path, 0)) {
		location_release(loc);
		ppc->result = CHECK_RESULT_ERROR;
		return CHECK_ERR(ppc, "cannot perform backup");
	}

	location_release(loc);
	loc->step = CHECK_STEP_COMPLETE;
	return 0;
}
コード例 #10
0
ファイル: check_sds.c プロジェクト: krzycz/nvml
/*
 * sds_fix -- (internal) fix shutdown state
 */
static int
sds_fix(PMEMpoolcheck *ppc, location *loc, uint32_t question,
	void *context)
{
	LOG(3, NULL);

	switch (question) {
	case Q_RESET_SDS:
		CHECK_INFO(ppc, "%sresetting pool_hdr.sds", loc->prefix);
		memset(&loc->hdr.sds, 0, sizeof(loc->hdr.sds));
		++loc->healthy_replicas;
		break;
	default:
		ERR("not implemented question id: %u", question);
	}
	return 0;
}
コード例 #11
0
ファイル: check_pool_hdr.c プロジェクト: plebioda/nvml
/*
 * pool_hdr_checksum_fix -- (internal) fix checksum
 */
static int
pool_hdr_checksum_fix(PMEMpoolcheck *ppc, location *loc, uint32_t question,
	void *context)
{
	LOG(3, NULL);

	ASSERTne(loc, NULL);

	switch (question) {
	case Q_CHECKSUM:
		util_checksum(&loc->hdr, sizeof(loc->hdr), &loc->hdr.checksum,
			1, POOL_HDR_CSUM_END_OFF);
		CHECK_INFO(ppc, "%ssetting pool_hdr.checksum to 0x%jx",
			loc->prefix, le64toh(loc->hdr.checksum));
		break;
	default:
		ERR("not implemented question id: %u", question);
	}

	return 0;
}
コード例 #12
0
ファイル: check_pool_hdr.c プロジェクト: plebioda/nvml
/*
 * pool_hdr_checksum -- (internal) validate checksum
 */
static int
pool_hdr_checksum(PMEMpoolcheck *ppc, location *loc)
{
	LOG(3, NULL);

	if (loc->hdr_valid)
		return 0;

	if (CHECK_IS_NOT(ppc, REPAIR)) {
		ppc->result = CHECK_RESULT_NOT_CONSISTENT;
		return CHECK_ERR(ppc, INVALID_CHECKSUM, 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, INVALID_CHECKSUM, loc->prefix);
	}

	CHECK_ASK(ppc, Q_CHECKSUM, INVALID_CHECKSUM ".|Do you want to "
		"regenerate checksum?", loc->prefix);
	return check_questions_sequence_validate(ppc);
}
コード例 #13
0
ファイル: check_pool_hdr.c プロジェクト: plebioda/nvml
/*
 * pool_hdr_default_fix -- (internal) fix some default values in pool header
 */
static int
pool_hdr_default_fix(PMEMpoolcheck *ppc, location *loc, uint32_t question,
	void *context)
{
	LOG(3, NULL);

	ASSERTne(loc, NULL);
	struct pool_hdr def_hdr;
	pool_hdr_default(ppc->pool->params.type, &def_hdr);

	switch (question) {
	case Q_DEFAULT_SIGNATURE:
		CHECK_INFO(ppc, "%ssetting pool_hdr.signature to %.8s",
			loc->prefix, def_hdr.signature);
		memcpy(&loc->hdr.signature, &def_hdr.signature,
			POOL_HDR_SIG_LEN);
		break;
	case Q_DEFAULT_MAJOR:
		CHECK_INFO(ppc, "%ssetting pool_hdr.major to 0x%x", loc->prefix,
			def_hdr.major);
		loc->hdr.major = def_hdr.major;
		break;
	case Q_DEFAULT_COMPAT_FEATURES:
		CHECK_INFO(ppc, "%ssetting pool_hdr.compat_features to 0x%x",
			loc->prefix, def_hdr.compat_features);
		loc->hdr.compat_features = def_hdr.compat_features;
		break;
	case Q_DEFAULT_INCOMPAT_FEATURES:
		CHECK_INFO(ppc, "%ssetting pool_hdr.incompat_features to 0x%x",
			loc->prefix, def_hdr.incompat_features);
		loc->hdr.incompat_features = def_hdr.incompat_features;
		break;
	case Q_DEFAULT_RO_COMPAT_FEATURES:
		CHECK_INFO(ppc, "%ssetting pool_hdr.ro_compat_features to 0x%x",
			loc->prefix, def_hdr.ro_compat_features);
		loc->hdr.ro_compat_features = def_hdr.ro_compat_features;
		break;
	case Q_ZERO_UNUSED_AREA:
		CHECK_INFO(ppc, "%ssetting pool_hdr.unused to zeros",
			loc->prefix);
		memset(loc->hdr.unused, 0, sizeof(loc->hdr.unused));
		break;
	default:
		ERR("not implemented question id: %u", question);
	}

	return 0;
}
コード例 #14
0
ファイル: check_pool_hdr.c プロジェクト: plebioda/nvml
/*
 * pool_hdr_nondefault -- (internal) validate custom value fields
 */
static int
pool_hdr_nondefault(PMEMpoolcheck *ppc, location *loc)
{
	LOG(3, NULL);

	if (loc->hdr.crtime > (uint64_t)ppc->pool->set_file->mtime) {
		const char *error = "%spool_hdr.crtime is not valid";
		if (CHECK_IS_NOT(ppc, REPAIR)) {
			ppc->result = CHECK_RESULT_NOT_CONSISTENT;
			return CHECK_ERR(ppc, error, 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, error, loc->prefix);
		}

		CHECK_ASK(ppc, Q_CRTIME,
			"%spool_hdr.crtime is not valid.|Do you want to set it "
			"to file's modtime [%s]?", loc->prefix,
			check_get_time_str(ppc->pool->set_file->mtime));
	}

	if (loc->valid_part_hdrp &&
			memcmp(&loc->valid_part_hdrp->arch_flags,
				&loc->hdr.arch_flags,
				sizeof(struct arch_flags)) != 0) {
		const char *error = "%spool_hdr.arch_flags is not valid";
		if (CHECK_IS_NOT(ppc, REPAIR)) {
			ppc->result = CHECK_RESULT_NOT_CONSISTENT;
			return CHECK_ERR(ppc, error, loc->prefix);
		}

		CHECK_ASK(ppc, Q_ARCH_FLAGS,
			"%spool_hdr.arch_flags is not valid.|Do you want to "
			"copy it from a valid part?", loc->prefix);
	}

	return check_questions_sequence_validate(ppc);
}
コード例 #15
0
ファイル: check_backup.c プロジェクト: tomaszkapela/nvml
/*
 * backup_poolset_requirements -- (internal) check backup requirements
 */
static int
backup_poolset_requirements(PMEMpoolcheck *ppc, location *loc)
{
	LOG(3, "backup_path %s", ppc->backup_path);

	if (ppc->pool->set_file->poolset->nreplicas > 1) {
		CHECK_INFO(ppc,
			"backup of a poolset with multiple replicas is not supported");
		goto err;
	}

	if (pool_set_parse(&loc->set, ppc->backup_path)) {
		CHECK_INFO(ppc, "invalid poolset backup file: %s",
			ppc->backup_path);
		goto err;
	}

	if (loc->set->nreplicas > 1) {
		CHECK_INFO(ppc,
			"backup to a poolset with multiple replicas is not supported");
		goto err_poolset;
	}

	ASSERTeq(loc->set->nreplicas, 1);
	struct pool_replica *srep = ppc->pool->set_file->poolset->replica[0];
	struct pool_replica *drep = loc->set->replica[0];
	if (srep->nparts != drep->nparts) {
		CHECK_INFO(ppc,
			"number of part files in the backup poolset must match number of part files in the source poolset");
		goto err_poolset;
	}

	int overwrite_required = 0;
	for (unsigned p = 0; p < srep->nparts; p++) {
		if (srep->part[p].filesize != drep->part[p].filesize) {
			CHECK_INFO(ppc,
				"size of the part %u of the backup poolset does not match source poolset",
				p);
			goto err_poolset;
		}

		if (os_access(drep->part[p].path, F_OK)) {
			if (errno == ENOENT) {
				errno = 0;
				continue;
			} else {
				CHECK_INFO(ppc,
					"unable to access the part of the destination poolset: %s",
					ppc->backup_path);
				goto err_poolset;
			}
		}

		overwrite_required = true;

		if ((size_t)util_file_get_size(drep->part[p].path) !=
				srep->part[p].filesize) {
			CHECK_INFO(ppc,
				"destination of the backup part does not match size of the source part file: %s",
				drep->part[p].path);
			goto err_poolset;
		}
	}

	if (CHECK_WITHOUT_FIXING(ppc)) {
		location_release(loc);
		loc->step = CHECK_STEP_COMPLETE;
		return 0;
	}

	if (overwrite_required) {
		CHECK_ASK(ppc, Q_OVERWRITE_EXISTING_PARTS,
			"part files of the destination poolset of the backup already exist.|"
			"Do you want to overwrite them?");
	}

	return check_questions_sequence_validate(ppc);

err_poolset:
	location_release(loc);
err:
	ppc->result = CHECK_RESULT_ERROR;
	return CHECK_ERR(ppc, "unable to backup poolset");
}
コード例 #16
0
ファイル: check_cto.c プロジェクト: GBuella/nvml
/*
 * cto_hdr_check -- (internal) check pmemcto header
 */
static int
cto_hdr_check(PMEMpoolcheck *ppc, location *loc)
{
	LOG(3, NULL);

	CHECK_INFO(ppc, "checking pmemcto header");

	if (cto_read(ppc)) {
		ppc->result = CHECK_RESULT_ERROR;
		return -1;
	}

	if (ppc->pool->hdr.cto.consistent == 0) {
		if (CHECK_ASK(ppc, Q_CTO_CONSISTENT,
				"pmemcto.consistent flag is not set.|Do you want to set pmemcto.consistent flag?"))
			goto error;
	}

	if ((void *)ppc->pool->hdr.cto.addr == NULL) {
		if (CHECK_ASK(ppc, Q_CTO_ADDR,
				"invalid pmemcto.addr: %p.|Do you want to recover pmemcto.addr?",
				(void *)ppc->pool->hdr.cto.addr))
			goto error;
	}

	if (ppc->pool->hdr.cto.size < PMEMCTO_MIN_POOL) {
		CHECK_INFO(ppc,
			"pmemcto.size is less than minimum: %zu < %zu.",
			ppc->pool->hdr.cto.size,
			PMEMCTO_MIN_POOL);
	}

	if (ppc->pool->hdr.cto.size != ppc->pool->params.size) {
		if (CHECK_ASK(ppc, Q_CTO_SIZE,
				"pmemcto.size is different than pool size: %zu != %zu.|Do you want to set pmemlog.size to the actual pool size?",
				ppc->pool->hdr.cto.size,
				ppc->pool->params.size))
			goto error;
	}

	char *valid_addr_begin =
		(char *)ppc->pool->hdr.cto.addr + CTO_DSC_SIZE_ALIGNED;
	char *valid_addr_end =
		(char *)ppc->pool->hdr.cto.addr + ppc->pool->hdr.cto.size;

	if ((void *)ppc->pool->hdr.cto.root != NULL &&
	    ((char *)ppc->pool->hdr.cto.root < valid_addr_begin ||
	    (char *)ppc->pool->hdr.cto.root >= valid_addr_end)) {
		if (CHECK_ASK(ppc, Q_CTO_ROOT,
				"invalid pmemcto.root: %p.|Do you want to recover pmemcto.root?",
				(void *)ppc->pool->hdr.cto.root))
			goto error;
	}

	if (ppc->result == CHECK_RESULT_CONSISTENT ||
		ppc->result == CHECK_RESULT_REPAIRED)
		CHECK_INFO(ppc, "pmemcto header correct");

	return check_questions_sequence_validate(ppc);

error:
	ppc->result = CHECK_RESULT_NOT_CONSISTENT;
	check_end(ppc->data);
	return -1;
}
コード例 #17
0
ファイル: check_pool_hdr.c プロジェクト: plebioda/nvml
/*
 * 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);
}
コード例 #18
0
ファイル: check_pool_hdr.c プロジェクト: plebioda/nvml
/*
 * 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);
}