zap_micro.c revision de8267e0f723ed2c38ea9def92d465f69a300f56
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER START
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The contents of this file are subject to the terms of the
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens * Common Development and Distribution License (the "License").
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens * You may not use this file except in compliance with the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fa9e4066f08beec538e775443c5be79dd423fcabahrens * See the License for the specific language governing permissions
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and limitations under the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * When distributing Covered Code, include this CDDL HEADER in each
fa9e4066f08beec538e775443c5be79dd423fcabahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If applicable, add the following below this CDDL HEADER, with the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * fields enclosed by brackets "[]" replaced with your own identifying
fa9e4066f08beec538e775443c5be79dd423fcabahrens * information: Portions Copyright [yyyy] [name of copyright owner]
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER END
c25056de36a33f2a76f79dcf64593f731d258013gw * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Use is subject to license terms.
fa9e4066f08beec538e775443c5be79dd423fcabahrens#pragma ident "%Z%%M% %I% %E% SMI"
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* NB: name must already be normalized, if necessary */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (cp = (const uint8_t *)normname; (c = *cp) != '\0'; cp++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Only use 28 bits, since we need 4 bits in the cookie for the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * collision differentiator. We MUST use the high bits, since
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * those are the ones that we first pay attention to when
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * chosing the bucket.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwzap_normalize(zap_t *zap, const char *name, char *namenorm)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) u8_textprep_str((char *)name, &inlen, namenorm, &outlen,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw zap->zap_normflags | U8_TEXTPREP_IGNORE_NULL, U8_UNICODE_LATEST,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* MT_BEST or MT_EXACT */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* XXX combine this with zap_lockdir()? */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwzap_name_alloc(zap_t *zap, const char *name, matchtype_t mt)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw zap_name_t *zn = kmem_alloc(sizeof (zap_name_t), KM_SLEEP);
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; i < max; i++) {
5ad820458efd0fdb914baff9c1447c22b819fa23nd if (block_type == ZBT_MICRO || block_type == BSWAP_64(ZBT_MICRO)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* ASSERT(magic == ZAP_LEAF_MAGIC); */
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (+1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (+1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrensmze_insert(zap_t *zap, int chunkid, uint64_t hash, mzap_ent_phys_t *mzep)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (strlen(zn->zn_name_norm) >= sizeof (mze_tofind.mze_phys.mze_name))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (; mze && mze->mze_hash == zn->zn_hash; mze = AVL_NEXT(avl, mze)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens mze && mze->mze_hash == hash; mze = AVL_NEXT(avl, mze)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens while (mze = avl_destroy_nodes(&zap->zap_m.zap_avl, &avlcookie))
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT3U(MZAP_ENT_LEN, ==, sizeof (mzap_ent_phys_t));
fa9e4066f08beec538e775443c5be79dd423fcabahrens mutex_init(&zap->zap_f.zap_num_entries_mtx, 0, 0, 0);
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens zap->zap_f.zap_block_shift = highbit(db->db_size) - 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Make sure that zap_ismicro is set before we let others see
fa9e4066f08beec538e775443c5be79dd423fcabahrens * it, because zap_lockdir() checks zap_ismicro without the lock
455d5089097abbf7ee4538a03c4df823497b6e68ahrens winner = dmu_buf_set_user(db, zap, &zap->zap_m.zap_phys, zap_evict);
fa9e4066f08beec538e775443c5be79dd423fcabahrens zap->zap_m.zap_num_chunks = db->db_size / MZAP_ENT_LEN - 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens sizeof (mzap_ent_t), offsetof(mzap_ent_t, mze_node));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw zap->zap_normflags = zap->zap_f.zap_phys->zap_normflags;
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens * The embedded pointer table should not overlap the
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens * other members.
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens * The embedded pointer table should end at the end of
f65e61c04bc28ffd6bda04619c84330b420450b5ahrens * the block
c5f9e43110e1fb316fc4297c2d150b3518b80bbeahrens krw_t lti, boolean_t fatreader, boolean_t adding, zap_t **zapp)
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(dmu_ot[doi.doi_type].ot_byteswap == zap_byteswap);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * We're checking zap_ismicro without the lock held, in order to
fa9e4066f08beec538e775443c5be79dd423fcabahrens * tell what type of lock we want. Once we have some sort of
fa9e4066f08beec538e775443c5be79dd423fcabahrens * lock, see if it really is the right type. In practice this
fa9e4066f08beec538e775443c5be79dd423fcabahrens * can only be different if it was upgraded from micro to fat,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and micro wanted WRITER but fat only needs READER.
fa9e4066f08beec538e775443c5be79dd423fcabahrens lt = (!zap->zap_ismicro && fatreader) ? RW_READER : lti;
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (lt != ((!zap->zap_ismicro && fatreader) ? RW_READER : lti)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* it was upgraded, now we only need reader */
fa9e4066f08beec538e775443c5be79dd423fcabahrens zap->zap_m.zap_num_entries <= zap->zap_m.zap_num_chunks);
fa9e4066f08beec538e775443c5be79dd423fcabahrens zap->zap_m.zap_num_entries == zap->zap_m.zap_num_chunks) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens err = dmu_object_set_blocksize(os, obj, newsz, 0, tx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens err = dmu_object_set_blocksize(zap->zap_objset, zap->zap_object,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* XXX destroy the avl later, so we can use the stored hash value */
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; i < nchunks; i++) {
ad860c82b2a8ffe69f42630da73ded0c92a7a36ebonwick err = fzap_add_cd(zn, 8, 1, &mze->mze_value, mze->mze_cd, tx);
ad860c82b2a8ffe69f42630da73ded0c92a7a36ebonwick zap = zn->zn_zap; /* fzap_add_cd() may change zap */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwmzap_create_impl(objset_t *os, uint64_t obj, int normflags, dmu_tx_t *tx)
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(dmu_ot[doi.doi_type].ot_byteswap == zap_byteswap);
fa9e4066f08beec538e775443c5be79dd423fcabahrens zp->mz_salt = ((uintptr_t)db ^ (uintptr_t)tx ^ (obj << 1)) | 1ULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrenszap_create_claim(objset_t *os, uint64_t obj, dmu_object_type_t ot,
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwzap_create_claim_norm(objset_t *os, uint64_t obj, int normflags,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
fa9e4066f08beec538e775443c5be79dd423fcabahrens err = dmu_object_claim(os, obj, ot, 0, bonustype, bonuslen, tx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (zap_create_norm(os, 0, ot, bonustype, bonuslen, tx));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwzap_create_norm(objset_t *os, int normflags, dmu_object_type_t ot,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t obj = dmu_object_alloc(os, ot, 0, bonustype, bonuslen, tx);
fa9e4066f08beec538e775443c5be79dd423fcabahrenszap_destroy(objset_t *os, uint64_t zapobj, dmu_tx_t *tx)
fa9e4066f08beec538e775443c5be79dd423fcabahrens * dmu_object_free will free the object number and free the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * data. Freeing the data will cause our pageout function to be
fa9e4066f08beec538e775443c5be79dd423fcabahrens * called, which will destroy our data (zap_leaf_t's and zap_t).
fa9e4066f08beec538e775443c5be79dd423fcabahrenszap_count(objset_t *os, uint64_t zapobj, uint64_t *count)
c5f9e43110e1fb316fc4297c2d150b3518b80bbeahrens err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, &zap);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * zn may be NULL; if not specified, it will be computed if needed.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * See also the comment above zap_entry_normalization_conflict().
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwmzap_normalization_conflict(zap_t *zap, zap_name_t *zn, mzap_ent_t *mze)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (other = avl_walk(&zap->zap_m.zap_avl, mze, direction);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw other = avl_walk(&zap->zap_m.zap_avl, other, direction)) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Routines for manipulating attributes.
fa9e4066f08beec538e775443c5be79dd423fcabahrenszap_lookup(objset_t *os, uint64_t zapobj, const char *name,
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t integer_size, uint64_t num_integers, void *buf)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwzap_lookup_norm(objset_t *os, uint64_t zapobj, const char *name,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint64_t integer_size, uint64_t num_integers, void *buf,
c5f9e43110e1fb316fc4297c2d150b3518b80bbeahrens err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, &zap);
fa9e4066f08beec538e775443c5be79dd423fcabahrenszap_length(objset_t *os, uint64_t zapobj, const char *name,
c5f9e43110e1fb316fc4297c2d150b3518b80bbeahrens err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, &zap);
fa9e4066f08beec538e775443c5be79dd423fcabahrens mzap_ent_phys_t *mze = &zap->zap_m.zap_phys->mz_chunk[i];
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* given the limited size of the microzap, this can't happen */
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = start; i < zap->zap_m.zap_num_chunks; i++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens mzap_ent_phys_t *mze = &zap->zap_m.zap_phys->mz_chunk[i];
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (start != 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrenszap_add(objset_t *os, uint64_t zapobj, const char *name,
c5f9e43110e1fb316fc4297c2d150b3518b80bbeahrens err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, &zap);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw err = fzap_add(zn, integer_size, num_integers, val, tx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens dprintf("upgrading obj %llu: intsz=%u numint=%llu name=%s\n",
ad860c82b2a8ffe69f42630da73ded0c92a7a36ebonwick err = fzap_add(zn, integer_size, num_integers, val, tx);
ad860c82b2a8ffe69f42630da73ded0c92a7a36ebonwick if (zap != NULL) /* may be NULL if fzap_add() failed */
fa9e4066f08beec538e775443c5be79dd423fcabahrenszap_update(objset_t *os, uint64_t zapobj, const char *name,
fa9e4066f08beec538e775443c5be79dd423fcabahrens int integer_size, uint64_t num_integers, const void *val, dmu_tx_t *tx)
c5f9e43110e1fb316fc4297c2d150b3518b80bbeahrens err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, &zap);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw err = fzap_update(zn, integer_size, num_integers, val, tx);
ad860c82b2a8ffe69f42630da73ded0c92a7a36ebonwick zap = zn->zn_zap; /* fzap_update() may change zap */
fa9e4066f08beec538e775443c5be79dd423fcabahrens dprintf("upgrading obj %llu: intsz=%u numint=%llu name=%s\n",
ad860c82b2a8ffe69f42630da73ded0c92a7a36ebonwick zap = zn->zn_zap; /* fzap_update() may change zap */
ad860c82b2a8ffe69f42630da73ded0c92a7a36ebonwick if (zap != NULL) /* may be NULL if fzap_upgrade() failed */
fa9e4066f08beec538e775443c5be79dd423fcabahrenszap_remove(objset_t *os, uint64_t zapobj, const char *name, dmu_tx_t *tx)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (zap_remove_norm(os, zapobj, name, MT_EXACT, tx));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwzap_remove_norm(objset_t *os, uint64_t zapobj, const char *name,
c5f9e43110e1fb316fc4297c2d150b3518b80bbeahrens err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, FALSE, &zap);
fa9e4066f08beec538e775443c5be79dd423fcabahrens bzero(&zap->zap_m.zap_phys->mz_chunk[mze->mze_chunkid],
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Routines for iterating over the attributes.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * We want to keep the high 32 bits of the cursor zero if we can, so
fa9e4066f08beec538e775443c5be79dd423fcabahrens * that 32-bit programs can access this. So use a small hash value so
fa9e4066f08beec538e775443c5be79dd423fcabahrens * we can fit 4 bits of cd into the 32-bit cursor.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * [ 4 zero bits | 32-bit collision differentiator | 28-bit hash value ]
fa9e4066f08beec538e775443c5be79dd423fcabahrenszap_cursor_init_serialized(zap_cursor_t *zc, objset_t *os, uint64_t zapobj,
87e5029a3226958edab1512d6182bc74d8d80c9aahrenszap_cursor_init(zap_cursor_t *zc, objset_t *os, uint64_t zapobj)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1ULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrenszap_cursor_retrieve(zap_cursor_t *zc, zap_attribute_t *za)
87e5029a3226958edab1512d6182bc74d8d80c9aahrens err = zap_lockdir(zc->zc_objset, zc->zc_zapobj, NULL,
87e5029a3226958edab1512d6182bc74d8d80c9aahrens mze = avl_find(&zc->zc_zap->zap_m.zap_avl, &mze_tofind, &idx);
fa9e4066f08beec538e775443c5be79dd423fcabahrenszap_get_stats(objset_t *os, uint64_t zapobj, zap_stats_t *zs)
c5f9e43110e1fb316fc4297c2d150b3518b80bbeahrens err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, &zap);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);