예제 #1
0
파일: zap_leaf.c 프로젝트: gcracker/zfs
int
zap_leaf_lookup(zap_leaf_t *l, zap_name_t *zn, zap_entry_handle_t *zeh)
{
	uint16_t *chunkp;
	struct zap_leaf_entry *le;

	ASSERT3U(zap_leaf_phys(l)->l_hdr.lh_magic, ==, ZAP_LEAF_MAGIC);

again:
	for (chunkp = LEAF_HASH_ENTPTR(l, zn->zn_hash);
	    *chunkp != CHAIN_END; chunkp = &le->le_next) {
		uint16_t chunk = *chunkp;
		le = ZAP_LEAF_ENTRY(l, chunk);

		ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l));
		ASSERT3U(le->le_type, ==, ZAP_CHUNK_ENTRY);

		if (le->le_hash != zn->zn_hash)
			continue;

		/*
		 * NB: the entry chain is always sorted by cd on
		 * normalized zap objects, so this will find the
		 * lowest-cd match for MT_FIRST.
		 */
		ASSERT(zn->zn_matchtype == MT_EXACT ||
		    (zap_leaf_phys(l)->l_hdr.lh_flags & ZLF_ENTRIES_CDSORTED));
		if (zap_leaf_array_match(l, zn, le->le_name_chunk,
		    le->le_name_numints)) {
			zeh->zeh_num_integers = le->le_value_numints;
			zeh->zeh_integer_size = le->le_value_intlen;
			zeh->zeh_cd = le->le_cd;
			zeh->zeh_hash = le->le_hash;
			zeh->zeh_chunkp = chunkp;
			zeh->zeh_leaf = l;
			return (0);
		}
	}

	/*
	 * NB: we could of course do this in one pass, but that would be
	 * a pain.  We'll see if MT_BEST is even used much.
	 */
	if (zn->zn_matchtype == MT_BEST) {
		zn->zn_matchtype = MT_FIRST;
		goto again;
	}

	return (SET_ERROR(ENOENT));
}
예제 #2
0
파일: zap_leaf.c 프로젝트: gcracker/zfs
static void
zap_leaf_chunk_free(zap_leaf_t *l, uint16_t chunk)
{
	struct zap_leaf_free *zlf = &ZAP_LEAF_CHUNK(l, chunk).l_free;
	ASSERT3U(zap_leaf_phys(l)->l_hdr.lh_nfree, <, ZAP_LEAF_NUMCHUNKS(l));
	ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l));
	ASSERT(zlf->lf_type != ZAP_CHUNK_FREE);

	zlf->lf_type = ZAP_CHUNK_FREE;
	zlf->lf_next = zap_leaf_phys(l)->l_hdr.lh_freelist;
	bzero(zlf->lf_pad, sizeof (zlf->lf_pad)); /* help it to compress */
	zap_leaf_phys(l)->l_hdr.lh_freelist = chunk;

	zap_leaf_phys(l)->l_hdr.lh_nfree++;
}
예제 #3
0
파일: zap_leaf.c 프로젝트: gcracker/zfs
int
zap_leaf_lookup_closest(zap_leaf_t *l,
    uint64_t h, uint32_t cd, zap_entry_handle_t *zeh)
{
	uint16_t chunk;
	uint64_t besth = -1ULL;
	uint32_t bestcd = -1U;
	uint16_t bestlh = ZAP_LEAF_HASH_NUMENTRIES(l)-1;
	uint16_t lh;
	struct zap_leaf_entry *le;

	ASSERT3U(zap_leaf_phys(l)->l_hdr.lh_magic, ==, ZAP_LEAF_MAGIC);

#ifdef __APPLE__
	if (zap_leaf_phys(l)->l_hdr.lh_magic != ZAP_LEAF_MAGIC) {
		printf("ZFS: Corrupt zap_leaf_lookup_closest detected\n");
		return EIO;
	}
#endif

	for (lh = LEAF_HASH(l, h); lh <= bestlh; lh++) {
		for (chunk = zap_leaf_phys(l)->l_hash[lh];
		    chunk != CHAIN_END; chunk = le->le_next) {
			le = ZAP_LEAF_ENTRY(l, chunk);

			ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l));
			ASSERT3U(le->le_type, ==, ZAP_CHUNK_ENTRY);

			if (HCD_GTEQ(le->le_hash, le->le_cd, h, cd) &&
			    HCD_GTEQ(besth, bestcd, le->le_hash, le->le_cd)) {
				ASSERT3U(bestlh, >=, lh);
				bestlh = lh;
				besth = le->le_hash;
				bestcd = le->le_cd;

				zeh->zeh_num_integers = le->le_value_numints;
				zeh->zeh_integer_size = le->le_value_intlen;
				zeh->zeh_cd = le->le_cd;
				zeh->zeh_hash = le->le_hash;
				zeh->zeh_fakechunk = chunk;
				zeh->zeh_chunkp = &zeh->zeh_fakechunk;
				zeh->zeh_leaf = l;
			}
		}
	}
