Beispiel #1
0
/*
 * 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;
}
Beispiel #2
0
/*
 * pool_set_map -- (internal) map poolset
 */
static int
pool_set_map(const char *fname, struct pool_set **poolset, int rdonly)
{
	ASSERTeq(util_is_poolset_file(fname), 1);

	struct pool_hdr hdr;
	if (pool_set_read_header(fname, &hdr))
		return -1;

	util_convert2h_hdr_nocheck(&hdr);

	/* parse pool type from first pool set file */
	enum pool_type type = pool_hdr_get_type(&hdr);
	if (type == POOL_TYPE_UNKNOWN) {
		ERR("cannot determine pool type from poolset");
		return -1;
	}

	/* get minimum size based on pool type for util_pool_open */
	size_t minsize = pool_get_min_size(type);

	/*
	 * Open the poolset, the values passed to util_pool_open are read
	 * from the first poolset file, these values are then compared with
	 * the values from all headers of poolset files.
	 */
	if (util_pool_open(poolset, fname, rdonly, minsize, hdr.signature,
			hdr.major, hdr.compat_features, hdr.incompat_features,
			hdr.ro_compat_features, NULL)) {
		ERR("opening poolset failed");
		return -1;
	}

	return 0;
}
Beispiel #3
0
/*
 * pool_set_map -- (internal) map poolset
 */
static int
pool_set_map(const char *fname, struct pool_set **poolset, unsigned flags)
{
	ASSERTeq(util_is_poolset_file(fname), 1);

	struct pool_hdr hdr;
	if (pool_set_read_header(fname, &hdr))
		return -1;

	util_convert2h_hdr_nocheck(&hdr);

	/* parse pool type from first pool set file */
	enum pool_type type = pool_hdr_get_type(&hdr);
	if (type == POOL_TYPE_UNKNOWN) {
		ERR("cannot determine pool type from poolset");
		return -1;
	}

	/*
	 * Open the poolset, the values passed to util_pool_open are read
	 * from the first poolset file, these values are then compared with
	 * the values from all headers of poolset files.
	 */
	struct pool_attr attr;
	util_pool_hdr2attr(&attr, &hdr);
	if (util_pool_open(poolset, fname, 0 /* minpartsize */, &attr,
				NULL, NULL, flags | POOL_OPEN_IGNORE_SDS |
						POOL_OPEN_IGNORE_BAD_BLOCKS)) {
		ERR("opening poolset failed");
		return -1;
	}

	return 0;
}
Beispiel #4
0
/*
 * pool_set_type -- get pool type of a poolset
 */
enum pool_type
pool_set_type(struct pool_set *set)
{
	struct pool_hdr hdr;

	/* open the first part file to read the pool header values */
	const struct pool_set_part *part = &PART(REP(set, 0), 0);
	int fdp = util_file_open(part->path, NULL, 0, O_RDONLY);
	if (fdp < 0) {
		ERR("cannot open poolset part file");
		return POOL_TYPE_UNKNOWN;
	}

	/* read the pool header from first pool set file */
	if (read(fdp, &hdr, sizeof(hdr)) != sizeof(hdr)) {
		ERR("cannot read pool header from poolset");
		close(fdp);
		return POOL_TYPE_UNKNOWN;
	}

	close(fdp);
	util_convert2h_hdr_nocheck(&hdr);
	enum pool_type type = pool_hdr_get_type(&hdr);
	return type;
}
Beispiel #5
0
/*
 * pool_set_type -- get pool type of a poolset
 */
enum pool_type
pool_set_type(struct pool_set *set)
{
	struct pool_hdr hdr;

	/* open the first part file to read the pool header values */
	const struct pool_set_part *part = &PART(REP(set, 0), 0);

	if (util_file_pread(part->path, &hdr, sizeof(hdr), 0) !=
			sizeof(hdr)) {
		ERR("cannot read pool header from poolset");
		return POOL_TYPE_UNKNOWN;
	}

	util_convert2h_hdr_nocheck(&hdr);
	enum pool_type type = pool_hdr_get_type(&hdr);
	return type;
}
Beispiel #6
0
/*
 * util_convert_hdr -- convert header to host byte order & validate
 *
 * Returns true if header is valid, and all the integer fields are
 * converted to host byte order.  If the header is not valid, this
 * routine returns false and the header passed in is left in an
 * unknown state.
 */
