예제 #1
0
/*
 * pool_hdr_uuid_links -- (internal) check UUID links values
 */
static int
pool_hdr_uuid_links(PMEMpoolcheck *ppc, location *loc)
{
	LOG(3, NULL);

	/*
	 * If the pool header is valid and there is not other parts or replicas
	 * in the poolset its uuid links are also valid.
	 */
	if (loc->hdr_valid && loc->single_repl && loc->single_part)
		return 0;

	uuid_t *links[] = {
		&loc->hdr.next_part_uuid, &loc->hdr.prev_part_uuid,
		&loc->hdr.next_repl_uuid, &loc->hdr.prev_repl_uuid};
	uuid_t *uuids[] = {
		&loc->next_part_hdrp->uuid, &loc->prev_part_hdrp->uuid,
		&loc->next_repl_hdrp->uuid, &loc->prev_repl_hdrp->uuid
	};
	uint32_t questions[] = {
		Q_NEXT_PART_UUID_SET, Q_PREV_PART_UUID_SET,
		Q_NEXT_REPL_UUID_SET, Q_PREV_REPL_UUID_SET
	};
	const char *fields[] = {
		"pool_hdr.next_part_uuid", "pool_hdr.prev_part_uuid",
		"pool_hdr.next_repl_uuid", "pool_hdr.prev_repl_uuid"
	};

	COMPILE_ERROR_ON(ARRAY_SIZE(links) != ARRAY_SIZE(uuids));
	COMPILE_ERROR_ON(ARRAY_SIZE(links) != ARRAY_SIZE(questions));
	COMPILE_ERROR_ON(ARRAY_SIZE(links) != ARRAY_SIZE(fields));
	for (uint64_t i = 0; i < ARRAY_SIZE(links); ++i) {
		if (uuidcmp(*links[i], *uuids[i]) == 0)
			continue;

		if (CHECK_IS(ppc, REPAIR)) {
			CHECK_ASK(ppc, questions[i],
				"%sinvalid %s.|Do you want to set it to a "
				"valid value?", loc->prefix, fields[i]);
		} else {
			ppc->result = CHECK_RESULT_NOT_CONSISTENT;
			return CHECK_ERR(ppc, "%sinvalid %s", loc->prefix,
				fields[i]);
		}
	}

	return check_questions_sequence_validate(ppc);
}
예제 #2
0
/*
 * alloc_class_find_or_create -- (internal) searches for the
 * biggest allocation class for which unit_size is evenly divisible by n.
 * If no such class exists, create one.
 */
static struct alloc_class *
alloc_class_find_or_create(struct alloc_class_collection *ac, size_t n)
{
	LOG(10, NULL);

	COMPILE_ERROR_ON(MAX_ALLOCATION_CLASSES > UINT8_MAX);
	uint64_t required_size_bytes = n * RUN_MIN_NALLOCS;
	uint32_t required_size_idx = 1;
	if (required_size_bytes > RUNSIZE) {
		required_size_bytes -= RUNSIZE;
		required_size_idx +=
			CALC_SIZE_IDX(CHUNKSIZE, required_size_bytes);
		if (required_size_idx > RUN_SIZE_IDX_CAP)
			required_size_idx = RUN_SIZE_IDX_CAP;
	}

	for (int i = MAX_ALLOCATION_CLASSES - 1; i >= 0; --i) {
		struct alloc_class *c = ac->aclasses[i];

		if (c == NULL || c->type == CLASS_HUGE ||
				c->run.size_idx < required_size_idx)
			continue;

		if (n % c->unit_size == 0 &&
			n / c->unit_size <= RUN_UNIT_MAX_ALLOC)
			return c;
	}

	/*
	 * In order to minimize the wasted space at the end of the run the
	 * run data size must be divisible by the allocation class unit size
	 * with the smallest possible remainder, preferably 0.
	 */
	size_t runsize_bytes = RUN_SIZE_BYTES(required_size_idx);
	while ((runsize_bytes % n) > MAX_RUN_WASTED_BYTES) {
		n += ALLOC_BLOCK_SIZE_GEN;
	}

	/*
	 * Now that the desired unit size is found the existing classes need
	 * to be searched for possible duplicates. If a class that can handle
	 * the calculated size already exists, simply return that.
	 */
	for (int i = 1; i < MAX_ALLOCATION_CLASSES; ++i) {
		struct alloc_class *c = ac->aclasses[i];
		if (c == NULL || c->type == CLASS_HUGE)
			continue;
		if (n / c->unit_size <= RUN_UNIT_MAX_ALLOC &&
			n % c->unit_size == 0)
			return c;
		if (c->unit_size == n)
			return c;
	}

	return alloc_class_new(-1, ac, CLASS_RUN, HEADER_COMPACT, n, 0,
		required_size_idx);
}
예제 #3
0
파일: obj.c 프로젝트: jxy859/nvml
/*
 * obj_init -- initialization of obj
 *
 * Called by constructor.
 */
