/* * pmemobj_type_num -- returns type number of object */ int pmemobj_type_num(PMEMoid oid) { LOG(3, "oid.off 0x%016jx", oid.off); if (OBJ_OID_IS_NULL(oid)) return -1; void *ptr = pmemobj_direct(oid); struct oob_header *oobh = OOB_HEADER_FROM_PTR(ptr); return oobh->data.user_type; }
/* * obj_realloc_common -- (internal) common routine for resizing * existing objects */ static int obj_realloc_common(PMEMobjpool *pop, struct object_store *store, PMEMoid *oidp, size_t size, unsigned int type_num, void (*constr_alloc)(PMEMobjpool *pop, void *ptr, void *arg), void (*constr_realloc)(PMEMobjpool *pop, void *ptr, void *arg)) { /* if OID is NULL just allocate memory */ if (OBJ_OID_IS_NULL(*oidp)) { struct carg_alloc carg; carg.size = size; /* if size is 0 - do nothing */ if (size == 0) return 0; return obj_alloc_construct(pop, oidp, size, type_num, constr_alloc, &carg); } if (size > PMEMOBJ_MAX_ALLOC_SIZE) { ERR("requested size too large"); errno = ENOMEM; return -1; } /* if size is 0 just free */ if (size == 0) { obj_free(pop, oidp); return 0; } struct carg_realloc carg; carg.ptr = OBJ_OFF_TO_PTR(pop, oidp->off); carg.new_size = size; carg.old_size = pmemobj_alloc_usable_size(*oidp); carg.user_type = type_num; carg.constructor = NULL; carg.arg = NULL; struct oob_header *pobj = OOB_HEADER_FROM_OID(pop, *oidp); uint16_t user_type_old = pobj->data.user_type; ASSERT(user_type_old < PMEMOBJ_NUM_OID_TYPES); if (type_num >= PMEMOBJ_NUM_OID_TYPES) { errno = EINVAL; ERR("!obj_realloc_construct"); LOG(2, "type_num has to be in range [0, %u]", PMEMOBJ_NUM_OID_TYPES - 1); return -1; } struct list_head *lhead_old = &store->bytype[user_type_old].head; if (type_num == user_type_old) { int ret = list_realloc(pop, lhead_old, 0, NULL, size, constr_realloc, &carg, 0, 0, oidp); if (ret) LOG(2, "list_realloc failed"); return ret; } else { struct list_head *lhead_new = &store->bytype[type_num].head; /* * Redo log updates 8 byte entries, so we have to prepare * full 8-byte value even if we want to update smaller field * (here: user_type). */ struct oob_header_data d = pobj->data; d.user_type = type_num; uint64_t data_offset = OOB_OFFSET_OF(*oidp, data); int ret = list_realloc_move(pop, lhead_old, lhead_new, 0, NULL, size, constr_realloc, &carg, data_offset, *((uint64_t *)&d), oidp); if (ret) LOG(2, "list_realloc_move failed"); return ret; } }
/* * obj_realloc_common -- (internal) common routine for resizing * existing objects */ static int obj_realloc_common(PMEMobjpool *pop, struct object_store *store, PMEMoid *oidp, size_t size, type_num_t type_num, int zero_init) { /* if OID is NULL just allocate memory */ if (OBJ_OID_IS_NULL(*oidp)) { /* if size is 0 - do nothing */ if (size == 0) return 0; return obj_alloc_construct(pop, oidp, size, type_num, zero_init, NULL, NULL); } if (size > PMEMOBJ_MAX_ALLOC_SIZE) { ERR("requested size too large"); errno = ENOMEM; return -1; } /* if size is 0 just free */ if (size == 0) { obj_free(pop, oidp); return 0; } struct carg_realloc carg; carg.ptr = OBJ_OFF_TO_PTR(pop, oidp->off); carg.new_size = size; carg.old_size = pmemobj_alloc_usable_size(*oidp); carg.user_type = type_num; carg.constructor = NULL; carg.arg = NULL; carg.zero_init = zero_init; struct oob_header *pobj = OOB_HEADER_FROM_OID(pop, *oidp); type_num_t user_type_old = pobj->data.user_type; /* callers should have checked this */ ASSERT(type_num < PMEMOBJ_NUM_OID_TYPES); ASSERT(user_type_old < PMEMOBJ_NUM_OID_TYPES); struct list_head *lhead_old = &store->bytype[user_type_old].head; if (type_num == user_type_old) { int ret = list_realloc(pop, lhead_old, 0, NULL, size, constructor_realloc, &carg, 0, 0, oidp); if (ret) LOG(2, "list_realloc failed"); /* oidp could be different, so we need to get the ptr again */ VALGRIND_DO_MAKE_MEM_NOACCESS(pop, &OOB_HEADER_FROM_OID(pop, *oidp)->data.padding, sizeof (OOB_HEADER_FROM_OID(pop, *oidp)->data.padding)); return ret; } else { struct list_head *lhead_new = &store->bytype[type_num].head; /* * Header padding doubles as a red zone to check for header * overwrites. Disable it temporarily so we can modify the type * number. */ VALGRIND_DO_MAKE_MEM_DEFINED(pop, &OOB_HEADER_FROM_OID(pop, *oidp)->data.padding, sizeof (OOB_HEADER_FROM_OID(pop, *oidp)->data.padding)); /* * Redo log updates 8 byte entries, so we have to prepare * full 8-byte value even if we want to update smaller field * (here: user_type). */ struct oob_header_data d = pobj->data; d.user_type = type_num; uint64_t data_offset = OOB_OFFSET_OF(*oidp, data); int ret = list_realloc_move(pop, lhead_old, lhead_new, 0, NULL, size, constructor_realloc, &carg, data_offset, *((uint64_t *)&d), oidp); if (ret) LOG(2, "list_realloc_move failed"); /* oidp could be different, so we need to get the ptr again */ VALGRIND_DO_MAKE_MEM_NOACCESS(pop, &OOB_HEADER_FROM_OID(pop, *oidp)->data.padding, sizeof (OOB_HEADER_FROM_OID(pop, *oidp)->data.padding)); return ret; } }