예제 #1
0
파일: file.c 프로젝트: ChandKV/nvml
/*
 * util_file_pread -- reads from a file with an offset
 */
ssize_t
util_file_pread(const char *path, void *buffer, size_t size,
	off_t offset)
{
	if (!util_file_is_device_dax(path)) {
		int fd = util_file_open(path, NULL, 0, O_RDONLY);
		if (fd < 0)
			return -1;

		ssize_t read_len = pread(fd, buffer, size, offset);
		int olderrno = errno;
		(void) close(fd);
		errno = olderrno;
		return read_len;
	}

	ssize_t file_size = util_file_get_size(path);
	if (file_size < 0)
		return -1;

	size_t max_size = (size_t)(file_size - offset);
	if (size > max_size) {
		LOG(1, "Requested size of read goes beyond the mapped memory");
		size = max_size;
	}

	void *addr = util_file_map_whole(path);
	if (addr == NULL)
		return -1;

	memcpy(buffer, ADDR_SUM(addr, offset), size);
	util_unmap(addr, (size_t)file_size);
	return (ssize_t)size;
}
예제 #2
0
파일: pool.c 프로젝트: stellarhopper/nvml
/*
 * 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;
}
예제 #3
0
파일: file.c 프로젝트: krzycz/nvml
/*
 * util_unlink_flock -- flocks the file and unlinks it
 *
 * The unlink(2) call on a file which is opened and locked using flock(2)
 * by different process works on linux. Thus in order to forbid removing a
 * pool when in use by different process we need to flock(2) the pool files
 * first before unlinking.
 */
int
util_unlink_flock(const char *path)
{
	LOG(3, "path \"%s\"", path);

#ifdef WIN32
	/*
	 * On Windows it is not possible to unlink the
	 * file if it is flocked.
	 */
	return util_unlink(path);
#else
	int fd = util_file_open(path, NULL, 0, O_RDONLY);
	if (fd < 0) {
		LOG(2, "failed to open file \"%s\"", path);
		return -1;
	}

	int ret = util_unlink(path);

	(void) os_close(fd);

	return ret;
#endif
}
예제 #4
0
파일: pool.c 프로젝트: mslusarz/nvml
/*
 * pool_set_read_header -- (internal) read a header of a pool set
 */
static int
pool_set_read_header(const char *fname, struct pool_hdr *hdr)
{
	struct pool_set *set;
	int ret = 0;

	if (util_poolset_read(&set, fname)) {
		return -1;
	}
	/* open the first part set 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");
		ret = -1;
		goto err_pool_set;
	}

	/* read the pool header from first pool set file */
	if (pread(fdp, hdr, sizeof(*hdr), 0) != sizeof(*hdr)) {
		ERR("cannot read pool header from poolset");
		ret = -1;
		goto err_close_part;
	}

err_close_part:
	close(fdp);

err_pool_set:
	util_poolset_free(set);
	return ret;
}
예제 #5
0
파일: pool.c 프로젝트: krzycz/nvml
/*
 * pool_set_file_open -- (internal) opens pool set file or regular file
 */