int
util_convert_hdr(struct pool_hdr *hdrp)
{
	LOG(3, "hdrp %p", hdrp);

	util_convert2h_hdr_nocheck(hdrp);

	/* to be valid, a header must have a major version of at least 1 */
	if (hdrp->major == 0) {
		ERR("invalid major version (0)");
		return 0;
	}

	/* and to be valid, the fields must checksum correctly */
	if (!util_checksum(hdrp, sizeof(*hdrp), &hdrp->checksum, 0)) {
		ERR("invalid checksum of pool header");
		return 0;
	}

	LOG(3, "valid header, signature \"%.8s\"", hdrp->signature);
	return 1;
}
Beispiel #7
0
/*
 * pmempool_info_pool_hdr -- (internal) print pool header information
 */
static int
pmempool_info_pool_hdr(struct pmem_info *pip, int v)
{
	static const char *alignment_desc_str[] = {
		"  char",
		"  short",
		"  int",
		"  long",
		"  long long",
		"  size_t",
		"  off_t",
		"  float",
		"  double",
		"  long double",
		"  void *",
	};
	static const size_t alignment_desc_n =
		sizeof(alignment_desc_str) / sizeof(alignment_desc_str[0]);

	int ret = 0;
	struct pool_hdr *hdr = malloc(sizeof(struct pool_hdr));
	if (!hdr)
		err(1, "Cannot allocate memory for pool_hdr");

	if (pmempool_info_read(pip, hdr, sizeof(*hdr), 0)) {
		outv_err("cannot read pool header\n");
		free(hdr);
		return -1;
	}

	struct arch_flags arch_flags;
	if (util_get_arch_flags(&arch_flags)) {
		outv_err("cannot read architecture flags\n");
		free(hdr);
		return -1;
	}

	outv_title(v, "POOL Header");
	outv_hexdump(pip->args.vhdrdump, hdr, sizeof(*hdr), 0, 1);

	util_convert2h_hdr_nocheck(hdr);

	outv_field(v, "Signature", "%.*s%s", POOL_HDR_SIG_LEN,
			hdr->signature,
			pip->params.is_part ?
			" [part file]" : "");
	outv_field(v, "Major", "%d", hdr->major);
	outv_field(v, "Mandatory features", "0x%x", hdr->incompat_features);
	outv_field(v, "Not mandatory features", "0x%x", hdr->compat_features);
	outv_field(v, "Forced RO", "0x%x", hdr->ro_compat_features);
	outv_field(v, "Pool set UUID", "%s",
				out_get_uuid_str(hdr->poolset_uuid));
	outv_field(v, "UUID", "%s", out_get_uuid_str(hdr->uuid));
	outv_field(v, "Previous part UUID", "%s",
				out_get_uuid_str(hdr->prev_part_uuid));
	outv_field(v, "Next part UUID", "%s",
				out_get_uuid_str(hdr->next_part_uuid));
	outv_field(v, "Previous replica UUID", "%s",
				out_get_uuid_str(hdr->prev_repl_uuid));
	outv_field(v, "Next replica UUID", "%s",
				out_get_uuid_str(hdr->next_repl_uuid));
	outv_field(v, "Creation Time", "%s",
			out_get_time_str((time_t)hdr->crtime));

	uint64_t ad = hdr->arch_flags.alignment_desc;
	uint64_t cur_ad = arch_flags.alignment_desc;

	outv_field(v, "Alignment Descriptor", "%s",
			out_get_alignment_desc_str(ad, cur_ad));

	for (size_t i = 0; i < alignment_desc_n; i++) {
		uint64_t a = GET_ALIGNMENT(ad, i);
		if (ad == cur_ad) {
			outv_field(v + 1, alignment_desc_str[i],
					"%2lu", a);
		} else {
			uint64_t av = GET_ALIGNMENT(cur_ad, i);
			if (a == av) {
				outv_field(v + 1, alignment_desc_str[i],
					"%2lu [OK]", a);
			} else {
				outv_field(v + 1, alignment_desc_str[i],
					"%2lu [wrong! should be %2lu]", a, av);
			}
		}
	}

	outv_field(v, "Class", "%s",
			out_get_ei_class_str(hdr->arch_flags.ei_class));
	outv_field(v, "Data", "%s",
			out_get_ei_data_str(hdr->arch_flags.ei_data));
	outv_field(v, "Machine", "%s",
			out_get_e_machine_str(hdr->arch_flags.e_machine));

	outv_field(v, "Checksum", "%s", out_get_checksum(hdr, sizeof(*hdr),
				&hdr->checksum));

	free(hdr);

	return ret;
}
Beispiel #8
0
/*
 * pool_parse_params -- parse pool type, file size and block size
 */
