diff options
author | pjd <pjd@FreeBSD.org> | 2008-11-17 20:49:29 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2008-11-17 20:49:29 +0000 |
commit | bbe899b96e388a8b82439f81ed3707e0d9c6070d (patch) | |
tree | 81b89fa4ac6467771d5aa291a97f4665981a6108 /sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c | |
parent | d2f579595c362ce27b4d87e2c40e1c4e09b929e3 (diff) | |
download | FreeBSD-src-bbe899b96e388a8b82439f81ed3707e0d9c6070d.zip FreeBSD-src-bbe899b96e388a8b82439f81ed3707e0d9c6070d.tar.gz |
Update ZFS from version 6 to 13 and bring some FreeBSD-specific changes.
This bring huge amount of changes, I'll enumerate only user-visible changes:
- Delegated Administration
Allows regular users to perform ZFS operations, like file system
creation, snapshot creation, etc.
- L2ARC
Level 2 cache for ZFS - allows to use additional disks for cache.
Huge performance improvements mostly for random read of mostly
static content.
- slog
Allow to use additional disks for ZFS Intent Log to speed up
operations like fsync(2).
- vfs.zfs.super_owner
Allows regular users to perform privileged operations on files stored
on ZFS file systems owned by him. Very careful with this one.
- chflags(2)
Not all the flags are supported. This still needs work.
- ZFSBoot
Support to boot off of ZFS pool. Not finished, AFAIK.
Submitted by: dfr
- Snapshot properties
- New failure modes
Before if write requested failed, system paniced. Now one
can select from one of three failure modes:
- panic - panic on write error
- wait - wait for disk to reappear
- continue - serve read requests if possible, block write requests
- Refquota, refreservation properties
Just quota and reservation properties, but don't count space consumed
by children file systems, clones and snapshots.
- Sparse volumes
ZVOLs that don't reserve space in the pool.
- External attributes
Compatible with extattr(2).
- NFSv4-ACLs
Not sure about the status, might not be complete yet.
Submitted by: trasz
- Creation-time properties
- Regression tests for zpool(8) command.
Obtained from: OpenSolaris
Diffstat (limited to 'sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c')
-rw-r--r-- | sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c | 421 |
1 files changed, 317 insertions, 104 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c index 9a882a5..75b43a6 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,9 +34,104 @@ #include <sys/zap_leaf.h> #include <sys/avl.h> +#ifdef _KERNEL +#include <sys/sunddi.h> +#endif + +static int mzap_upgrade(zap_t **zapp, dmu_tx_t *tx); + + +static uint64_t +zap_hash(zap_t *zap, const char *normname) +{ + const uint8_t *cp; + uint8_t c; + uint64_t crc = zap->zap_salt; + + /* NB: name must already be normalized, if necessary */ + + ASSERT(crc != 0); + ASSERT(zfs_crc64_table[128] == ZFS_CRC64_POLY); + for (cp = (const uint8_t *)normname; (c = *cp) != '\0'; cp++) { + crc = (crc >> 8) ^ zfs_crc64_table[(crc ^ c) & 0xFF]; + } + + /* + * Only use 28 bits, since we need 4 bits in the cookie for the + * collision differentiator. We MUST use the high bits, since + * those are the ones that we first pay attention to when + * chosing the bucket. + */ + crc &= ~((1ULL << (64 - ZAP_HASHBITS)) - 1); -static void mzap_upgrade(zap_t *zap, dmu_tx_t *tx); + return (crc); +} + +static int +zap_normalize(zap_t *zap, const char *name, char *namenorm) +{ + size_t inlen, outlen; + int err; + + inlen = strlen(name) + 1; + outlen = ZAP_MAXNAMELEN; + + err = 0; + (void) u8_textprep_str((char *)name, &inlen, namenorm, &outlen, + zap->zap_normflags | U8_TEXTPREP_IGNORE_NULL, U8_UNICODE_LATEST, + &err); + + return (err); +} + +boolean_t +zap_match(zap_name_t *zn, const char *matchname) +{ + if (zn->zn_matchtype == MT_FIRST) { + char norm[ZAP_MAXNAMELEN]; + if (zap_normalize(zn->zn_zap, matchname, norm) != 0) + return (B_FALSE); + + return (strcmp(zn->zn_name_norm, norm) == 0); + } else { + /* MT_BEST or MT_EXACT */ + return (strcmp(zn->zn_name_orij, matchname) == 0); + } +} + +void +zap_name_free(zap_name_t *zn) +{ + kmem_free(zn, sizeof (zap_name_t)); +} + +/* XXX combine this with zap_lockdir()? */ +zap_name_t * +zap_name_alloc(zap_t *zap, const char *name, matchtype_t mt) +{ + zap_name_t *zn = kmem_alloc(sizeof (zap_name_t), KM_SLEEP); + + zn->zn_zap = zap; + zn->zn_name_orij = name; + zn->zn_matchtype = mt; + if (zap->zap_normflags) { + if (zap_normalize(zap, name, zn->zn_normbuf) != 0) { + zap_name_free(zn); + return (NULL); + } + zn->zn_name_norm = zn->zn_normbuf; + } else { + if (mt != MT_EXACT) { + zap_name_free(zn); + return (NULL); + } + zn->zn_name_norm = zn->zn_name_orij; + } + + zn->zn_hash = zap_hash(zap, zn->zn_name_norm); + return (zn); +} static void mzap_byteswap(mzap_phys_t *buf, size_t size) @@ -44,6 +139,7 @@ mzap_byteswap(mzap_phys_t *buf, size_t size) int i, max; buf->mz_block_type = BSWAP_64(buf->mz_block_type); buf->mz_salt = BSWAP_64(buf->mz_salt); + buf->mz_normflags = BSWAP_64(buf->mz_normflags); max = (size / MZAP_ENT_LEN) - 1; for (i = 0; i < max; i++) { buf->mz_chunk[i].mze_value = @@ -93,7 +189,6 @@ mze_insert(zap_t *zap, int chunkid, uint64_t hash, mzap_ent_phys_t *mzep) ASSERT(zap->zap_ismicro); ASSERT(RW_WRITE_HELD(&zap->zap_rwlock)); ASSERT(mzep->mze_cd < ZAP_MAXCD); - ASSERT3U(zap_hash(zap, mzep->mze_name), ==, hash); mze = kmem_alloc(sizeof (mzap_ent_t), KM_SLEEP); mze->mze_chunkid = chunkid; @@ -103,30 +198,34 @@ mze_insert(zap_t *zap, int chunkid, uint64_t hash, mzap_ent_phys_t *mzep) } static mzap_ent_t * -mze_find(zap_t *zap, const char *name, uint64_t hash) +mze_find(zap_name_t *zn) { mzap_ent_t mze_tofind; mzap_ent_t *mze; avl_index_t idx; - avl_tree_t *avl = &zap->zap_m.zap_avl; + avl_tree_t *avl = &zn->zn_zap->zap_m.zap_avl; - ASSERT(zap->zap_ismicro); - ASSERT(RW_LOCK_HELD(&zap->zap_rwlock)); - ASSERT3U(zap_hash(zap, name), ==, hash); + ASSERT(zn->zn_zap->zap_ismicro); + ASSERT(RW_LOCK_HELD(&zn->zn_zap->zap_rwlock)); - if (strlen(name) >= sizeof (mze_tofind.mze_phys.mze_name)) + if (strlen(zn->zn_name_norm) >= sizeof (mze_tofind.mze_phys.mze_name)) return (NULL); - mze_tofind.mze_hash = hash; + mze_tofind.mze_hash = zn->zn_hash; mze_tofind.mze_phys.mze_cd = 0; +again: mze = avl_find(avl, &mze_tofind, &idx); if (mze == NULL) mze = avl_nearest(avl, idx, AVL_AFTER); - for (; mze && mze->mze_hash == hash; mze = AVL_NEXT(avl, mze)) { - if (strcmp(name, mze->mze_phys.mze_name) == 0) + for (; mze && mze->mze_hash == zn->zn_hash; mze = AVL_NEXT(avl, mze)) { + if (zap_match(zn, mze->mze_phys.mze_name)) return (mze); } + if (zn->zn_matchtype == MT_BEST) { + zn->zn_matchtype = MT_FIRST; + goto again; + } return (NULL); } @@ -193,7 +292,7 @@ mzap_open(objset_t *os, uint64_t obj, dmu_buf_t *db) zap->zap_object = obj; zap->zap_dbuf = db; - if (((uint64_t *)db->db_data)[0] != ZBT_MICRO) { + if (*(uint64_t *)db->db_data != ZBT_MICRO) { mutex_init(&zap->zap_f.zap_num_entries_mtx, NULL, MUTEX_DEFAULT, 0); zap->zap_f.zap_block_shift = highbit(db->db_size) - 1; @@ -219,6 +318,7 @@ mzap_open(objset_t *os, uint64_t obj, dmu_buf_t *db) if (zap->zap_ismicro) { zap->zap_salt = zap->zap_m.zap_phys->mz_salt; + zap->zap_normflags = zap->zap_m.zap_phys->mz_normflags; zap->zap_m.zap_num_chunks = db->db_size / MZAP_ENT_LEN - 1; avl_create(&zap->zap_m.zap_avl, mze_compare, sizeof (mzap_ent_t), offsetof(mzap_ent_t, mze_node)); @@ -227,13 +327,18 @@ mzap_open(objset_t *os, uint64_t obj, dmu_buf_t *db) mzap_ent_phys_t *mze = &zap->zap_m.zap_phys->mz_chunk[i]; if (mze->mze_name[0]) { + zap_name_t *zn; + zap->zap_m.zap_num_entries++; - mze_insert(zap, i, - zap_hash(zap, mze->mze_name), mze); + zn = zap_name_alloc(zap, mze->mze_name, + MT_EXACT); + mze_insert(zap, i, zn->zn_hash, mze); + zap_name_free(zn); } } } else { zap->zap_salt = zap->zap_f.zap_phys->zap_salt; + zap->zap_normflags = zap->zap_f.zap_phys->zap_normflags; ASSERT3U(sizeof (struct zap_leaf_header), ==, 2*ZAP_LEAF_CHUNKSIZE); @@ -260,7 +365,7 @@ mzap_open(objset_t *os, uint64_t obj, dmu_buf_t *db) int zap_lockdir(objset_t *os, uint64_t obj, dmu_tx_t *tx, - krw_t lti, int fatreader, zap_t **zapp) + krw_t lti, boolean_t fatreader, boolean_t adding, zap_t **zapp) { zap_t *zap; dmu_buf_t *db; @@ -312,15 +417,14 @@ zap_lockdir(objset_t *os, uint64_t obj, dmu_tx_t *tx, ASSERT(!zap->zap_ismicro || zap->zap_m.zap_num_entries <= zap->zap_m.zap_num_chunks); - if (zap->zap_ismicro && tx && + if (zap->zap_ismicro && tx && adding && zap->zap_m.zap_num_entries == zap->zap_m.zap_num_chunks) { uint64_t newsz = db->db_size + SPA_MINBLOCKSIZE; if (newsz > MZAP_MAX_BLKSZ) { dprintf("upgrading obj %llu: num_entries=%u\n", obj, zap->zap_m.zap_num_entries); - mzap_upgrade(zap, tx); *zapp = zap; - return (0); + return (mzap_upgrade(zapp, tx)); } err = dmu_object_set_blocksize(os, obj, newsz, 0, tx); ASSERT3U(err, ==, 0); @@ -339,11 +443,12 @@ zap_unlockdir(zap_t *zap) dmu_buf_rele(zap->zap_dbuf, NULL); } -static void -mzap_upgrade(zap_t *zap, dmu_tx_t *tx) +static int +mzap_upgrade(zap_t **zapp, dmu_tx_t *tx) { mzap_phys_t *mzp; int i, sz, nchunks, err; + zap_t *zap = *zapp; ASSERT(RW_WRITE_HELD(&zap->zap_rwlock)); @@ -354,10 +459,14 @@ mzap_upgrade(zap_t *zap, dmu_tx_t *tx) err = dmu_object_set_blocksize(zap->zap_objset, zap->zap_object, 1ULL << fzap_default_block_shift, 0, tx); - ASSERT(err == 0); + if (err) { + kmem_free(mzp, sz); + return (err); + } dprintf("upgrading obj=%llu with %u chunks\n", zap->zap_object, nchunks); + /* XXX destroy the avl later, so we can use the stored hash value */ mze_destroy(zap); fzap_upgrade(zap, tx); @@ -365,44 +474,25 @@ mzap_upgrade(zap_t *zap, dmu_tx_t *tx) for (i = 0; i < nchunks; i++) { int err; mzap_ent_phys_t *mze = &mzp->mz_chunk[i]; + zap_name_t *zn; if (mze->mze_name[0] == 0) continue; dprintf("adding %s=%llu\n", mze->mze_name, mze->mze_value); - err = fzap_add_cd(zap, - mze->mze_name, 8, 1, &mze->mze_value, - mze->mze_cd, tx); - ASSERT3U(err, ==, 0); + zn = zap_name_alloc(zap, mze->mze_name, MT_EXACT); + err = fzap_add_cd(zn, 8, 1, &mze->mze_value, mze->mze_cd, tx); + zap = zn->zn_zap; /* fzap_add_cd() may change zap */ + zap_name_free(zn); + if (err) + break; } kmem_free(mzp, sz); + *zapp = zap; + return (err); } -uint64_t -zap_hash(zap_t *zap, const char *name) -{ - const uint8_t *cp; - uint8_t c; - uint64_t crc = zap->zap_salt; - - ASSERT(crc != 0); - ASSERT(zfs_crc64_table[128] == ZFS_CRC64_POLY); - for (cp = (const uint8_t *)name; (c = *cp) != '\0'; cp++) - crc = (crc >> 8) ^ zfs_crc64_table[(crc ^ c) & 0xFF]; - - /* - * Only use 28 bits, since we need 4 bits in the cookie for the - * collision differentiator. We MUST use the high bits, since - * those are the onces that we first pay attention to when - * chosing the bucket. - */ - crc &= ~((1ULL << (64 - ZAP_HASHBITS)) - 1); - - return (crc); -} - - static void -mzap_create_impl(objset_t *os, uint64_t obj, dmu_tx_t *tx) +mzap_create_impl(objset_t *os, uint64_t obj, int normflags, dmu_tx_t *tx) { dmu_buf_t *db; mzap_phys_t *zp; @@ -421,7 +511,7 @@ mzap_create_impl(objset_t *os, uint64_t obj, dmu_tx_t *tx) zp = db->db_data; zp->mz_block_type = ZBT_MICRO; zp->mz_salt = ((uintptr_t)db ^ (uintptr_t)tx ^ (obj << 1)) | 1ULL; - ASSERT(zp->mz_salt != 0); + zp->mz_normflags = normflags; dmu_buf_rele(db, FTAG); } @@ -429,12 +519,21 @@ int zap_create_claim(objset_t *os, uint64_t obj, dmu_object_type_t ot, dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx) { + return (zap_create_claim_norm(os, obj, + 0, ot, bonustype, bonuslen, tx)); +} + +int +zap_create_claim_norm(objset_t *os, uint64_t obj, int normflags, + dmu_object_type_t ot, + dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx) +{ int err; err = dmu_object_claim(os, obj, ot, 0, bonustype, bonuslen, tx); if (err != 0) return (err); - mzap_create_impl(os, obj, tx); + mzap_create_impl(os, obj, normflags, tx); return (0); } @@ -442,9 +541,16 @@ uint64_t zap_create(objset_t *os, dmu_object_type_t ot, dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx) { + return (zap_create_norm(os, 0, ot, bonustype, bonuslen, tx)); +} + +uint64_t +zap_create_norm(objset_t *os, int normflags, dmu_object_type_t ot, + dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx) +{ uint64_t obj = dmu_object_alloc(os, ot, 0, bonustype, bonuslen, tx); - mzap_create_impl(os, obj, tx); + mzap_create_impl(os, obj, normflags, tx); return (obj); } @@ -482,7 +588,7 @@ zap_count(objset_t *os, uint64_t zapobj, uint64_t *count) zap_t *zap; int err; - err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, &zap); + err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, &zap); if (err) return (err); if (!zap->zap_ismicro) { @@ -495,36 +601,102 @@ zap_count(objset_t *os, uint64_t zapobj, uint64_t *count) } /* - * Routines for maniplulating attributes. + * zn may be NULL; if not specified, it will be computed if needed. + * See also the comment above zap_entry_normalization_conflict(). + */ +static boolean_t +mzap_normalization_conflict(zap_t *zap, zap_name_t *zn, mzap_ent_t *mze) +{ + mzap_ent_t *other; + int direction = AVL_BEFORE; + boolean_t allocdzn = B_FALSE; + + if (zap->zap_normflags == 0) + return (B_FALSE); + +again: + for (other = avl_walk(&zap->zap_m.zap_avl, mze, direction); + other && other->mze_hash == mze->mze_hash; + other = avl_walk(&zap->zap_m.zap_avl, other, direction)) { + + if (zn == NULL) { + zn = zap_name_alloc(zap, mze->mze_phys.mze_name, + MT_FIRST); + allocdzn = B_TRUE; + } + if (zap_match(zn, other->mze_phys.mze_name)) { + if (allocdzn) + zap_name_free(zn); + return (B_TRUE); + } + } + + if (direction == AVL_BEFORE) { + direction = AVL_AFTER; + goto again; + } + + if (allocdzn) + zap_name_free(zn); + return (B_FALSE); +} + +/* + * Routines for manipulating attributes. */ int zap_lookup(objset_t *os, uint64_t zapobj, const char *name, uint64_t integer_size, uint64_t num_integers, void *buf) { + return (zap_lookup_norm(os, zapobj, name, integer_size, + num_integers, buf, MT_EXACT, NULL, 0, NULL)); +} + +int +zap_lookup_norm(objset_t *os, uint64_t zapobj, const char *name, + uint64_t integer_size, uint64_t num_integers, void *buf, + matchtype_t mt, char *realname, int rn_len, + boolean_t *ncp) +{ zap_t *zap; int err; mzap_ent_t *mze; + zap_name_t *zn; - err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, &zap); + err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, &zap); if (err) return (err); + zn = zap_name_alloc(zap, name, mt); + if (zn == NULL) { + zap_unlockdir(zap); + return (ENOTSUP); + } + if (!zap->zap_ismicro) { - err = fzap_lookup(zap, name, - integer_size, num_integers, buf); + err = fzap_lookup(zn, integer_size, num_integers, buf, + realname, rn_len, ncp); } else { - mze = mze_find(zap, name, zap_hash(zap, name)); + mze = mze_find(zn); if (mze == NULL) { err = ENOENT; } else { - if (num_integers < 1) + if (num_integers < 1) { err = EOVERFLOW; - else if (integer_size != 8) + } else if (integer_size != 8) { err = EINVAL; - else + } else { *(uint64_t *)buf = mze->mze_phys.mze_value; + (void) strlcpy(realname, + mze->mze_phys.mze_name, rn_len); + if (ncp) { + *ncp = mzap_normalization_conflict(zap, + zn, mze); + } + } } } + zap_name_free(zn); zap_unlockdir(zap); return (err); } @@ -536,14 +708,20 @@ zap_length(objset_t *os, uint64_t zapobj, const char *name, zap_t *zap; int err; mzap_ent_t *mze; + zap_name_t *zn; - err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, &zap); + err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, &zap); if (err) return (err); + zn = zap_name_alloc(zap, name, MT_EXACT); + if (zn == NULL) { + zap_unlockdir(zap); + return (ENOTSUP); + } if (!zap->zap_ismicro) { - err = fzap_length(zap, name, integer_size, num_integers); + err = fzap_length(zn, integer_size, num_integers); } else { - mze = mze_find(zap, name, zap_hash(zap, name)); + mze = mze_find(zn); if (mze == NULL) { err = ENOENT; } else { @@ -553,28 +731,31 @@ zap_length(objset_t *os, uint64_t zapobj, const char *name, *num_integers = 1; } } + zap_name_free(zn); zap_unlockdir(zap); return (err); } static void -mzap_addent(zap_t *zap, const char *name, uint64_t hash, uint64_t value) +mzap_addent(zap_name_t *zn, uint64_t value) { int i; + zap_t *zap = zn->zn_zap; int start = zap->zap_m.zap_alloc_next; uint32_t cd; - dprintf("obj=%llu %s=%llu\n", zap->zap_object, name, value); + dprintf("obj=%llu %s=%llu\n", zap->zap_object, + zn->zn_name_orij, value); ASSERT(RW_WRITE_HELD(&zap->zap_rwlock)); #ifdef ZFS_DEBUG for (i = 0; i < zap->zap_m.zap_num_chunks; i++) { mzap_ent_phys_t *mze = &zap->zap_m.zap_phys->mz_chunk[i]; - ASSERT(strcmp(name, mze->mze_name) != 0); + ASSERT(strcmp(zn->zn_name_orij, mze->mze_name) != 0); } #endif - cd = mze_find_unused_cd(zap, hash); + cd = mze_find_unused_cd(zap, zn->zn_hash); /* given the limited size of the microzap, this can't happen */ ASSERT(cd != ZAP_MAXCD); @@ -584,13 +765,13 @@ again: if (mze->mze_name[0] == 0) { mze->mze_value = value; mze->mze_cd = cd; - (void) strcpy(mze->mze_name, name); + (void) strcpy(mze->mze_name, zn->zn_name_orij); zap->zap_m.zap_num_entries++; zap->zap_m.zap_alloc_next = i+1; if (zap->zap_m.zap_alloc_next == zap->zap_m.zap_num_chunks) zap->zap_m.zap_alloc_next = 0; - mze_insert(zap, i, hash, mze); + mze_insert(zap, i, zn->zn_hash, mze); return; } } @@ -610,29 +791,39 @@ zap_add(objset_t *os, uint64_t zapobj, const char *name, int err; mzap_ent_t *mze; const uint64_t *intval = val; - uint64_t hash; + zap_name_t *zn; - err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, &zap); + err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, &zap); if (err) return (err); + zn = zap_name_alloc(zap, name, MT_EXACT); + if (zn == NULL) { + zap_unlockdir(zap); + return (ENOTSUP); + } if (!zap->zap_ismicro) { - err = fzap_add(zap, name, integer_size, num_integers, val, tx); + err = fzap_add(zn, integer_size, num_integers, val, tx); + zap = zn->zn_zap; /* fzap_add() may change zap */ } else if (integer_size != 8 || num_integers != 1 || strlen(name) >= MZAP_NAME_LEN) { dprintf("upgrading obj %llu: intsz=%u numint=%llu name=%s\n", zapobj, integer_size, num_integers, name); - mzap_upgrade(zap, tx); - err = fzap_add(zap, name, integer_size, num_integers, val, tx); + err = mzap_upgrade(&zn->zn_zap, tx); + if (err == 0) + err = fzap_add(zn, integer_size, num_integers, val, tx); + zap = zn->zn_zap; /* fzap_add() may change zap */ } else { - hash = zap_hash(zap, name); - mze = mze_find(zap, name, hash); + mze = mze_find(zn); if (mze != NULL) { err = EEXIST; } else { - mzap_addent(zap, name, hash, *intval); + mzap_addent(zn, *intval); } } - zap_unlockdir(zap); + ASSERT(zap == zn->zn_zap); + zap_name_free(zn); + if (zap != NULL) /* may be NULL if fzap_add() failed */ + zap_unlockdir(zap); return (err); } @@ -643,68 +834,87 @@ zap_update(objset_t *os, uint64_t zapobj, const char *name, zap_t *zap; mzap_ent_t *mze; const uint64_t *intval = val; - uint64_t hash; + zap_name_t *zn; int err; - err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, &zap); + err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, &zap); if (err) return (err); - ASSERT(RW_LOCK_HELD(&zap->zap_rwlock)); + zn = zap_name_alloc(zap, name, MT_EXACT); + if (zn == NULL) { + zap_unlockdir(zap); + return (ENOTSUP); + } if (!zap->zap_ismicro) { - err = fzap_update(zap, name, - integer_size, num_integers, val, tx); + err = fzap_update(zn, integer_size, num_integers, val, tx); + zap = zn->zn_zap; /* fzap_update() may change zap */ } else if (integer_size != 8 || num_integers != 1 || strlen(name) >= MZAP_NAME_LEN) { dprintf("upgrading obj %llu: intsz=%u numint=%llu name=%s\n", zapobj, integer_size, num_integers, name); - mzap_upgrade(zap, tx); - err = fzap_update(zap, name, - integer_size, num_integers, val, tx); + err = mzap_upgrade(&zn->zn_zap, tx); + if (err == 0) + err = fzap_update(zn, integer_size, num_integers, + val, tx); + zap = zn->zn_zap; /* fzap_update() may change zap */ } else { - hash = zap_hash(zap, name); - mze = mze_find(zap, name, hash); + mze = mze_find(zn); if (mze != NULL) { mze->mze_phys.mze_value = *intval; zap->zap_m.zap_phys->mz_chunk [mze->mze_chunkid].mze_value = *intval; } else { - mzap_addent(zap, name, hash, *intval); + mzap_addent(zn, *intval); } } - zap_unlockdir(zap); + ASSERT(zap == zn->zn_zap); + zap_name_free(zn); + if (zap != NULL) /* may be NULL if fzap_upgrade() failed */ + zap_unlockdir(zap); return (err); } int zap_remove(objset_t *os, uint64_t zapobj, const char *name, dmu_tx_t *tx) { + return (zap_remove_norm(os, zapobj, name, MT_EXACT, tx)); +} + +int +zap_remove_norm(objset_t *os, uint64_t zapobj, const char *name, + matchtype_t mt, dmu_tx_t *tx) +{ zap_t *zap; int err; mzap_ent_t *mze; + zap_name_t *zn; - err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, &zap); + err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, FALSE, &zap); if (err) return (err); + zn = zap_name_alloc(zap, name, mt); + if (zn == NULL) { + zap_unlockdir(zap); + return (ENOTSUP); + } if (!zap->zap_ismicro) { - err = fzap_remove(zap, name, tx); + err = fzap_remove(zn, tx); } else { - mze = mze_find(zap, name, zap_hash(zap, name)); + mze = mze_find(zn); if (mze == NULL) { - dprintf("fail: %s\n", name); err = ENOENT; } else { - dprintf("success: %s\n", name); zap->zap_m.zap_num_entries--; bzero(&zap->zap_m.zap_phys->mz_chunk[mze->mze_chunkid], sizeof (mzap_ent_phys_t)); mze_remove(zap, mze); } } + zap_name_free(zn); zap_unlockdir(zap); return (err); } - /* * Routines for iterating over the attributes. */ @@ -781,7 +991,7 @@ zap_cursor_retrieve(zap_cursor_t *zc, zap_attribute_t *za) if (zc->zc_zap == NULL) { err = zap_lockdir(zc->zc_objset, zc->zc_zapobj, NULL, - RW_READER, TRUE, &zc->zc_zap); + RW_READER, TRUE, FALSE, &zc->zc_zap); if (err) return (err); } else { @@ -796,14 +1006,17 @@ zap_cursor_retrieve(zap_cursor_t *zc, zap_attribute_t *za) mze_tofind.mze_phys.mze_cd = zc->zc_cd; mze = avl_find(&zc->zc_zap->zap_m.zap_avl, &mze_tofind, &idx); - ASSERT(mze == NULL || 0 == bcmp(&mze->mze_phys, - &zc->zc_zap->zap_m.zap_phys->mz_chunk[mze->mze_chunkid], - sizeof (mze->mze_phys))); if (mze == NULL) { mze = avl_nearest(&zc->zc_zap->zap_m.zap_avl, idx, AVL_AFTER); } if (mze) { + ASSERT(0 == bcmp(&mze->mze_phys, + &zc->zc_zap->zap_m.zap_phys->mz_chunk + [mze->mze_chunkid], sizeof (mze->mze_phys))); + + za->za_normalization_conflict = + mzap_normalization_conflict(zc->zc_zap, NULL, mze); za->za_integer_length = 8; za->za_num_integers = 1; za->za_first_integer = mze->mze_phys.mze_value; @@ -839,7 +1052,7 @@ zap_get_stats(objset_t *os, uint64_t zapobj, zap_stats_t *zs) int err; zap_t *zap; - err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, &zap); + err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, &zap); if (err) return (err); |