static struct pool_set_file *
pool_set_file_open(const char *fname, struct pool_params *params, int rdonly)
{
	LOG(3, NULL);

	struct pool_set_file *file = calloc(1, sizeof(*file));
	if (!file)
		return NULL;

	file->fname = strdup(fname);
	if (!file->fname)
		goto err;

	const char *path = file->fname;

	if (params->type != POOL_TYPE_BTT) {
		int ret = util_poolset_create_set(&file->poolset, path,
			0, 0, true);
		if (ret < 0) {
			LOG(2, "cannot open pool set -- '%s'", path);
			goto err_free_fname;
		}
		unsigned flags = (rdonly ? POOL_OPEN_COW : 0) |
					POOL_OPEN_IGNORE_BAD_BLOCKS;
		if (util_pool_open_nocheck(file->poolset, flags))
			goto err_free_fname;

		file->size = file->poolset->poolsize;

		/* get modification time from the first part of first replica */
		path = file->poolset->replica[0]->part[0].path;
		file->addr = file->poolset->replica[0]->part[0].addr;
	} else {
		int oflag = rdonly ? O_RDONLY : O_RDWR;
		file->fd = util_file_open(fname, NULL, 0, oflag);
		file->size = params->size;
	}

	os_stat_t buf;
	if (os_stat(path, &buf)) {
		ERR("%s", path);
		goto err_close_poolset;
	}

	file->mtime = buf.st_mtime;
	file->mode = buf.st_mode;
	return file;

err_close_poolset:
	if (params->type != POOL_TYPE_BTT)
		util_poolset_close(file->poolset, DO_NOT_DELETE_PARTS);
	else if (file->fd != -1)
		os_close(file->fd);
err_free_fname:
	free(file->fname);
err:
	free(file);
	return NULL;
}
예제 #6
0
파일: set.c 프로젝트: jebtang/nvml
/*
 * util_poolset_open -- (internal) open memory pool set
 *
 * On success returns 0 and a pointer to a newly allocated structure
 * containing the info of all the parts of the pool set and replicas.
 */
static int
util_poolset_open(struct pool_set **setp, const char *path, size_t minsize)
{
	LOG(3, "setp %p path %s minsize %zu", setp, path, minsize);

	int oerrno;
	int ret = 0;
	int fd;
	size_t size = 0;

	/* do not check minsize */
	if ((fd = util_file_open(path, &size, 0, O_RDWR)) == -1)
		return -1;

	char signature[POOLSET_HDR_SIG_LEN];
	ret = read(fd, signature, POOLSET_HDR_SIG_LEN);
	if (ret < 0) {
		ERR("!read %d", fd);
		goto err;
	}

	if (ret < POOLSET_HDR_SIG_LEN ||
	    strncmp(signature, POOLSET_HDR_SIG, POOLSET_HDR_SIG_LEN)) {
		LOG(4, "not a pool set header");

		if (size < minsize) {
			ERR("size %zu smaller than %zu", size, minsize);
			errno = EINVAL;
			ret = -1;
			goto err;
		}

		*setp = util_poolset_single(path, size, fd, 0);
		if (*setp == NULL) {
			ret = -1;
			goto err;
		}

		/* do not close the file */
		return 0;
	}

	ret = util_poolset_parse(path, fd, setp);
	if (ret != 0)
		goto err;

	ret = util_poolset_files(*setp, minsize, 0);
	if (ret != 0)
		util_poolset_close(*setp, 0);

err:
	oerrno = errno;
	(void) close(fd);
	errno = oerrno;
	return ret;
}
예제 #7
0
/*
 * pmempool_sync -- synchronize replicas within a poolset
 */
int
pmempool_sync(const char *poolset, unsigned flags)
{
	ASSERTne(poolset, NULL);

	/* check if poolset has correct signature */
	if (util_is_poolset_file(poolset) != 1) {
		ERR("file is not a poolset file");
		goto err;
	}

	/* open poolset file */
	int fd = util_file_open(poolset, NULL, 0, O_RDONLY);
	if (fd < 0) {
		ERR("cannot open a poolset file");
		goto err;
	}

	/* fill up pool_set structure */
	struct pool_set *set = NULL;
	if (util_poolset_parse(&set, poolset, fd)) {
		ERR("parsing input poolset failed");
		goto err_close_file;
	}
	if (set->remote) {
		if (util_remote_load()) {
			ERR("remote replication not available");
			goto err_close_file;
		}
	}

	/* sync all replicas */
	if (sync_replica(set, flags)) {
		LOG(1, "Synchronization failed");
		goto err_close_all;
	}

	util_poolset_close(set, 0);
	close(fd);
	return 0;

err_close_all:
	util_poolset_close(set, 0);

err_close_file:
	close(fd);

err:
	if (errno == 0)
		errno = EINVAL;

	return -1;
}
예제 #8
0
파일: file.c 프로젝트: krzycz/nvml
/*
 * util_file_pread -- reads from a file with an offset
 */