void
obj_init(void)
{
	LOG(3, NULL);

	COMPILE_ERROR_ON(sizeof (struct pmemobjpool) != 8192);

	pools = cuckoo_new();
	if (pools == NULL)
		FATAL("!cuckoo_new");
}
예제 #4
0
파일: pmalloc.c 프로젝트: mslusarz/nvml
/*
 * pmalloc_boot -- initializes allocator section
 */
static int
pmalloc_boot(PMEMobjpool *pop)
{
	COMPILE_ERROR_ON(PALLOC_DATA_OFF != OBJ_OOB_SIZE);
	COMPILE_ERROR_ON(ALLOC_BLOCK_SIZE != _POBJ_CL_ALIGNMENT);

	int ret = palloc_boot(&pop->heap, (char *)pop + pop->heap_offset,
			pop->heap_size, pop, &pop->p_ops);
	if (ret)
		return ret;

#ifdef USE_VG_MEMCHECK
	palloc_heap_vg_open(&pop->heap, obj_vg_register, pop, pop->vg_boot);
#endif

	ret = palloc_buckets_init(&pop->heap);
	if (ret)
		palloc_heap_cleanup(&pop->heap);

	return ret;
}
예제 #5
0
/*
 * shutdown_state_init -- initializes shutdown_state struct
 */
int
shutdown_state_init(struct shutdown_state *sds, struct pool_replica *rep)
{
	/* check if we didn't change size of shutdown_state accidentally */
	COMPILE_ERROR_ON(sizeof(struct shutdown_state) != 64);
	LOG(3, "sds %p", sds);

	memset(sds, 0, sizeof(*sds));

	shutdown_state_checksum(sds, rep);

	return 0;
}
예제 #6
0
파일: palloc.c 프로젝트: mramotowski/nvml
/*
 * palloc_reserve -- creates a single reservation
 */
int
palloc_reserve(struct palloc_heap *heap, size_t size,
	palloc_constr constructor, void *arg,
	uint64_t extra_field, uint16_t object_flags, uint16_t class_id,
	struct pobj_action *act)
{
	COMPILE_ERROR_ON(sizeof(struct pobj_action) !=
		sizeof(struct pobj_action_internal));
	act->type = POBJ_ACTION_TYPE_HEAP;

	return palloc_reservation_create(heap, size, constructor, arg,
		extra_field, object_flags, class_id,
		(struct pobj_action_internal *)act);
}
예제 #7
0
파일: memblock.c 프로젝트: ChandKV/nvml
/*
 * chunk_get_chunk_hdr_value -- (internal) get value of a header for redo log
 */
static uint64_t
chunk_get_chunk_hdr_value(uint16_t type, uint32_t size_idx)
{
	uint64_t val;
	COMPILE_ERROR_ON(sizeof(struct chunk_header) != sizeof(uint64_t));

	struct chunk_header hdr;
	hdr.type = type;
	hdr.size_idx = size_idx;
	hdr.flags = 0;
	memcpy(&val, &hdr, sizeof(val));

	return val;
}
예제 #8
0
파일: obj.c 프로젝트: andreas-bluemle/nvml
/*
 * obj_init -- initialization of obj
 *
 * Called by constructor.
 */
void
obj_init(void)
{
	LOG(3, NULL);

	COMPILE_ERROR_ON(sizeof (struct pmemobjpool) != 8192);

#ifdef USE_COW_ENV
	char *env = getenv("PMEMOBJ_COW");
	if (env)
		Open_cow = atoi(env);
#endif

	pools_ht = cuckoo_new();
	if (pools_ht == NULL)
		FATAL("!cuckoo_new");

	pools_tree = ctree_new();
	if (pools_tree == NULL)
		FATAL("!ctree_new");
}
예제 #9
0
파일: set.c 프로젝트: bgbhpe/nvml
/*
 * util_map_part -- map a header of a pool set
 */
int
util_map_hdr(struct pool_set_part *part, int flags)
{
	LOG(3, "part %p flags %d", part, flags);

	COMPILE_ERROR_ON(POOL_HDR_SIZE == 0);
	ASSERTeq(POOL_HDR_SIZE % Pagesize, 0);

	void *hdrp = mmap(NULL, POOL_HDR_SIZE,
		PROT_READ|PROT_WRITE, flags, part->fd, 0);

	if (hdrp == MAP_FAILED) {
		ERR("!mmap: %s", part->path);
		return -1;
	}

	part->hdrsize = POOL_HDR_SIZE;
	part->hdr = hdrp;

	VALGRIND_REGISTER_PMEM_MAPPING(part->hdr, part->hdrsize);
	VALGRIND_REGISTER_PMEM_FILE(part->fd, part->hdr, part->hdrsize, 0);

	return 0;
}
예제 #10
0
파일: memblock.c 프로젝트: krzycz/nvml
/*
 * memblock_header_compact_write --
 *	(internal) writes a compact header of an object
 */