예제 #4
0
파일: zap_leaf.c 프로젝트: gcracker/zfs
static uint16_t
zap_leaf_chunk_alloc(zap_leaf_t *l)
{
	int chunk;

	ASSERT(zap_leaf_phys(l)->l_hdr.lh_nfree > 0);

	chunk = zap_leaf_phys(l)->l_hdr.lh_freelist;
	ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l));
	ASSERT3U(ZAP_LEAF_CHUNK(l, chunk).l_free.lf_type, ==, ZAP_CHUNK_FREE);

	zap_leaf_phys(l)->l_hdr.lh_freelist =
	    ZAP_LEAF_CHUNK(l, chunk).l_free.lf_next;

	zap_leaf_phys(l)->l_hdr.lh_nfree--;

	return (chunk);
}
예제 #5
0
파일: zap_leaf.c 프로젝트: LLNL/zfs
int
zap_leaf_lookup(zap_leaf_t *l, zap_name_t *zn, zap_entry_handle_t *zeh)
{
	uint16_t *chunkp;
	struct zap_leaf_entry *le;

	ASSERT3U(zap_leaf_phys(l)->l_hdr.lh_magic, ==, ZAP_LEAF_MAGIC);

	for (chunkp = LEAF_HASH_ENTPTR(l, zn->zn_hash);
	    *chunkp != CHAIN_END; chunkp = &le->le_next) {
		uint16_t chunk = *chunkp;
		le = ZAP_LEAF_ENTRY(l, chunk);

		ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l));
		ASSERT3U(le->le_type, ==, ZAP_CHUNK_ENTRY);

		if (le->le_hash != zn->zn_hash)
			continue;

		/*
		 * NB: the entry chain is always sorted by cd on
		 * normalized zap objects, so this will find the
		 * lowest-cd match for MT_NORMALIZE.
		 */
		ASSERT((zn->zn_matchtype == 0) ||
		    (zap_leaf_phys(l)->l_hdr.lh_flags & ZLF_ENTRIES_CDSORTED));
		if (zap_leaf_array_match(l, zn, le->le_name_chunk,
		    le->le_name_numints)) {
			zeh->zeh_num_integers = le->le_value_numints;
			zeh->zeh_integer_size = le->le_value_intlen;
			zeh->zeh_cd = le->le_cd;
			zeh->zeh_hash = le->le_hash;
			zeh->zeh_chunkp = chunkp;
			zeh->zeh_leaf = l;
			return (0);
		}
	}

	return (SET_ERROR(ENOENT));
}
예제 #6
0
파일: zap_leaf.c 프로젝트: gcracker/zfs
void
zap_leaf_init(zap_leaf_t *l, boolean_t sort)
{
	int i;

	l->l_bs = highbit64(l->l_dbuf->db_size) - 1;
	zap_memset(&zap_leaf_phys(l)->l_hdr, 0,
	    sizeof (struct zap_leaf_header));
	zap_memset(zap_leaf_phys(l)->l_hash, CHAIN_END,
	    2*ZAP_LEAF_HASH_NUMENTRIES(l));
	for (i = 0; i < ZAP_LEAF_NUMCHUNKS(l); i++) {
		ZAP_LEAF_CHUNK(l, i).l_free.lf_type = ZAP_CHUNK_FREE;
		ZAP_LEAF_CHUNK(l, i).l_free.lf_next = i+1;
	}
	ZAP_LEAF_CHUNK(l, ZAP_LEAF_NUMCHUNKS(l)-1).l_free.lf_next = CHAIN_END;
	zap_leaf_phys(l)->l_hdr.lh_block_type = ZBT_LEAF;
	zap_leaf_phys(l)->l_hdr.lh_magic = ZAP_LEAF_MAGIC;
	zap_leaf_phys(l)->l_hdr.lh_nfree = ZAP_LEAF_NUMCHUNKS(l);
	if (sort)
		zap_leaf_phys(l)->l_hdr.lh_flags |= ZLF_ENTRIES_CDSORTED;
}