ssize_t
util_file_pread(const char *path, void *buffer, size_t size,
	os_off_t offset)
{
	LOG(3, "path \"%s\" buffer %p size %zu offset %ju",
			path, buffer, size, offset);

	enum file_type type = util_file_get_type(path);
	if (type < 0)
		return -1;

	if (type == TYPE_NORMAL) {
		int fd = util_file_open(path, NULL, 0, O_RDONLY);
		if (fd < 0) {
			LOG(2, "failed to open file \"%s\"", path);
			return -1;
		}

		ssize_t read_len = pread(fd, buffer, size, offset);
		int olderrno = errno;
		(void) os_close(fd);
		errno = olderrno;
		return read_len;
	}

	ssize_t file_size = util_file_get_size(path);
	if (file_size < 0) {
		LOG(2, "cannot determine file length \"%s\"", path);
		return -1;
	}

	size_t max_size = (size_t)(file_size - offset);
	if (size > max_size) {
		LOG(2, "requested size of read goes beyond the file length, "
			"%zu > %zu", size, max_size);
		LOG(4, "adjusting size to %zu", max_size);
		size = max_size;
	}

	void *addr = util_file_map_whole(path);
	if (addr == NULL) {
		LOG(2, "failed to map entire file \"%s\"", path);
		return -1;
	}

	memcpy(buffer, ADDR_SUM(addr, offset), size);
	util_unmap(addr, (size_t)file_size);
	return (ssize_t)size;
}
예제 #9
0
파일: set.c 프로젝트: bgbhpe/nvml
/*
 * util_is_poolset -- check if specified file is a poolset
 *
 * Return value:
 * -1 - error
 *  0 - not a poolset
 *  1 - is a poolset
 */
int
util_is_poolset(const char *path)
{
	int fd = util_file_open(path, NULL, 0, O_RDONLY);
	if (fd < 0)
		return -1;

	int ret = 0;
	char poolset[POOLSET_HDR_SIG_LEN];
	if (read(fd, poolset, sizeof(poolset)) != sizeof(poolset)) {
		ret = -1;
		goto out;
	}

	if (memcmp(poolset, POOLSET_HDR_SIG, POOLSET_HDR_SIG_LEN) == 0)
		ret = 1;
out:
	close(fd);
	return ret;
}
예제 #10
0
파일: info.c 프로젝트: jebtang/nvml
/*
 * pmempool_info_get_pool_type -- get pool type to parse
 *
 * Return pool type to parse based on headers data and command line arguments.
 */
static pmem_pool_type_t
pmempool_info_get_pool_type(struct pmem_info *pip)
{

	int ret = 0;
	int is_poolset = !pmem_pool_check_pool_set(pip->file_name);
	struct pool_hdr hdr;

	pip->fd = util_file_open(pip->file_name, NULL, 0, O_RDONLY);
	if (pip->fd < 0) {
		warn("%s", pip->file_name);
		return PMEM_POOL_TYPE_UNKNOWN;
	}

	if (is_poolset) {
		if (pmempool_setup_poolset(pip))
			goto err;
	}

	if (pmempool_info_read(pip, &hdr, sizeof (hdr), 0)) {
		outv_err("cannot read pool header\n");
		goto err;
	}

	/*
	 * If force flag is set 'types' fields _must_ hold
	 * single pool type - this is validated when processing
	 * command line arguments.
	 */
	if (pip->args.force)
		return pip->args.type;

	/* parse pool type from pool header */
	ret = pmem_pool_type_parse_hdr(&hdr);

	return ret;
err:
	close(pip->fd);
	pip->fd = -1;
	return PMEM_POOL_TYPE_UNKNOWN;
}
예제 #11
0
파일: set.c 프로젝트: tgockel/nvml
/*
 * util_poolset_file -- (internal) open or create a single part file
 */
