From owner-svn-src-head@FreeBSD.ORG Tue Sep 11 07:12:49 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 4C4451065673; Tue, 11 Sep 2012 07:12:49 +0000 (UTC) (envelope-from avg@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 25A668FC20; Tue, 11 Sep 2012 07:12:49 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q8B7Cnn1098749; Tue, 11 Sep 2012 07:12:49 GMT (envelope-from avg@svn.freebsd.org) Received: (from avg@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q8B7Cm2c098747; Tue, 11 Sep 2012 07:12:48 GMT (envelope-from avg@svn.freebsd.org) Message-Id: <201209110712.q8B7Cm2c098747@svn.freebsd.org> From: Andriy Gapon Date: Tue, 11 Sep 2012 07:12:48 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r240347 - head/sys/boot/zfs X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 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: Tue, 11 Sep 2012 07:12:49 -0000 Author: avg Date: Tue Sep 11 07:12:48 2012 New Revision: 240347 URL: http://svn.freebsd.org/changeset/base/240347 Log: zfs boot: fix/replace fzap_rlookup implementation The previous one was totally bogus as it used hash value of _output_ variable as an index for searching... The only reliable way to do a reverse lookup here is to iterate over all entries. MFC after: 15 days Modified: head/sys/boot/zfs/zfsimpl.c Modified: head/sys/boot/zfs/zfsimpl.c ============================================================================== --- head/sys/boot/zfs/zfsimpl.c Tue Sep 11 07:11:32 2012 (r240346) +++ head/sys/boot/zfs/zfsimpl.c Tue Sep 11 07:12:48 2012 (r240347) @@ -1581,9 +1581,7 @@ fzap_rlookup(const spa_t *spa, const dno int bsize = dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT; zap_phys_t zh = *(zap_phys_t *) zap_scratch; fat_zap_t z; - uint64_t *ptrtbl; - uint64_t hash; - int rc; + int i, j; if (zh.zap_magic != ZAP_MAGIC) return (EIO); @@ -1592,59 +1590,34 @@ fzap_rlookup(const spa_t *spa, const dno z.zap_phys = (zap_phys_t *) zap_scratch; /* - * Figure out where the pointer table is and read it in if necessary. + * This assumes that the leaf blocks start at block 1. The + * documentation isn't exactly clear on this. */ - if (zh.zap_ptrtbl.zt_blk) { - rc = dnode_read(spa, dnode, zh.zap_ptrtbl.zt_blk * bsize, - zap_scratch, bsize); - if (rc) - return (rc); - ptrtbl = (uint64_t *) zap_scratch; - } else { - ptrtbl = &ZAP_EMBEDDED_PTRTBL_ENT(&z, 0); - } - - hash = zap_hash(zh.zap_salt, name); - zap_leaf_t zl; zl.l_bs = z.zap_block_shift; + for (i = 0; i < zh.zap_num_leafs; i++) { + off_t off = (i + 1) << zl.l_bs; - off_t off = ptrtbl[hash >> (64 - zh.zap_ptrtbl.zt_shift)] << zl.l_bs; - zap_leaf_chunk_t *zc; - - rc = dnode_read(spa, dnode, off, zap_scratch, bsize); - if (rc) - return (rc); + if (dnode_read(spa, dnode, off, zap_scratch, bsize)) + return (EIO); - zl.l_phys = (zap_leaf_phys_t *) zap_scratch; + zl.l_phys = (zap_leaf_phys_t *) zap_scratch; - /* - * Make sure this chunk matches our hash. - */ - if (zl.l_phys->l_hdr.lh_prefix_len > 0 - && zl.l_phys->l_hdr.lh_prefix - != hash >> (64 - zl.l_phys->l_hdr.lh_prefix_len)) - return (ENOENT); + for (j = 0; j < ZAP_LEAF_NUMCHUNKS(&zl); j++) { + zap_leaf_chunk_t *zc; - /* - * Hash within the chunk to find our entry. - */ - int shift = (64 - ZAP_LEAF_HASH_SHIFT(&zl) - zl.l_phys->l_hdr.lh_prefix_len); - int h = (hash >> shift) & ((1 << ZAP_LEAF_HASH_SHIFT(&zl)) - 1); - h = zl.l_phys->l_hash[h]; - if (h == 0xffff) - return (ENOENT); - zc = &ZAP_LEAF_CHUNK(&zl, h); - while (zc->l_entry.le_hash != hash) { - if (zc->l_entry.le_next == 0xffff) { - zc = 0; - break; + zc = &ZAP_LEAF_CHUNK(&zl, j); + if (zc->l_entry.le_type != ZAP_CHUNK_ENTRY) + continue; + if (zc->l_entry.le_value_intlen != 8 || + zc->l_entry.le_value_numints != 1) + continue; + + if (fzap_leaf_value(&zl, zc) == value) { + fzap_name_copy(&zl, zc, name); + return (0); + } } - zc = &ZAP_LEAF_CHUNK(&zl, zc->l_entry.le_next); - } - if (fzap_leaf_value(&zl, zc) == value) { - fzap_name_copy(&zl, zc, name); - return (0); } return (ENOENT);