1eda14cbcSMatt Macy /* 2eda14cbcSMatt Macy * CDDL HEADER START 3eda14cbcSMatt Macy * 4eda14cbcSMatt Macy * The contents of this file are subject to the terms of the 5eda14cbcSMatt Macy * Common Development and Distribution License (the "License"). 6eda14cbcSMatt Macy * You may not use this file except in compliance with the License. 7eda14cbcSMatt Macy * 8eda14cbcSMatt Macy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9271171e0SMartin Matuska * or https://opensource.org/licenses/CDDL-1.0. 10eda14cbcSMatt Macy * See the License for the specific language governing permissions 11eda14cbcSMatt Macy * and limitations under the License. 12eda14cbcSMatt Macy * 13eda14cbcSMatt Macy * When distributing Covered Code, include this CDDL HEADER in each 14eda14cbcSMatt Macy * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15eda14cbcSMatt Macy * If applicable, add the following below this CDDL HEADER, with the 16eda14cbcSMatt Macy * fields enclosed by brackets "[]" replaced with your own identifying 17eda14cbcSMatt Macy * information: Portions Copyright [yyyy] [name of copyright owner] 18eda14cbcSMatt Macy * 19eda14cbcSMatt Macy * CDDL HEADER END 20eda14cbcSMatt Macy */ 21eda14cbcSMatt Macy 22eda14cbcSMatt Macy /* 23eda14cbcSMatt Macy * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 24eda14cbcSMatt Macy * Copyright (c) 2018 by Delphix. All rights reserved. 25eda14cbcSMatt Macy */ 26eda14cbcSMatt Macy 27eda14cbcSMatt Macy #include <sys/zfs_context.h> 28eda14cbcSMatt Macy #include <sys/spa.h> 29eda14cbcSMatt Macy #include <sys/zio.h> 30eda14cbcSMatt Macy #include <sys/ddt.h> 31eda14cbcSMatt Macy #include <sys/zap.h> 32eda14cbcSMatt Macy #include <sys/dmu_tx.h> 33eda14cbcSMatt Macy 34*0a97523dSMartin Matuska static unsigned int ddt_zap_default_bs = 15; 35*0a97523dSMartin Matuska static unsigned int ddt_zap_default_ibs = 15; 36eda14cbcSMatt Macy 37eda14cbcSMatt Macy static int 38eda14cbcSMatt Macy ddt_zap_create(objset_t *os, uint64_t *objectp, dmu_tx_t *tx, boolean_t prehash) 39eda14cbcSMatt Macy { 40eda14cbcSMatt Macy zap_flags_t flags = ZAP_FLAG_HASH64 | ZAP_FLAG_UINT64_KEY; 41eda14cbcSMatt Macy 42eda14cbcSMatt Macy if (prehash) 43eda14cbcSMatt Macy flags |= ZAP_FLAG_PRE_HASHED_KEY; 44eda14cbcSMatt Macy 45eda14cbcSMatt Macy *objectp = zap_create_flags(os, 0, flags, DMU_OT_DDT_ZAP, 46*0a97523dSMartin Matuska ddt_zap_default_bs, ddt_zap_default_ibs, 47eda14cbcSMatt Macy DMU_OT_NONE, 0, tx); 48eda14cbcSMatt Macy 49eda14cbcSMatt Macy return (*objectp == 0 ? SET_ERROR(ENOTSUP) : 0); 50eda14cbcSMatt Macy } 51eda14cbcSMatt Macy 52eda14cbcSMatt Macy static int 53eda14cbcSMatt Macy ddt_zap_destroy(objset_t *os, uint64_t object, dmu_tx_t *tx) 54eda14cbcSMatt Macy { 55eda14cbcSMatt Macy return (zap_destroy(os, object, tx)); 56eda14cbcSMatt Macy } 57eda14cbcSMatt Macy 58eda14cbcSMatt Macy static int 59eda14cbcSMatt Macy ddt_zap_lookup(objset_t *os, uint64_t object, ddt_entry_t *dde) 60eda14cbcSMatt Macy { 61eda14cbcSMatt Macy uchar_t *cbuf; 62eda14cbcSMatt Macy uint64_t one, csize; 63eda14cbcSMatt Macy int error; 64eda14cbcSMatt Macy 65eda14cbcSMatt Macy cbuf = kmem_alloc(sizeof (dde->dde_phys) + 1, KM_SLEEP); 66eda14cbcSMatt Macy 67eda14cbcSMatt Macy error = zap_length_uint64(os, object, (uint64_t *)&dde->dde_key, 68eda14cbcSMatt Macy DDT_KEY_WORDS, &one, &csize); 69eda14cbcSMatt Macy if (error) 70eda14cbcSMatt Macy goto out; 71eda14cbcSMatt Macy 72eda14cbcSMatt Macy ASSERT(one == 1); 73eda14cbcSMatt Macy ASSERT(csize <= (sizeof (dde->dde_phys) + 1)); 74eda14cbcSMatt Macy 75eda14cbcSMatt Macy error = zap_lookup_uint64(os, object, (uint64_t *)&dde->dde_key, 76eda14cbcSMatt Macy DDT_KEY_WORDS, 1, csize, cbuf); 77eda14cbcSMatt Macy if (error) 78eda14cbcSMatt Macy goto out; 79eda14cbcSMatt Macy 80eda14cbcSMatt Macy ddt_decompress(cbuf, dde->dde_phys, csize, sizeof (dde->dde_phys)); 81eda14cbcSMatt Macy out: 82eda14cbcSMatt Macy kmem_free(cbuf, sizeof (dde->dde_phys) + 1); 83eda14cbcSMatt Macy 84eda14cbcSMatt Macy return (error); 85eda14cbcSMatt Macy } 86eda14cbcSMatt Macy 87eda14cbcSMatt Macy static void 88eda14cbcSMatt Macy ddt_zap_prefetch(objset_t *os, uint64_t object, ddt_entry_t *dde) 89eda14cbcSMatt Macy { 90eda14cbcSMatt Macy (void) zap_prefetch_uint64(os, object, (uint64_t *)&dde->dde_key, 91eda14cbcSMatt Macy DDT_KEY_WORDS); 92eda14cbcSMatt Macy } 93eda14cbcSMatt Macy 94eda14cbcSMatt Macy static int 95eda14cbcSMatt Macy ddt_zap_update(objset_t *os, uint64_t object, ddt_entry_t *dde, dmu_tx_t *tx) 96eda14cbcSMatt Macy { 97eda14cbcSMatt Macy uchar_t cbuf[sizeof (dde->dde_phys) + 1]; 98eda14cbcSMatt Macy uint64_t csize; 99eda14cbcSMatt Macy 100eda14cbcSMatt Macy csize = ddt_compress(dde->dde_phys, cbuf, 101eda14cbcSMatt Macy sizeof (dde->dde_phys), sizeof (cbuf)); 102eda14cbcSMatt Macy 103eda14cbcSMatt Macy return (zap_update_uint64(os, object, (uint64_t *)&dde->dde_key, 104eda14cbcSMatt Macy DDT_KEY_WORDS, 1, csize, cbuf, tx)); 105eda14cbcSMatt Macy } 106eda14cbcSMatt Macy 107eda14cbcSMatt Macy static int 108eda14cbcSMatt Macy ddt_zap_remove(objset_t *os, uint64_t object, ddt_entry_t *dde, dmu_tx_t *tx) 109eda14cbcSMatt Macy { 110eda14cbcSMatt Macy return (zap_remove_uint64(os, object, (uint64_t *)&dde->dde_key, 111eda14cbcSMatt Macy DDT_KEY_WORDS, tx)); 112eda14cbcSMatt Macy } 113eda14cbcSMatt Macy 114eda14cbcSMatt Macy static int 115eda14cbcSMatt Macy ddt_zap_walk(objset_t *os, uint64_t object, ddt_entry_t *dde, uint64_t *walk) 116eda14cbcSMatt Macy { 117eda14cbcSMatt Macy zap_cursor_t zc; 118eda14cbcSMatt Macy zap_attribute_t za; 119eda14cbcSMatt Macy int error; 120eda14cbcSMatt Macy 121eda14cbcSMatt Macy if (*walk == 0) { 122eda14cbcSMatt Macy /* 123eda14cbcSMatt Macy * We don't want to prefetch the entire ZAP object, because 124eda14cbcSMatt Macy * it can be enormous. Also the primary use of DDT iteration 125eda14cbcSMatt Macy * is for scrubbing, in which case we will be issuing many 126eda14cbcSMatt Macy * scrub I/Os for each ZAP block that we read in, so 127eda14cbcSMatt Macy * reading the ZAP is unlikely to be the bottleneck. 128eda14cbcSMatt Macy */ 129eda14cbcSMatt Macy zap_cursor_init_noprefetch(&zc, os, object); 130eda14cbcSMatt Macy } else { 131eda14cbcSMatt Macy zap_cursor_init_serialized(&zc, os, object, *walk); 132eda14cbcSMatt Macy } 133eda14cbcSMatt Macy if ((error = zap_cursor_retrieve(&zc, &za)) == 0) { 134eda14cbcSMatt Macy uchar_t cbuf[sizeof (dde->dde_phys) + 1]; 135eda14cbcSMatt Macy uint64_t csize = za.za_num_integers; 136eda14cbcSMatt Macy ASSERT(za.za_integer_length == 1); 137eda14cbcSMatt Macy error = zap_lookup_uint64(os, object, (uint64_t *)za.za_name, 138eda14cbcSMatt Macy DDT_KEY_WORDS, 1, csize, cbuf); 139eda14cbcSMatt Macy ASSERT(error == 0); 140eda14cbcSMatt Macy if (error == 0) { 141eda14cbcSMatt Macy ddt_decompress(cbuf, dde->dde_phys, csize, 142eda14cbcSMatt Macy sizeof (dde->dde_phys)); 143eda14cbcSMatt Macy dde->dde_key = *(ddt_key_t *)za.za_name; 144eda14cbcSMatt Macy } 145eda14cbcSMatt Macy zap_cursor_advance(&zc); 146eda14cbcSMatt Macy *walk = zap_cursor_serialize(&zc); 147eda14cbcSMatt Macy } 148eda14cbcSMatt Macy zap_cursor_fini(&zc); 149eda14cbcSMatt Macy return (error); 150eda14cbcSMatt Macy } 151eda14cbcSMatt Macy 152eda14cbcSMatt Macy static int 153eda14cbcSMatt Macy ddt_zap_count(objset_t *os, uint64_t object, uint64_t *count) 154eda14cbcSMatt Macy { 155eda14cbcSMatt Macy return (zap_count(os, object, count)); 156eda14cbcSMatt Macy } 157eda14cbcSMatt Macy 158eda14cbcSMatt Macy const ddt_ops_t ddt_zap_ops = { 159eda14cbcSMatt Macy "zap", 160eda14cbcSMatt Macy ddt_zap_create, 161eda14cbcSMatt Macy ddt_zap_destroy, 162eda14cbcSMatt Macy ddt_zap_lookup, 163eda14cbcSMatt Macy ddt_zap_prefetch, 164eda14cbcSMatt Macy ddt_zap_update, 165eda14cbcSMatt Macy ddt_zap_remove, 166eda14cbcSMatt Macy ddt_zap_walk, 167eda14cbcSMatt Macy ddt_zap_count, 168eda14cbcSMatt Macy }; 169*0a97523dSMartin Matuska 170*0a97523dSMartin Matuska /* BEGIN CSTYLED */ 171*0a97523dSMartin Matuska ZFS_MODULE_PARAM(zfs_dedup, , ddt_zap_default_bs, UINT, ZMOD_RW, 172*0a97523dSMartin Matuska "DDT ZAP leaf blockshift"); 173*0a97523dSMartin Matuska ZFS_MODULE_PARAM(zfs_dedup, , ddt_zap_default_ibs, UINT, ZMOD_RW, 174*0a97523dSMartin Matuska "DDT ZAP indirect blockshift"); 175*0a97523dSMartin Matuska /* END CSTYLED */ 176