static int
util_poolset_file(struct pool_set_part *part, size_t minsize, int create)
{
	LOG(3, "part %p minsize %zu create %d", part, minsize, create);

	/* check if file exists */
	if (access(part->path, F_OK) == 0)
		create = 0;

	size_t size;

	if (create) {
		size = part->filesize;
		part->fd = util_file_create(part->path, size, minsize);
		part->created = 1;
		if (part->fd == -1) {
			LOG(2, "failed to create file: %s", part->path);
			return -1;
		}
	} else {
		size = 0;
		part->fd = util_file_open(part->path, &size, minsize, O_RDWR);
		part->created = 0;
		if (part->fd == -1) {
			LOG(2, "failed to open file: %s", part->path);
			return -1;
		}

		/* check if filesize matches */
		if (part->filesize != size) {
			ERR("file size does not match config: %s, %zu != %zu",
				part->path, size, part->filesize);
			errno = EINVAL;
			return -1;
		}
	}

	return 0;
}
예제 #12
0
int
main(int argc, char *argv[])
{
	START(argc, argv, "util_file_open");

	if (argc < 3)
		UT_FATAL("usage: %s minlen path...", argv[0]);

	char *fname;
	size_t minsize = strtoul(argv[1], &fname, 0);

	for (int arg = 2; arg < argc; arg++) {
		size_t size = 0;
		int fd = util_file_open(argv[arg], &size, minsize, O_RDWR);
		if (fd == -1)
			UT_OUT("!%s: util_file_open", argv[arg]);
		else {
			UT_OUT("%s: open, len %zu", argv[arg], size);
			close(fd);
		}
	}

	DONE(NULL);
}
예제 #13
0
파일: set.c 프로젝트: bgbhpe/nvml
/*
 * util_poolset_open -- (internal) open memory pool set
 *
 * On success returns 0 and a pointer to a newly allocated structure
 * containing the info of all the parts of the pool set and replicas.
 */
static int
util_poolset_open(struct pool_set **setp, const char *path, size_t minsize)
{
	LOG(3, "setp %p path %s minsize %zu", setp, path, minsize);

	int oerrno;
	int ret = 0;
	int fd;
	size_t size = 0;

	/* do not check minsize */
	if ((fd = util_file_open(path, &size, 0, O_RDONLY)) == -1)
		return -1;

	char signature[POOLSET_HDR_SIG_LEN];
	/*
	 * read returns ssize_t, but we know it will return value between -1
	 * and POOLSET_HDR_SIG_LEN (11), so we can safely cast it to int
	 */
	ret = (int)read(fd, signature, POOLSET_HDR_SIG_LEN);
	if (ret < 0) {
		ERR("!read %d", fd);
		goto err;
	}

	if (ret < POOLSET_HDR_SIG_LEN ||
	    strncmp(signature, POOLSET_HDR_SIG, POOLSET_HDR_SIG_LEN)) {
		LOG(4, "not a pool set header");

		if (size < minsize) {
			ERR("size %zu smaller than %zu", size, minsize);
			errno = EINVAL;
			ret = -1;
			goto err;
		}

		/* close the file and open with O_RDWR */
		(void) close(fd);
		size = 0;
		if ((fd = util_file_open(path, &size, 0, O_RDWR)) == -1)
			return -1;

		*setp = util_poolset_single(path, size, fd, 0);
		if (*setp == NULL) {
			ret = -1;
			goto err;
		}

		/* do not close the file */
		return 0;
	}

	ret = util_poolset_parse(path, fd, setp);
	if (ret != 0)
		goto err;

	ret = util_poolset_files(*setp, minsize, 0);
	if (ret != 0)
		util_poolset_close(*setp, 0);

err:
	oerrno = errno;
	(void) close(fd);
	errno = oerrno;
	return ret;
}
예제 #14
0
파일: pool.c 프로젝트: mslusarz/nvml
/*
 * pool_copy -- make a copy of the pool
 */