static int
pool_params_parse(const PMEMpoolcheck *ppc, struct pool_params *params,
	int check)
{
	LOG(3, NULL);
	int is_btt = ppc->args.pool_type == PMEMPOOL_POOL_TYPE_BTT;

	params->type = POOL_TYPE_UNKNOWN;
	params->is_poolset = util_is_poolset_file(ppc->path) == 1;

	int fd = util_file_open(ppc->path, NULL, 0, O_RDONLY);
	if (fd < 0)
		return -1;

	int ret = 0;

	util_stat_t stat_buf;
	ret = util_fstat(fd, &stat_buf);
	if (ret)
		goto out_close;

	ASSERT(stat_buf.st_size >= 0);

	params->mode = stat_buf.st_mode;

	struct pool_set *set;
	void *addr;
	if (params->is_poolset) {
		/*
		 * Need to close the poolset because it will be opened with
		 * flock in the following instructions.
		 */
		close(fd);
		fd = -1;

		if (check) {
			if (pool_set_map(ppc->path, &set, 0))
				return -1;
		} else {
			ret = util_poolset_create_set(&set, ppc->path, 0, 0);
			if (ret < 0) {
				LOG(2, "cannot open pool set -- '%s'",
					ppc->path);
				return -1;
			}
			if (set->remote) {
				ERR("poolsets with remote replicas are not "
					"supported");
				return -1;
			}
			if (util_pool_open_nocheck(set, 0))
				return -1;
		}

		params->size = set->poolsize;
		addr = set->replica[0]->part[0].addr;

		/*
		 * XXX mprotect for device dax with length not aligned to its
		 * page granularity causes SIGBUS on the next page fault.
		 * The length argument of this call should be changed to
		 * set->poolsize once the kernel issue is solved.
		 */
		if (mprotect(addr, set->replica[0]->repsize,
			PROT_READ) < 0) {
			ERR("!mprotect");
			goto out_unmap;
		}
		params->is_device_dax = set->replica[0]->part[0].is_dax;
	} else if (is_btt) {
		params->size = (size_t)stat_buf.st_size;
#ifndef _WIN32
		if (params->mode & S_IFBLK)
			if (ioctl(fd, BLKGETSIZE64, &params->size)) {
				ERR("!ioctl");
				goto out_close;
			}
#endif
		addr = NULL;
	} else {
		ssize_t s = util_file_get_size(ppc->path);
		if (s < 0) {
			ret = -1;
			goto out_close;
		}
		params->size = (size_t)s;
		addr = mmap(NULL, (uint64_t)params->size, PROT_READ,
			MAP_PRIVATE, fd, 0);
		if (addr == MAP_FAILED) {
			ret = -1;
			goto out_close;
		}
		params->is_device_dax = util_file_is_device_dax(ppc->path);
	}

	/* stop processing for BTT device */
	if (is_btt) {
		params->type = POOL_TYPE_BTT;
		params->is_part = false;
		goto out_close;
	}

	struct pool_hdr hdr;
	memcpy(&hdr, addr, sizeof(hdr));
	util_convert2h_hdr_nocheck(&hdr);
	pool_params_from_header(params, &hdr);

	if (ppc->args.pool_type != PMEMPOOL_POOL_TYPE_DETECT) {
		enum pool_type declared_type =
			pmempool_check_type_to_pool_type(ppc->args.pool_type);
		if ((params->type & ~declared_type) != 0) {
			ERR("declared pool type does not match");
			ret = 1;
			goto out_unmap;
		}
	}

	if (params->type == POOL_TYPE_BLK) {
		struct pmemblk pbp;
		memcpy(&pbp, addr, sizeof(pbp));
		params->blk.bsize = le32toh(pbp.bsize);
	} else if (params->type == POOL_TYPE_OBJ) {
		struct pmemobjpool pop;
		memcpy(&pop, addr, sizeof(pop));
		memcpy(params->obj.layout, pop.layout,
			PMEMOBJ_MAX_LAYOUT);
	}

out_unmap:
	if (params->is_poolset) {
		ASSERTeq(fd, -1);
		ASSERTne(addr, NULL);
		util_poolset_close(set, 0);
	} else if (!is_btt) {
		ASSERTne(fd, -1);
		ASSERTne(addr, NULL);
		munmap(addr, params->size);
	}
out_close:
	if (fd != -1)
		close(fd);
	return ret;
}