/* * 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; }
/* * 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; }
/* * 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 }
/* * 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; }
/* * 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; }
/* * 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; }
/* * 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; }
/* * 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; }
/* * 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; }
/* * 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; }
/* * 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; }
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); }
/* * 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; }
/* * 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; }
/* * 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, ¶ms->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; }
/* * 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; }
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; }
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; }
/* * 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; }