int
pool_copy(struct pool_data *pool, const char *dst_path, int overwrite)
{
	struct pool_set_file *file = pool->set_file;
	int dfd;
	if (!access(dst_path, F_OK)) {
		if (!overwrite) {
			errno = EEXIST;
			return -1;
		}
		dfd = util_file_open(dst_path, NULL, 0, O_RDWR);
	} else {
		if (errno == ENOENT) {
			errno = 0;
			dfd = util_file_create(dst_path, file->size, 0);
		} else {
			return -1;
		}
	}
	if (dfd < 0)
		return -1;

	int result = 0;
	util_stat_t stat_buf;
	if (util_stat(file->fname, &stat_buf)) {
		result = -1;
		goto out_close;
	}

	if (fchmod(dfd, stat_buf.st_mode)) {
		result = -1;
		goto out_close;
	}

	void *daddr = mmap(NULL, file->size, PROT_READ | PROT_WRITE,
		MAP_SHARED, dfd, 0);
	if (daddr == MAP_FAILED) {
		result = -1;
		goto out_close;
	}

	if (pool->params.type != POOL_TYPE_BTT) {
		void *saddr = pool_set_file_map(file, 0);
		memcpy(daddr, saddr, file->size);
		goto out_unmap;
	}

	void *buf = malloc(RW_BUFFERING_SIZE);
	if (buf == NULL) {
		ERR("!malloc");
		result = -1;
		goto out_unmap;
	}

	pool_btt_lseek(pool, 0, SEEK_SET);
	ssize_t buf_read = 0;
	void *dst = daddr;
	while ((buf_read = pool_btt_read(pool, buf, RW_BUFFERING_SIZE))) {
		if (buf_read == -1)
			break;

		memcpy(dst, buf, (size_t)buf_read);
		dst  = (void *)((ssize_t)dst + buf_read);
	}

	free(buf);
out_unmap:
	munmap(daddr, file->size);
out_close:
	if (dfd >= 0)
		close(dfd);
	return result;
}
예제 #15
0
파일: pool.c 프로젝트: mslusarz/nvml
/*
 * 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;
}
예제 #16
0
파일: replica.c 프로젝트: ChandKV/nvml
/*
 * pmempool_transform -- alter poolset structure
 */
