svn commit: r299439 - head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs

Alexander Motin mav at FreeBSD.org
Wed May 11 12:46:09 UTC 2016


Author: mav
Date: Wed May 11 12:46:07 2016
New Revision: 299439
URL: https://svnweb.freebsd.org/changeset/base/299439

Log:
  MFV r299438: 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:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap.c
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c
Directory Properties:
  head/sys/cddl/contrib/opensolaris/   (props changed)

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap.c	Wed May 11 12:45:21 2016	(r299438)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap.c	Wed May 11 12:46:07 2016	(r299439)
@@ -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: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c	Wed May 11 12:45:21 2016	(r299438)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c	Wed May 11 12:46:07 2016	(r299439)
@@ -373,6 +373,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));
 
@@ -383,9 +386,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;
 	}
@@ -398,14 +405,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;
@@ -457,6 +458,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
@@ -483,8 +492,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-head mailing list