Beispiel #1
0
Datei: obj.c Projekt: jxy859/nvml
/*
 * pmemobj_strndup -- allocates a new object with duplicate of the string s.
 */
int
pmemobj_strdup(PMEMobjpool *pop, PMEMoid *oidp, const char *s,
		unsigned int type_num)
{
	LOG(3, "pop %p oidp %p string %s type_num %u", pop, oidp, s, type_num);

	/* log notice message if used inside a transaction */
	_POBJ_DEBUG_NOTICE_IN_TX();

	if (type_num >= PMEMOBJ_NUM_OID_TYPES) {
		errno = EINVAL;
		ERR("!pmemobj_strdup");
		LOG(2, "type_num has to be in range [0, %i]",
		    PMEMOBJ_NUM_OID_TYPES - 1);
		return -1;
	}

	if (NULL == s) {
		errno = EINVAL;
		return -1;
	}

	struct carg_strdup carg;
	carg.size = (strlen(s) + 1) * sizeof (char);
	carg.s = s;

	return obj_alloc_construct(pop, oidp, carg.size, type_num,
					constructor_strdup, &carg);
}
Beispiel #2
0
/*
 * pmemobj_zalloc -- allocates a new zeroed object
 */
int
pmemobj_zalloc(PMEMobjpool *pop, PMEMoid *oidp, size_t size,
		unsigned int type_num)
{
	LOG(3, "pop %p oidp %p size %zu type_num %u",
			pop, oidp, size, type_num);

	/* log notice message if used inside a transaction */
	_POBJ_DEBUG_NOTICE_IN_TX();

	if (size == 0) {
		ERR("allocation with size 0");
		errno = EINVAL;
		return -1;
	}

	if (type_num >= PMEMOBJ_NUM_OID_TYPES) {
		errno = EINVAL;
		ERR("invalid type_num %u", type_num);
		return -1;
	}

	return obj_alloc_construct(pop, oidp, size, (type_num_t)type_num,
					1, NULL, NULL);
}
Beispiel #3
0
Datei: obj.c Projekt: jxy859/nvml
/*
 * pmemobj_alloc -- allocates a new object
 */
int
pmemobj_alloc(PMEMobjpool *pop, PMEMoid *oidp, size_t size,
	unsigned int type_num, void (*constructor)(PMEMobjpool *pop, void *ptr,
	void *arg), void *arg)
{
	LOG(3, "pop %p oidp %p size %zu type_num %u constructor %p arg %p",
		pop, oidp, size, type_num, constructor, arg);

	/* log notice message if used inside a transaction */
	_POBJ_DEBUG_NOTICE_IN_TX();

	if (size == 0) {
		ERR("allocation with size 0");
		errno = EINVAL;
		return -1;
	}

	return obj_alloc_construct(pop, oidp, size, type_num, constructor, arg);
}
Beispiel #4
0
Datei: obj.c Projekt: jxy859/nvml
/*
 * pmemobj_zalloc -- allocates a new zeroed object
 */
int
pmemobj_zalloc(PMEMobjpool *pop, PMEMoid *oidp, size_t size,
		unsigned int type_num)
{
	LOG(3, "pop %p oidp %p size %zu type_num %u",
			pop, oidp, size, type_num);

	/* log notice message if used inside a transaction */
	_POBJ_DEBUG_NOTICE_IN_TX();

	if (size == 0) {
		ERR("allocation with size 0");
		errno = EINVAL;
		return -1;
	}

	struct carg_alloc carg;
	carg.size = size;

	return obj_alloc_construct(pop, oidp, size, type_num,
					constructor_zalloc, &carg);
}
Beispiel #5
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 #6
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;
	}
}