/* * pool_data_alloc -- allocate pool data and open set_file */ struct pool_data * pool_data_alloc(PMEMpoolcheck *ppc) { LOG(3, NULL); struct pool_data *pool = malloc(sizeof(*pool)); if (!pool) { ERR("!malloc"); return NULL; } TAILQ_INIT(&pool->arenas); pool->narenas = 0; pool->blk_no_layout = 0; pool->uuid_op = UUID_NOP; pool->set_file = NULL; pool->bttc.valid = false; if (pool_params_parse(ppc, &pool->params, 0)) goto error; int rdonly = CHECK_WITHOUT_FIXING(ppc); pool->set_file = pool_set_file_open(ppc->path, &pool->params, rdonly); if (!pool->set_file) goto error; return pool; error: pool_data_free(pool); return NULL; }
/* * pool_data_alloc -- allocate pool data and open set_file */ struct pool_data * pool_data_alloc(PMEMpoolcheck *ppc) { LOG(3, NULL); struct pool_data *pool = malloc(sizeof(*pool)); if (!pool) { ERR("!malloc"); return NULL; } TAILQ_INIT(&pool->arenas); pool->narenas = 0; pool->blk_no_layout = 0; pool->uuid_op = UUID_NOP; pool->set_file = NULL; pool->bttc.valid = false; if (pool_params_parse(ppc, &pool->params, 0)) goto error; int rdonly = CHECK_IS_NOT(ppc, REPAIR); int prv = CHECK_IS(ppc, DRY_RUN); if (prv && pool->params.is_device_dax) { errno = ENOTSUP; ERR("!cannot perform a dry run on dax device"); goto error; } pool->set_file = pool_set_file_open(ppc->path, &pool->params, prv); if (pool->set_file == NULL) goto error; /* * 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 * pool->set_file->poolsize once the kernel issue is solved. */ if (rdonly && mprotect(pool->set_file->addr, pool->set_file->poolset->replica[0]->repsize, PROT_READ) < 0) goto error; if (pool->params.type != POOL_TYPE_BTT) { if (pool_set_file_map_headers(pool->set_file, rdonly, prv)) goto error; } return pool; error: pool_data_free(pool); return NULL; }
/* * pmempool_info_file -- print info about single file */ static int pmempool_info_file(struct pmem_info *pip, const char *file_name) { int ret = 0; pip->file_name = file_name; /* * If force flag is set 'types' fields _must_ hold * single pool type - this is validated when processing * command line arguments. */ if (pip->args.force) { pip->type = pip->args.type; } else { if (pmem_pool_parse_params(file_name, &pip->params, 1)) { if (errno) perror(file_name); else outv_err("%s: cannot determine type of pool\n", file_name); return -1; } pip->type = pip->params.type; } if (PMEM_POOL_TYPE_UNKNOWN == pip->type) { ret = -1; outv_err("%s: unknown pool type -- '%s'\n", file_name, pip->params.signature); } else { if (util_options_verify(pip->opts, pip->type)) return -1; pip->pfile = pool_set_file_open(file_name, 1, 1); if (!pip->pfile) { perror(file_name); return -1; } if (pip->args.obj.replica && pool_set_file_set_replica(pip->pfile, pip->args.obj.replica)) { outv_err("invalid replica number '%lu'", pip->args.obj.replica); } /* hdr info is not present in btt device */ if (pip->type != PMEM_POOL_TYPE_BTT) { if (pmempool_info_pool_hdr(pip, VERBOSE_DEFAULT)) { ret = -1; goto out_close; } } if (pip->params.is_part) { ret = 0; goto out_close; } switch (pip->type) { case PMEM_POOL_TYPE_LOG: ret = pmempool_info_log(pip); break; case PMEM_POOL_TYPE_BLK: ret = pmempool_info_blk(pip); break; case PMEM_POOL_TYPE_OBJ: ret = pmempool_info_obj(pip); break; case PMEM_POOL_TYPE_BTT: ret = pmempool_info_btt(pip); break; case PMEM_POOL_TYPE_UNKNOWN: default: ret = -1; break; } out_close: pool_set_file_close(pip->pfile); } return ret; }
/* * pmempool_info_file -- print info about single file */ static int pmempool_info_file(struct pmem_info *pip, const char *file_name) { int ret = 0; pip->file_name = file_name; /* * If force flag is set 'types' fields _must_ hold * single pool type - this is validated when processing * command line arguments. */ if (pip->args.force) { pip->type = pip->args.type; } else { if (pmem_pool_parse_params(file_name, &pip->params, 1)) { if (errno) perror(file_name); else outv_err("%s: cannot determine type of pool\n", file_name); return -1; } pip->type = pip->params.type; } if (PMEM_POOL_TYPE_UNKNOWN == pip->type) { outv_err("%s: unknown pool type -- '%s'\n", file_name, pip->params.signature); return -1; } else if (!pip->args.force && !pip->params.is_checksum_ok) { outv_err("%s: invalid checksum\n", file_name); return -1; } else { if (util_options_verify(pip->opts, pip->type)) return -1; pip->pfile = pool_set_file_open(file_name, 0, !pip->args.force); if (!pip->pfile) { perror(file_name); return -1; } if (pip->type != PMEM_POOL_TYPE_BTT) { struct pool_set *ps = pip->pfile->poolset; for (unsigned r = 0; r < ps->nreplicas; ++r) { if (ps->replica[r]->remote == NULL && mprotect(ps->replica[r]->part[0].addr, ps->replica[r]->repsize, PROT_READ) < 0) { outv_err( "%s: failed to change pool protection", pip->pfile->fname); ret = -1; goto out_close; } } } if (pip->args.obj.replica) { size_t nreplicas = pool_set_file_nreplicas(pip->pfile); if (nreplicas == 1) { outv_err("only master replica available"); ret = -1; goto out_close; } if (pip->args.obj.replica >= nreplicas) { outv_err("replica number out of range" " (valid range is: 0-%" PRIu64 ")", nreplicas - 1); ret = -1; goto out_close; } if (pool_set_file_set_replica(pip->pfile, pip->args.obj.replica)) { outv_err("setting replica number failed"); ret = -1; goto out_close; } } /* hdr info is not present in btt device */ if (pip->type != PMEM_POOL_TYPE_BTT) { if (pip->params.is_poolset && pmempool_info_poolset(pip, VERBOSE_DEFAULT)) { ret = -1; goto out_close; } if (!pip->params.is_poolset && pmempool_info_part(pip, UNDEF_REPLICA, UNDEF_PART, VERBOSE_DEFAULT)) { ret = -1; goto out_close; } if (pmempool_info_pool_hdr(pip, VERBOSE_DEFAULT)) { ret = -1; goto out_close; } } if (pip->params.is_part) { ret = 0; goto out_close; } switch (pip->type) { case PMEM_POOL_TYPE_LOG: ret = pmempool_info_log(pip); break; case PMEM_POOL_TYPE_BLK: ret = pmempool_info_blk(pip); break; case PMEM_POOL_TYPE_OBJ: ret = pmempool_info_obj(pip); break; case PMEM_POOL_TYPE_BTT: ret = pmempool_info_btt(pip); break; case PMEM_POOL_TYPE_UNKNOWN: default: ret = -1; break; } out_close: pool_set_file_close(pip->pfile); } return ret; }
/* * pmempool_convert_func -- main function for convert command */ int pmempool_convert_func(char *appname, int argc, char *argv[]) { if (argc != 2) { print_usage(appname); return -1; } int ret = 0; const char *f = argv[1]; struct pmem_pool_params params; if (pmem_pool_parse_params(f, ¶ms, 1)) { fprintf(stderr, "Cannot determine type of pool.\n"); return -1; } if (params.is_part) { fprintf(stderr, "Conversion cannot be performed on " "a poolset part.\n"); return -1; } if (params.type != PMEM_POOL_TYPE_OBJ) { fprintf(stderr, "Conversion is currently supported only for " "pmemobj pools.\n"); return -1; } struct pool_set_file *psf = pool_set_file_open(f, 0, 1); if (psf == NULL) { perror(f); return -1; } if (psf->poolset->remote) { fprintf(stderr, "Conversion of remotely replicated pools is " "currently not supported. Remove the replica first\n"); pool_set_file_close(psf); return -1; } void *addr = pool_set_file_map(psf, 0); if (addr == NULL) { perror(f); ret = -1; goto out; } struct pool_hdr *phdr = addr; uint32_t m = le32toh(phdr->major); if (m >= COUNT_OF(version_convert) || !version_convert[m]) { fprintf(stderr, "There's no conversion method for the pool.\n" "Please make sure the pmempool utility " "is up-to-date.\n"); ret = -1; goto out; } printf("This tool will update the pool to the latest available " "layout version.\nThis process is NOT fail-safe.\n" "Proceed only if the pool has been backed up or\n" "the risks are fully understood and acceptable.\n"); if (ask_Yn('?', "convert the pool '%s' ?", f) != 'y') { ret = 0; goto out; } PMEMobjpool *pop = addr; for (unsigned r = 0; r < psf->poolset->nreplicas; ++r) { struct pool_replica *rep = psf->poolset->replica[r]; for (unsigned p = 0; p < rep->nparts; ++p) { struct pool_set_part *part = &rep->part[p]; if (util_map_hdr(part, MAP_SHARED, 0) != 0) { fprintf(stderr, "Failed to map headers.\n" "Conversion did not start.\n"); ret = -1; goto out; } } } uint32_t i; for (i = m; i < COUNT_OF(version_convert); ++i) { if (version_convert[i](psf, pop) != 0) { fprintf(stderr, "Failed to convert the pool\n"); break; } else { /* need to update every header of every part */ uint32_t target_m = i + 1; for (unsigned r = 0; r < psf->poolset->nreplicas; ++r) { struct pool_replica *rep = psf->poolset->replica[r]; for (unsigned p = 0; p < rep->nparts; ++p) { struct pool_set_part *part = &rep->part[p]; struct pool_hdr *hdr = part->hdr; hdr->major = htole32(target_m); util_checksum(hdr, sizeof(*hdr), &hdr->checksum, 1); PERSIST_GENERIC_AUTO(hdr, sizeof(struct pool_hdr)); } } } } if (i != m) /* at least one step has been performed */ printf("The pool has been converted to version %d\n.", i); PERSIST_GENERIC_AUTO(pop, psf->size); out: for (unsigned r = 0; r < psf->poolset->nreplicas; ++r) { struct pool_replica *rep = psf->poolset->replica[r]; for (unsigned p = 0; p < rep->nparts; ++p) { struct pool_set_part *part = &rep->part[p]; if (part->hdr != NULL) util_unmap_hdr(part); } } pool_set_file_close(psf); return ret; }