/* * pmemobj_root_construct -- returns root object */ PMEMoid pmemobj_root_construct(PMEMobjpool *pop, size_t size, void (*constructor)(PMEMobjpool *pop, void *ptr, void *arg), void *arg) { LOG(3, "pop %p size %zu constructor %p args %p", pop, size, constructor, arg); if (size > PMEMOBJ_MAX_ALLOC_SIZE) { ERR("requested size too large"); errno = ENOMEM; return OID_NULL; } PMEMoid root; pmemobj_mutex_lock(pop, &pop->rootlock); if (pop->store->root.head.pe_first.off == 0) /* root object list is empty */ obj_alloc_root(pop, pop->store, size, constructor, arg); else { size_t old_size = pmemobj_root_size(pop); if (size > old_size) if (obj_realloc_root(pop, pop->store, size, old_size, constructor, arg)) { pmemobj_mutex_unlock(pop, &pop->rootlock); LOG(2, "obj_realloc_root failed"); return OID_NULL; } } root = pop->store->root.head.pe_first; pmemobj_mutex_unlock(pop, &pop->rootlock); return root; }
/* * pmemobj_vg_register_object -- (internal) notify Valgrind about object */ static void pmemobj_vg_register_object(struct pmemobjpool *pop, PMEMoid oid, int is_root) { LOG(4, "pop %p oid.off 0x%016jx is_root %d", pop, oid.off, is_root); void *addr = pmemobj_direct(oid); size_t sz; if (is_root) sz = pmemobj_root_size(pop); else sz = pmemobj_alloc_usable_size(oid); size_t headers = sizeof (struct allocation_header) + OBJ_OOB_SIZE; VALGRIND_DO_MEMPOOL_ALLOC(pop, addr, sz); VALGRIND_DO_MAKE_MEM_DEFINED(pop, addr - headers, sz + headers); struct oob_header *oob = OOB_HEADER_FROM_PTR(addr); if (!is_root) /* no one should touch it */ VALGRIND_DO_MAKE_MEM_NOACCESS(pop, &oob->size, sizeof (oob->size)); /* no one should touch it */ VALGRIND_DO_MAKE_MEM_NOACCESS(pop, &oob->data.padding, sizeof (oob->data.padding)); }
/* * pocli_str_root_print -- print a string stored in the root object data */ static enum pocli_ret pocli_str_root_print(struct pocli_ctx *ctx, struct pocli_args *args) { if (args->argc != 3) return POCLI_ERR_ARGS; size_t offset = 0; enum pocli_ret ret = pocli_args_size(args, 1, &offset); if (ret) return ret; size_t len = 0; ret = pocli_args_number(args, 2, &len); if (ret) return ret; size_t root_size = pmemobj_root_size(ctx->pop); if (offset + len > root_size) return POCLI_ERR_ARGS; PMEMoid root = pmemobj_root(ctx->pop, root_size); assert(!OID_IS_NULL(root)); char *root_data = pmemobj_direct(root); char *buff = malloc(len + 1); memcpy(buff, root_data + offset, len); buff[len] = '\0'; printf("%s\n", buff); return ret; }
/* * pocli_str_root_copy -- copy a string into a root object data */ static enum pocli_ret pocli_str_root_copy(struct pocli_ctx *ctx, struct pocli_args *args) { if (args->argc != 3) return POCLI_ERR_ARGS; size_t offset = 0; enum pocli_ret ret = pocli_args_size(args, 1, &offset); if (ret) return ret; const char *str = args->argv[2]; if (str == NULL) return POCLI_ERR_ARGS; size_t len = strlen(str); size_t root_size = pmemobj_root_size(ctx->pop); if (offset + len > root_size) return POCLI_ERR_ARGS; PMEMoid root = pmemobj_root(ctx->pop, root_size); assert(!OID_IS_NULL(root)); char *root_data = pmemobj_direct(root); pmemobj_memcpy_persist(ctx->pop, root_data + offset, str, len); return ret; }
/* * pocli_pmemobj_root_size -- pmemobj_root_size() command */ static enum pocli_ret pocli_pmemobj_root_size(struct pocli_ctx *ctx, struct pocli_args *args) { if (args->argc != 1) return POCLI_ERR_ARGS; size_t size = pmemobj_root_size(ctx->pop); pocli_printf(ctx, "%s: size = %lu\n", args->argv[0], size); return POCLI_RET_OK; }
/* * pocli_args_obj_root -- parse object's descriptor from root object */ static enum pocli_ret pocli_args_obj_root(struct pocli_ctx *ctx, char *in, PMEMoid **oidp) { char *input = strdup(in); if (!input) return POCLI_ERR_MALLOC; if (!oidp) return POCLI_ERR_PARS; struct pocli_args *args = pocli_args_alloc(NULL, input, "."); if (!args) return POCLI_ERR_PARS; enum pocli_ret ret = POCLI_RET_OK; if (strcmp(args->argv[0], "r") != 0) { ret = POCLI_ERR_PARS; goto out; } PMEMoid *oid = &ctx->root; size_t size = pmemobj_root_size(ctx->pop); for (int i = 1; i < args->argc; i++) { unsigned ind; char c; int n = sscanf(args->argv[i], "%u%c", &ind, &c); if (n != 1) { ret = POCLI_ERR_PARS; goto out; } size_t max_ind = size / sizeof (PMEMoid); if (!max_ind || ind >= max_ind) { ret = POCLI_ERR_PARS; goto out; } PMEMoid *oids = pmemobj_direct(*oid); oid = &oids[ind]; size = pmemobj_alloc_usable_size(*oid); } *oidp = oid; out: free(input); free(args); return ret; }
/* * pocli_alloc -- allocate main context */ static struct pocli * pocli_alloc(FILE *input, const char *fname, const struct pocli_cmd *cmds, size_t ncmds, size_t inbuf_len) { assert(inbuf_len < INT_MAX); struct pocli_opts opts; if (pocli_read_opts(&opts)) return NULL; struct pocli *pcli = calloc(1, sizeof (*pcli)); if (!pcli) return NULL; memcpy(&pcli->opts, &opts, sizeof (pcli->opts)); pcli->in = input; pcli->istty = isatty(fileno(pcli->in)); pcli->cmds = cmds; pcli->ncmds = ncmds; pcli->ctx.pocli = pcli; pcli->ctx.err = stderr; pcli->ctx.out = stdout; pcli->ctx.pop = pmemobj_open(fname, NULL); if (!pcli->ctx.pop) { fprintf(stderr, "%s: %s\n", fname, pmemobj_errormsg()); goto err_free_pcli; } size_t root_size = pmemobj_root_size(pcli->ctx.pop); if (root_size) pcli->ctx.root = pmemobj_root(pcli->ctx.pop, root_size); pcli->inbuf_len = inbuf_len; pcli->inbuf = malloc(inbuf_len); if (!pcli->inbuf) goto err_close_pool; return pcli; err_close_pool: pmemobj_close(pcli->ctx.pop); err_free_pcli: free(pcli); return NULL; }
/* * pmemobj_vg_boot -- (internal) notify Valgrind about pool objects */ static void pmemobj_vg_boot(struct pmemobjpool *pop) { if (!On_valgrind) return; LOG(4, "pop %p", pop); PMEMoid oid; int rs = pmemobj_root_size(pop); if (rs) { oid = pmemobj_root(pop, rs); pmemobj_vg_register_object(pop, oid, 1); } for (int i = 0; i < PMEMOBJ_NUM_OID_TYPES; ++i) { for (oid = pmemobj_first(pop, i); !OID_IS_NULL(oid); oid = pmemobj_next(oid)) pmemobj_vg_register_object(pop, oid, 0); } if (getenv("PMEMOBJ_VG_CHECK_UNDEF")) pmemobj_vg_check_no_undef(pop); }