diff options
author | Chunwei Chen <tuxoko@gmail.com> | 2016-03-25 15:21:56 -0400 |
---|---|---|
committer | Dan McDonald <danmcd@omniti.com> | 2016-04-05 10:41:38 -0400 |
commit | 02525cd08fb3730fff3a69cb5376443d481f7839 (patch) | |
tree | e7c0e53061fdef88f3307a8a88019113a4c33497 | |
parent | 399cc7d5d9aff97c714b708af3e3f0280ceab93f (diff) | |
download | illumos-joyent-02525cd08fb3730fff3a69cb5376443d481f7839.tar.gz |
6842 Fix empty xattr dir causing lockup
Reviewed by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed by: Dan McDonald <danmcd@omniti.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Approved by: Robert Mustacchi <rm@joyent.com>
-rw-r--r-- | usr/src/uts/common/fs/zfs/zap.c | 9 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/zap_micro.c | 38 |
2 files changed, 36 insertions, 11 deletions
diff --git a/usr/src/uts/common/fs/zfs/zap.c b/usr/src/uts/common/fs/zfs/zap.c index 2ea6b12219..c3bb19e11f 100644 --- a/usr/src/uts/common/fs/zfs/zap.c +++ b/usr/src/uts/common/fs/zfs/zap.c @@ -575,7 +575,14 @@ zap_deref_leaf(zap_t *zap, uint64_t h, dmu_tx_t *tx, krw_t lt, zap_leaf_t **lp) ASSERT(zap->zap_dbuf == NULL || zap_f_phys(zap) == zap->zap_dbuf->db_data); - ASSERT3U(zap_f_phys(zap)->zap_magic, ==, ZAP_MAGIC); + + /* Reality check for corrupt zap objects (leaf or header). */ + if ((zap_f_phys(zap)->zap_block_type != ZBT_LEAF && + zap_f_phys(zap)->zap_block_type != ZBT_HEADER) || + zap_f_phys(zap)->zap_magic != ZAP_MAGIC) { + return (SET_ERROR(EIO)); + } + idx = ZAP_HASH_IDX(h, zap_f_phys(zap)->zap_ptrtbl.zt_shift); err = zap_idx_to_blk(zap, idx, &blk); if (err != 0) diff --git a/usr/src/uts/common/fs/zfs/zap_micro.c b/usr/src/uts/common/fs/zfs/zap_micro.c index f51cc7b529..58acea3663 100644 --- a/usr/src/uts/common/fs/zfs/zap_micro.c +++ b/usr/src/uts/common/fs/zfs/zap_micro.c @@ -367,6 +367,9 @@ mzap_open(objset_t *os, uint64_t obj, dmu_buf_t *db) zap_t *winner; zap_t *zap; int i; + uint64_t *zap_hdr = (uint64_t *)db->db_data; + uint64_t zap_block_type = zap_hdr[0]; + uint64_t zap_magic = zap_hdr[1]; ASSERT3U(MZAP_ENT_LEN, ==, sizeof (mzap_ent_phys_t)); @@ -377,9 +380,13 @@ 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 != ZBT_MICRO) { + if (zap_block_type != ZBT_MICRO) { mutex_init(&zap->zap_f.zap_num_entries_mtx, 0, 0, 0); zap->zap_f.zap_block_shift = highbit64(db->db_size) - 1; + if (zap_block_type != ZBT_HEADER || zap_magic != ZAP_MAGIC) { + winner = NULL; /* No actual winner here... */ + goto handle_winner; + } } else { zap->zap_ismicro = TRUE; } @@ -392,14 +399,8 @@ mzap_open(objset_t *os, uint64_t obj, dmu_buf_t *db) dmu_buf_init_user(&zap->zap_dbu, zap_evict, &zap->zap_dbuf); winner = dmu_buf_set_user(db, &zap->zap_dbu); - if (winner != NULL) { - rw_exit(&zap->zap_rwlock); - rw_destroy(&zap->zap_rwlock); - if (!zap->zap_ismicro) - mutex_destroy(&zap->zap_f.zap_num_entries_mtx); - kmem_free(zap, sizeof (zap_t)); - return (winner); - } + if (winner != NULL) + goto handle_winner; if (zap->zap_ismicro) { zap->zap_salt = zap_m_phys(zap)->mz_salt; @@ -446,6 +447,14 @@ mzap_open(objset_t *os, uint64_t obj, dmu_buf_t *db) } rw_exit(&zap->zap_rwlock); return (zap); + +handle_winner: + rw_exit(&zap->zap_rwlock); + rw_destroy(&zap->zap_rwlock); + if (!zap->zap_ismicro) + mutex_destroy(&zap->zap_f.zap_num_entries_mtx); + kmem_free(zap, sizeof (zap_t)); + return (winner); } int @@ -472,8 +481,17 @@ zap_lockdir(objset_t *os, uint64_t obj, dmu_tx_t *tx, #endif zap = dmu_buf_get_user(db); - if (zap == NULL) + if (zap == NULL) { zap = mzap_open(os, obj, db); + if (zap == NULL) { + /* + * mzap_open() didn't like what it saw on-disk. + * Check for corruption! + */ + dmu_buf_rele(db, NULL); + return (SET_ERROR(EIO)); + } + } /* * We're checking zap_ismicro without the lock held, in order to |