/* * util_poolset_foreach_part -- walk through all poolset file parts * * Stops processing if callback returns non-zero value. * The value returned by callback is returned to the caller. * * Return value: * 0 - all part files have been processed * -1 - parsing poolset file error */ int util_poolset_foreach_part(const char *path, int (*cb)(const char *part_file, void *arg), void *arg) { int fd = open(path, O_RDONLY); if (fd < 0) return -1; struct pool_set *set; int ret = util_poolset_parse(path, fd, &set); if (ret) goto err_close; for (unsigned r = 0; r < set->nreplicas; r++) { for (unsigned p = 0; p < set->replica[r]->nparts; p++) { const char *part_file = set->replica[r]->part[p].path; ret = cb(part_file, arg); if (ret) goto out; } } out: util_poolset_free(set); err_close: close(fd); return ret; }
int main(int argc, char *argv[]) { START(argc, argv, "util_poolset_parse"); out_init(LOG_PREFIX, LOG_LEVEL_VAR, LOG_FILE_VAR, MAJOR_VERSION, MINOR_VERSION); if (argc < 2) FATAL("usage: %s set-file-name ...", argv[0]); struct pool_set *set; int fd; for (int i = 1; i < argc; i++) { const char *path = argv[i]; fd = OPEN(path, O_RDWR); int ret = util_poolset_parse(path, fd, &set); if (ret == 0) util_poolset_free(set); CLOSE(fd); } out_fini(); 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_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_poolset_read -- read memory pool set file * * 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. */ int util_poolset_read(struct pool_set **setp, const char *path) { LOG(3, "setp %p path %s", setp, path); int oerrno; int ret = 0; int fd; if ((fd = open(path, O_RDONLY)) < 0) return -1; ret = util_poolset_parse(path, fd, setp); oerrno = errno; (void) close(fd); errno = oerrno; return ret; }
/* * util_poolset_size -- get size of poolset, returns 0 on error */ size_t util_poolset_size(const char *path) { int fd = open(path, O_RDONLY); if (fd < 0) return 0; size_t size = 0; struct pool_set *set; if (util_poolset_parse(path, fd, &set)) goto err_close; size = set->poolsize; util_poolset_free(set); err_close: close(fd); return size; }
/* * pool_set_parse -- parse poolset file */ int pool_set_parse(struct pool_set **setp, const char *path) { LOG(3, "setp %p path %s", setp, path); int fd = open(path, O_RDONLY); int ret = 0; if (fd < 0) return 1; if (util_poolset_parse(setp, path, fd)) { ret = 1; goto err_close; } err_close: 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; }
/* * 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; }
/* * 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; }
static inline #endif int pmempool_rmU(const char *path, int flags) { LOG(3, "path %s flags %x", path, flags); int ret; if (flags & ~PMEMPOOL_RM_ALL_FLAGS) { ERR("invalid flags specified"); errno = EINVAL; return -1; } int is_poolset = util_is_poolset_file(path); if (is_poolset < 0) { os_stat_t buff; ret = os_stat(path, &buff); if (!ret) { if (S_ISDIR(buff.st_mode)) { errno = EISDIR; ERR("removing file failed"); return -1; } } ERR_F(flags, "removing file failed"); if (CHECK_FLAG(flags, FORCE)) return 0; return -1; } if (!is_poolset) { LOG(2, "%s: not a poolset file", path); return rm_local(path, flags, 0); } LOG(2, "%s: poolset file", path); /* fill up pool_set structure */ struct pool_set *set = NULL; int fd = os_open(path, O_RDONLY); if (fd == -1 || util_poolset_parse(&set, path, fd)) { ERR_F(flags, "parsing poolset file failed"); if (fd != -1) os_close(fd); if (CHECK_FLAG(flags, FORCE)) return 0; return -1; } os_close(fd); if (set->remote) { /* ignore error - it will be handled in rm_remote() */ (void) util_remote_load(); } util_poolset_free(set); struct cb_args args; args.flags = flags; args.error = 0; ret = util_poolset_foreach_part(path, rm_cb, &args); if (ret == -1) { ERR_F(flags, "parsing poolset file failed"); if (CHECK_FLAG(flags, FORCE)) return 0; return ret; } ASSERTeq(ret, 0); if (args.error) return args.error; if (CHECK_FLAG(flags, POOLSET_LOCAL)) { ret = rm_local(path, flags, 0); if (ret) { ERR_F(flags, "removing pool set file failed"); } else { LOG(3, "%s: removed", path); } if (CHECK_FLAG(flags, FORCE)) return 0; return ret; } return 0; }