svn commit: r299438 - vendor-sys/illumos/dist/uts/common/fs/zfs
Alexander Motin
mav at FreeBSD.org
Wed May 11 12:45:22 UTC 2016
Author: mav
Date: Wed May 11 12:45:21 2016
New Revision: 299438
URL: https://svnweb.freebsd.org/changeset/base/299438
Log:
6842 Fix empty xattr dir causing lockup
Reviewed by: Brian Behlendorf <behlendorf1 at llnl.gov>
Reviewed by: Dan McDonald <danmcd at omniti.com>
Reviewed by: Matthew Ahrens <mahrens at delphix.com>
Approved by: Robert Mustacchi <rm at joyent.com>
Author: Chunwei Chen <tuxoko at gmail.com>
openzfs/openzfs at 02525cd08fb3730fff3a69cb5376443d481f7839
Modified:
vendor-sys/illumos/dist/uts/common/fs/zfs/zap.c
vendor-sys/illumos/dist/uts/common/fs/zfs/zap_micro.c
Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/zap.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/zap.c Wed May 11 12:43:54 2016 (r299437)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/zap.c Wed May 11 12:45:21 2016 (r299438)
@@ -575,7 +575,14 @@ zap_deref_leaf(zap_t *zap, uint64_t h, d
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)
Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/zap_micro.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/zap_micro.c Wed May 11 12:43:54 2016 (r299437)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/zap_micro.c Wed May 11 12:45:21 2016 (r299438)
@@ -367,6 +367,9 @@ mzap_open(objset_t *os, uint64_t obj, dm
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, dm
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, dm
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, dm
}
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,
#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
More information about the svn-src-vendor
mailing list