Beispiel #1
0
Datei: obj.c Projekt: jxy859/nvml
/*
 * 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;
}
Beispiel #2
0
Datei: obj.c Projekt: jxy859/nvml
/*
 * 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;
	}
}
Beispiel #3
0
/*
 * 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;
	}
}