/* * check_pool -- check if remote pool contains specified random sequence */ static int check_pool(const struct test_case *tc, int argc, char *argv[]) { if (argc < 3) UT_FATAL("usage: fill_pool <pool set> <seed> <size>"); char *pool_set = argv[0]; srand(atoi(argv[1])); int ret; size_t size; ret = util_parse_size(argv[2], &size); struct pool_set *set; ret = util_pool_open_nocheck(&set, pool_set, 0); UT_ASSERTeq(ret, 0); uint8_t *data = set->replica[0]->part[0].addr; for (size_t i = 0; i < size; i++) { uint8_t r = rand(); UT_ASSERTeq(data[POOL_HDR_SIZE + i], r); } util_poolset_close(set, 0); return 3; }
/* * 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; }
/* * fill_pool -- fill remote pool with specified random sequence */ static int fill_pool(const struct test_case *tc, int argc, char *argv[]) { if (argc < 2) UT_FATAL("usage: fill_pool <pool set> <seed>"); char *pool_set = argv[0]; srand(atoi(argv[1])); int ret; struct pool_set *set; ret = util_pool_open_nocheck(&set, pool_set, 0); UT_ASSERTeq(ret, 0); uint8_t *data = set->replica[0]->part[0].addr; for (size_t i = POOL_HDR_SIZE; i < set->poolsize; i++) data[i] = rand(); util_poolset_close(set, 0); return 2; }
/* * 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; }