int
pmempool_transform(const char *poolset_src,
		const char *poolset_dst, unsigned flags)
{
	LOG(3, "poolset_src %s, poolset_dst %s, flags %u", poolset_src,
			poolset_dst, flags);
	ASSERTne(poolset_src, NULL);
	ASSERTne(poolset_dst, NULL);

	/* check if the source poolset has correct signature */
	if (util_is_poolset_file(poolset_src) != 1) {
		ERR("source file is not a poolset file");
		goto err;
	}

	/* check if the destination poolset has correct signature */
	if (util_is_poolset_file(poolset_dst) != 1) {
		ERR("destination file is not a poolset file");
		goto err;
	}

	/* check if flags are supported */
	if (check_flags_transform(flags)) {
		ERR("unsupported flags");
		errno = EINVAL;
		goto err;
	}

	/* open the source poolset file */
	int fd_in = util_file_open(poolset_src, NULL, 0, O_RDONLY);
	if (fd_in < 0) {
		ERR("cannot open source poolset file");
		goto err;
	}

	/* parse the source poolset file */
	struct pool_set *set_in = NULL;
	if (util_poolset_parse(&set_in, poolset_src, fd_in)) {
		ERR("parsing source poolset failed");
		close(fd_in);
		goto err;
	}
	close(fd_in);

	/* open the destination poolset file */
	int fd_out = util_file_open(poolset_dst, NULL, 0, O_RDONLY);
	if (fd_out < 0) {
		ERR("cannot open destination poolset file");
		goto err;
	}

	int del = 0;

	/* parse the destination poolset file */
	struct pool_set *set_out = NULL;
	if (util_poolset_parse(&set_out, poolset_dst, fd_out)) {
		ERR("parsing destination poolset failed");
		close(fd_out);
		goto err_free_poolin;
	}
	close(fd_out);

	/* check if the source poolset is of a correct type */
	if (pool_set_type(set_in) != POOL_TYPE_OBJ) {
		ERR("source poolset is of a wrong type");
		goto err_free_poolout;
	}

	/* check if the source poolset is healthy */
	struct poolset_health_status *set_in_hs = NULL;
	if (replica_check_poolset_health(set_in, &set_in_hs, flags)) {
		ERR("source poolset health check failed");
		goto err_free_poolout;
	}

	if (!replica_is_poolset_healthy(set_in_hs)) {
		ERR("source poolset is broken");
		replica_free_poolset_health_status(set_in_hs);
		goto err_free_poolout;
	}

	replica_free_poolset_health_status(set_in_hs);

	del = !is_dry_run(flags);

	/* transform poolset */
	if (replica_transform(set_in, set_out, flags)) {
		ERR("transformation failed");
		goto err_free_poolout;
	}

	util_poolset_close(set_in, 0);
	util_poolset_close(set_out, 0);
	return 0;

err_free_poolout:
	util_poolset_close(set_out, del);

err_free_poolin:
	util_poolset_close(set_in, 0);

err:
	if (errno == 0)
		errno = EINVAL;

	return -1;
}
예제 #17
0
파일: replica.c 프로젝트: wojtuss/nvml
static inline
#endif
int
pmempool_transformU(const char *poolset_src,
		const char *poolset_dst, unsigned flags)
{
	LOG(3, "poolset_src %s, poolset_dst %s, flags %u", poolset_src,
			poolset_dst, flags);
	ASSERTne(poolset_src, NULL);
	ASSERTne(poolset_dst, NULL);

	/* check if the source poolset has correct signature */
	if (util_is_poolset_file(poolset_src) != 1) {
		ERR("source file is not a poolset file");
		goto err;
	}

	/* check if the destination poolset has correct signature */
	if (util_is_poolset_file(poolset_dst) != 1) {
		ERR("destination file is not a poolset file");
		goto err;
	}

	/* check if flags are supported */
	if (check_flags_transform(flags)) {
		ERR("unsupported flags");
		errno = EINVAL;
		goto err;
	}

	/* open the source poolset file */
	int fd_in = util_file_open(poolset_src, NULL, 0, O_RDONLY);
	if (fd_in < 0) {
		ERR("cannot open source poolset file");
		goto err;
	}

	/* parse the source poolset file */
	struct pool_set *set_in = NULL;
	if (util_poolset_parse(&set_in, poolset_src, fd_in)) {
		ERR("parsing source poolset failed");
		os_close(fd_in);
		goto err;
	}
	os_close(fd_in);

	/* open the destination poolset file */
	int fd_out = util_file_open(poolset_dst, NULL, 0, O_RDONLY);
	if (fd_out < 0) {
		ERR("cannot open destination poolset file");
		goto err;
	}

	enum del_parts_mode del = DO_NOT_DELETE_PARTS;

	/* parse the destination poolset file */
	struct pool_set *set_out = NULL;
	if (util_poolset_parse(&set_out, poolset_dst, fd_out)) {
		ERR("parsing destination poolset failed");
		os_close(fd_out);
		goto err_free_poolin;
	}
	os_close(fd_out);

	/* check if the source poolset is of a correct type */
	if (pool_set_type(set_in) != POOL_TYPE_OBJ) {
		ERR("source poolset is of a wrong type");
		goto err_free_poolout;
	}

	/* load remote library if needed */
	if (set_in->remote && util_remote_load()) {
		ERR("remote replication not available");
		goto err_free_poolout;
	}
	if (set_out->remote && util_remote_load()) {
		ERR("remote replication not available");
		goto err_free_poolout;
	}

	del = is_dry_run(flags) ? DO_NOT_DELETE_PARTS : DELETE_CREATED_PARTS;

	/* transform poolset */
	if (replica_transform(set_in, set_out, flags)) {
		ERR("transformation failed");
		goto err_free_poolout;
	}

	util_poolset_close(set_in, DO_NOT_DELETE_PARTS);
	util_poolset_close(set_out, DO_NOT_DELETE_PARTS);
	return 0;

err_free_poolout:
	util_poolset_close(set_out, del);

err_free_poolin:
	util_poolset_close(set_in, DO_NOT_DELETE_PARTS);

err:
	if (errno == 0)
		errno = EINVAL;

	return -1;
}
예제 #18
0
파일: replica.c 프로젝트: wojtuss/nvml
static inline
#endif
int
pmempool_syncU(const char *poolset, unsigned flags)
{
	LOG(3, "poolset %s, flags %u", poolset, flags);
	ASSERTne(poolset, NULL);

	/* check if poolset has correct signature */
	if (util_is_poolset_file(poolset) != 1) {
		ERR("file is not a poolset file");
		goto err;
	}

	/* check if flags are supported */
	if (check_flags_sync(flags)) {
		ERR("unsupported flags");
		errno = EINVAL;
		goto err;
	}

	/* open poolset file */
	int fd = util_file_open(poolset, NULL, 0, O_RDONLY);
	if (fd < 0) {
		ERR("cannot open a poolset file");
		goto err;
	}

	/* fill up pool_set structure */
	struct pool_set *set = NULL;
	if (util_poolset_parse(&set, poolset, fd)) {
		ERR("parsing input poolset failed");
		goto err_close_file;
	}

	if (set->remote && util_remote_load()) {
		ERR("remote replication not available");
		goto err_close_file;
	}

	/* sync all replicas */
	if (replica_sync(set, NULL, flags)) {
		LOG(1, "synchronization failed");
		goto err_close_all;
	}

	util_poolset_close(set, DO_NOT_DELETE_PARTS);
	os_close(fd);
	return 0;

err_close_all:
	util_poolset_close(set, DO_NOT_DELETE_PARTS);

err_close_file:
	os_close(fd);

err:
	if (errno == 0)
		errno = EINVAL;

	return -1;
}
예제 #19
0
파일: info.c 프로젝트: jebtang/nvml
/*
 * pmempool_setup_poolset -- parse poolset file and setup reading from it
 */