static void
memblock_header_compact_write(const struct memory_block *m,
	size_t size, uint64_t extra, uint16_t flags)
{
	COMPILE_ERROR_ON(ALLOC_HDR_COMPACT_SIZE > CACHELINE_SIZE);

	struct {
		struct allocation_header_compact hdr;
		uint8_t padding[CACHELINE_SIZE - ALLOC_HDR_COMPACT_SIZE];
	} padded;

	padded.hdr.size = size | ((uint64_t)flags << ALLOC_HDR_SIZE_SHIFT);
	padded.hdr.extra = extra;

	struct allocation_header_compact *hdrp = m->m_ops->get_real_data(m);

	VALGRIND_DO_MAKE_MEM_UNDEFINED(hdrp, sizeof(*hdrp));

	/*
	 * If possible write the entire header with a single memcpy, this allows
	 * the copy implementation to avoid a cache miss on a partial cache line
	 * write.
	 */
	size_t hdr_size = ALLOC_HDR_COMPACT_SIZE;
	if ((uintptr_t)hdrp % CACHELINE_SIZE == 0 && size >= sizeof(padded))
		hdr_size = sizeof(padded);

	VALGRIND_ADD_TO_TX(hdrp, hdr_size);

	pmemops_memcpy(&m->heap->p_ops, hdrp, &padded, hdr_size,
		PMEMOBJ_F_MEM_WC | PMEMOBJ_F_MEM_NODRAIN | PMEMOBJ_F_RELAXED);
	VALGRIND_DO_MAKE_MEM_UNDEFINED((char *)hdrp + ALLOC_HDR_COMPACT_SIZE,
		hdr_size - ALLOC_HDR_COMPACT_SIZE);

	VALGRIND_REMOVE_FROM_TX(hdrp, hdr_size);
}
예제 #11
0
/*
 * pool_hdr_uuid_find -- (internal) check UUID value
 */
static int
pool_hdr_uuid_find(PMEMpoolcheck *ppc, location *loc)
{
	LOG(3, NULL);

	/*
	 * If the pool header is valid and there is not other parts or replicas
	 * in the poolset its uuid is also valid.
	 */
	if (loc->hdr_valid && loc->single_repl && loc->single_part)
		return 0;

	int hdrs_valid[] = {
		loc->next_part_hdr_valid, loc->prev_part_hdr_valid,
		loc->next_repl_hdr_valid, loc->prev_repl_hdr_valid};
	uuid_t *uuids[] = {
		&loc->next_part_hdrp->prev_part_uuid,
		&loc->prev_part_hdrp->next_part_uuid,
		&loc->next_repl_hdrp->prev_repl_uuid,
		&loc->prev_repl_hdrp->next_repl_uuid
	};

	/*
	 * if all valid poolset part files have the same uuid links to this part
	 * file it is valid uuid
	 * if all links have the same uuid and it is single file pool it is also
	 * the valid uuid
	 */
	loc->valid_uuid = NULL;
	if (loc->hdr_valid)
		loc->valid_uuid = &loc->hdr.uuid;
	uuid_t *common_uuid = uuids[0];

	COMPILE_ERROR_ON(ARRAY_SIZE(uuids) != ARRAY_SIZE(hdrs_valid));
	COMPILE_ERROR_ON(COMPARE_TO_FIRST_PART_ONLY >= ARRAY_SIZE(uuids));
	for (unsigned i = 0; i < ARRAY_SIZE(uuids); ++i) {
		if (i > 0 && common_uuid != NULL) {
			if (uuidcmp(*common_uuid, *uuids[i]) != 0) {
				common_uuid = NULL;
			}
		}

		if (i >= COMPARE_TO_FIRST_PART_ONLY && loc->part != 0)
			continue;

		if (!hdrs_valid[i])
			continue;

		if (!loc->valid_uuid) {
			loc->valid_uuid = uuids[i];
		} else if (uuidcmp(*loc->valid_uuid, *uuids[i]) != 0) {
			ppc->result = CHECK_RESULT_NOT_CONSISTENT;
			return CHECK_ERR(ppc, "%sambiguous pool_hdr.uuid",
				loc->prefix);
		}
	}

	if (!loc->valid_uuid && common_uuid)
		loc->valid_uuid = common_uuid;

	if (loc->valid_uuid != NULL) {
		if (uuidcmp(*loc->valid_uuid, loc->hdr.uuid) != 0) {
			CHECK_ASK(ppc, Q_UUID_SET, INVALID_UUID ".|Do you want "
				"to set it to %s from a valid part file?",
				loc->prefix,
				check_get_uuid_str(*loc->valid_uuid));
		}
	} else if (CHECK_IS(ppc, ADVANCED)) {
		CHECK_ASK(ppc, Q_UUID_REGENERATE, INVALID_UUID ".|Do you want "
				"to regenerate it?", loc->prefix);
	} else if (CHECK_IS(ppc, REPAIR)) {
		ppc->result = CHECK_RESULT_CANNOT_REPAIR;
		CHECK_INFO(ppc, "%s" REQUIRE_ADVANCED, loc->prefix);
		return CHECK_ERR(ppc, INVALID_UUID, loc->prefix);
	} else {
		ppc->result = CHECK_RESULT_NOT_CONSISTENT;
		return CHECK_ERR(ppc, INVALID_UUID, loc->prefix);
	}

	return check_questions_sequence_validate(ppc);
}