From owner-svn-src-head@freebsd.org Wed May 11 12:46:09 2016 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 06FD9B363E9; Wed, 11 May 2016 12:46:09 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id D6FEF1E1F; Wed, 11 May 2016 12:46:08 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u4BCk84a057848; Wed, 11 May 2016 12:46:08 GMT (envelope-from mav@FreeBSD.org) Received: (from mav@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u4BCk7tW057846; Wed, 11 May 2016 12:46:07 GMT (envelope-from mav@FreeBSD.org) Message-Id: <201605111246.u4BCk7tW057846@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mav set sender to mav@FreeBSD.org using -f From: Alexander Motin Date: Wed, 11 May 2016 12:46:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r299439 - head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 11 May 2016 12:46:09 -0000 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 Reviewed by: Dan McDonald Reviewed by: Matthew Ahrens Approved by: Robert Mustacchi Author: Chunwei Chen openzfs/openzfs@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