static int
pmempool_setup_poolset(struct pmem_info *pip)
{
	struct pool_set *set = NULL;
	int fd = -1;
	struct pool_hdr hdr;

	/* parse poolset file */
	if (util_poolset_parse(pip->file_name, pip->fd, &set)) {
		outv_err("parsing poolset file failed\n");
		return -1;
	}

	close(pip->fd);
	pip->fd = -1;

	/* open the first part set file to read the pool header values */
	int ret = 0;
	fd = util_file_open(set->replica[0]->part[0].path, NULL, 0, O_RDONLY);
	if (fd < 0) {
		outv_err("cannot open poolset part file\n");
		ret = -1;
		goto err_pool_set;
	}

	/* read the pool header from first pool set file */
	if (pread(fd, &hdr, sizeof (hdr), 0)
			!= sizeof (hdr)) {
		outv_err("cannot read pool header from poolset\n");
		ret = -1;
		goto err_close;
	}
	close(fd);
	fd = -1;

	util_convert2h_pool_hdr(&hdr);

	/* parse pool type from first pool set file */
	pmem_pool_type_t type = pmem_pool_type_parse_hdr(&hdr);
	if (type == PMEM_POOL_TYPE_UNKNOWN) {
		outv_err("cannot determine pool type from poolset\n");
		ret = -1;
		goto err_close;
	}

	/* get minimum size based on pool type for util_pool_open */
	size_t minsize = pmem_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(&pip->poolset, pip->file_name, 1, minsize,
		sizeof (struct pool_hdr),
		hdr.signature, hdr.major,
		hdr.compat_features,
		hdr.incompat_features,
		hdr.ro_compat_features)) {
		outv_err("openning poolset failed\n");
		ret = -1;
	}

err_close:
	if (fd != -1)
		close(fd);
err_pool_set:
	util_poolset_free(set);

	return ret;

}