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> Author: Chunwei Chen <tuxoko@gmail.com> openzfs/openzfs@02525cd08f
This commit is contained in:
parent
563eb27902
commit
4e5a6ab1d7
@ -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 ||
|
ASSERT(zap->zap_dbuf == NULL ||
|
||||||
zap_f_phys(zap) == zap->zap_dbuf->db_data);
|
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);
|
idx = ZAP_HASH_IDX(h, zap_f_phys(zap)->zap_ptrtbl.zt_shift);
|
||||||
err = zap_idx_to_blk(zap, idx, &blk);
|
err = zap_idx_to_blk(zap, idx, &blk);
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
|
@ -367,6 +367,9 @@ mzap_open(objset_t *os, uint64_t obj, dmu_buf_t *db)
|
|||||||
zap_t *winner;
|
zap_t *winner;
|
||||||
zap_t *zap;
|
zap_t *zap;
|
||||||
int i;
|
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));
|
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_object = obj;
|
||||||
zap->zap_dbuf = db;
|
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);
|
mutex_init(&zap->zap_f.zap_num_entries_mtx, 0, 0, 0);
|
||||||
zap->zap_f.zap_block_shift = highbit64(db->db_size) - 1;
|
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 {
|
} else {
|
||||||
zap->zap_ismicro = TRUE;
|
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);
|
dmu_buf_init_user(&zap->zap_dbu, zap_evict, &zap->zap_dbuf);
|
||||||
winner = dmu_buf_set_user(db, &zap->zap_dbu);
|
winner = dmu_buf_set_user(db, &zap->zap_dbu);
|
||||||
|
|
||||||
if (winner != NULL) {
|
if (winner != NULL)
|
||||||
rw_exit(&zap->zap_rwlock);
|
goto handle_winner;
|
||||||
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 (zap->zap_ismicro) {
|
if (zap->zap_ismicro) {
|
||||||
zap->zap_salt = zap_m_phys(zap)->mz_salt;
|
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);
|
rw_exit(&zap->zap_rwlock);
|
||||||
return (zap);
|
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
|
int
|
||||||
@ -472,8 +481,17 @@ zap_lockdir(objset_t *os, uint64_t obj, dmu_tx_t *tx,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
zap = dmu_buf_get_user(db);
|
zap = dmu_buf_get_user(db);
|
||||||
if (zap == NULL)
|
if (zap == NULL) {
|
||||||
zap = mzap_open(os, obj, db);
|
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
|
* We're checking zap_ismicro without the lock held, in order to
|
||||||
|
Loading…
x
Reference in New Issue
Block a user