fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER START
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The contents of this file are subject to the terms of the
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Common Development and Distribution License (the "License").
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * You may not use this file except in compliance with the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fa9e4066f08beec538e775443c5be79dd423fcabahrens * or http://www.opensolaris.org/os/licensing.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * See the License for the specific language governing permissions
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and limitations under the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * When distributing Covered Code, include this CDDL HEADER in each
fa9e4066f08beec538e775443c5be79dd423fcabahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If applicable, add the following below this CDDL HEADER, with the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * fields enclosed by brackets "[]" replaced with your own identifying
fa9e4066f08beec538e775443c5be79dd423fcabahrens * information: Portions Copyright [yyyy] [name of copyright owner]
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER END
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
8df0bcf0df7622a075cc6e52f659d2fcfdd08cdcPaul Dagnelie * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
aad02571bc59671aa3103bb070ae365f531b0b62Saso Kiselkov/* Copyright (c) 2013 by Saso Kiselkov. All rights reserved. */
810e43b2eb0e320833671a403fdda51917e8b036Bill Pijewski/* Copyright (c) 2013, Joyent, Inc. All rights reserved. */
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk/* Copyright 2016 Nexenta Systems, Inc. All rights reserved. */
aad02571bc59671aa3103bb070ae365f531b0b62Saso Kiselkov
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/dmu.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/dmu_impl.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/dmu_tx.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/dbuf.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/dnode.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/zfs_context.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/dmu_objset.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/dmu_traverse.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/dsl_dataset.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/dsl_dir.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/dsl_pool.h>
1d452cf5123cb6ac0a013a4dbd4dcceeb0da314dahrens#include <sys/dsl_synctask.h>
a2eea2e101e6a163a537dcc6d4e3c4da2a0ea5b2ahrens#include <sys/dsl_prop.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/dmu_zfetch.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/zfs_ioctl.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/zap.h>
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock#include <sys/zio_checksum.h>
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson#include <sys/zio_compress.h>
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum#include <sys/sa.h>
b8289d24d866c1af02d7007348f7f057693c15d3Daniil Lunev#include <sys/zfeature.h>
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee#ifdef _KERNEL
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee#include <sys/vmsystm.h>
0fab61babcfe4e703c15518d8ef8d07e1a545650Jonathan W Adams#include <sys/zfs_znode.h>
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee#endif
fa9e4066f08beec538e775443c5be79dd423fcabahrens
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson/*
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson * Enable/disable nopwrite feature.
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson */
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilsonint zfs_nopwrite_enabled = 1;
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson
fa9e4066f08beec538e775443c5be79dd423fcabahrensconst dmu_object_type_info_t dmu_ot[DMU_OT_NUMTYPES] = {
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_UINT8, TRUE, "unallocated" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "object directory" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_UINT64, TRUE, "object array" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_UINT8, TRUE, "packed nvlist" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_UINT64, TRUE, "packed nvlist size" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_UINT64, TRUE, "bpobj" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_UINT64, TRUE, "bpobj header" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_UINT64, TRUE, "SPA space map header" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_UINT64, TRUE, "SPA space map" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_UINT64, TRUE, "ZIL intent log" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_DNODE, TRUE, "DMU dnode" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_OBJSET, TRUE, "DMU objset" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_UINT64, TRUE, "DSL directory" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "DSL directory child map"},
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "DSL dataset snap map" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "DSL props" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_UINT64, TRUE, "DSL dataset" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZNODE, TRUE, "ZFS znode" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_OLDACL, TRUE, "ZFS V0 ACL" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_UINT8, FALSE, "ZFS plain file" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "ZFS directory" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "ZFS master node" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "ZFS delete queue" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_UINT8, FALSE, "zvol object" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "zvol prop" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_UINT8, FALSE, "other uint8[]" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_UINT64, FALSE, "other uint64[]" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "other ZAP" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "persistent error log" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_UINT8, TRUE, "SPA history" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_UINT64, TRUE, "SPA history offsets" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "Pool properties" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "DSL permissions" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ACL, TRUE, "ZFS ACL" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_UINT8, TRUE, "ZFS SYSACL" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_UINT8, TRUE, "FUID table" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_UINT64, TRUE, "FUID table size" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "DSL dataset next clones"},
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "scan work queue" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "ZFS user/group used" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "ZFS user/group quota" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "snapshot refcount tags"},
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "DDT ZAP algorithm" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "DDT statistics" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_UINT8, TRUE, "System attributes" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "SA master node" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "SA attr registration" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "SA attr layouts" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "scan translations" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_UINT8, FALSE, "deduplicated block" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "DSL deadlist map" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_UINT64, TRUE, "DSL deadlist map hdr" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_ZAP, TRUE, "DSL dir clones" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { DMU_BSWAP_UINT64, TRUE, "bpobj subobj" }
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden};
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Sidenconst dmu_object_byteswap_info_t dmu_ot_byteswap[DMU_BSWAP_NUMFUNCS] = {
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { byteswap_uint8_array, "uint8" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { byteswap_uint16_array, "uint16" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { byteswap_uint32_array, "uint32" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { byteswap_uint64_array, "uint64" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { zap_byteswap, "zap" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { dnode_buf_byteswap, "dnode" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { dmu_objset_byteswap, "objset" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { zfs_znode_byteswap, "znode" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { zfs_oldacl_byteswap, "oldacl" },
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden { zfs_acl_byteswap, "acl" }
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling};
fa9e4066f08beec538e775443c5be79dd423fcabahrens
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrensint
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrensdmu_buf_hold_noread_by_dnode(dnode_t *dn, uint64_t offset,
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens void *tag, dmu_buf_t **dbp)
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens{
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens uint64_t blkid;
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens dmu_buf_impl_t *db;
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens blkid = dbuf_whichblock(dn, 0, offset);
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens rw_enter(&dn->dn_struct_rwlock, RW_READER);
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens db = dbuf_hold(dn, blkid, tag);
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens rw_exit(&dn->dn_struct_rwlock);
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens if (db == NULL) {
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens *dbp = NULL;
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens return (SET_ERROR(EIO));
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens }
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens *dbp = &db->db;
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens return (0);
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrensint
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrensdmu_buf_hold_noread(objset_t *os, uint64_t object, uint64_t offset,
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens void *tag, dmu_buf_t **dbp)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnode_t *dn;
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t blkid;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmu_buf_impl_t *db;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock int err;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens err = dnode_hold(os, object, FTAG, &dn);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (err)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (err);
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie blkid = dbuf_whichblock(dn, 0, offset);
fa9e4066f08beec538e775443c5be79dd423fcabahrens rw_enter(&dn->dn_struct_rwlock, RW_READER);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock db = dbuf_hold(dn, blkid, tag);
fa9e4066f08beec538e775443c5be79dd423fcabahrens rw_exit(&dn->dn_struct_rwlock);
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens dnode_rele(dn, FTAG);
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (db == NULL) {
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens *dbp = NULL;
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens return (SET_ERROR(EIO));
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens }
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens *dbp = &db->db;
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens return (err);
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens}
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrensint
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrensdmu_buf_hold_by_dnode(dnode_t *dn, uint64_t offset,
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens void *tag, dmu_buf_t **dbp, int flags)
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens{
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens int err;
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens int db_flags = DB_RF_CANFAIL;
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens if (flags & DMU_READ_NO_PREFETCH)
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens db_flags |= DB_RF_NOPREFETCH;
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens err = dmu_buf_hold_noread_by_dnode(dn, offset, tag, dbp);
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens if (err == 0) {
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens dmu_buf_impl_t *db = (dmu_buf_impl_t *)(*dbp);
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens err = dbuf_read(db, NULL, db_flags);
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens if (err != 0) {
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens dbuf_rele(db, tag);
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens *dbp = NULL;
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens }
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens }
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens return (err);
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens}
79d728325e257b05859d2eef4a4dfbefdce05a76Matthew Ahrens
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrensint
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrensdmu_buf_hold(objset_t *os, uint64_t object, uint64_t offset,
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens void *tag, dmu_buf_t **dbp, int flags)
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens{
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens int err;
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens int db_flags = DB_RF_CANFAIL;
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens if (flags & DMU_READ_NO_PREFETCH)
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens db_flags |= DB_RF_NOPREFETCH;
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens err = dmu_buf_hold_noread(os, object, offset, tag, dbp);
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens if (err == 0) {
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens dmu_buf_impl_t *db = (dmu_buf_impl_t *)(*dbp);
47cb52daa729f19e298c85a84e8df069365c5232Jeff Bonwick err = dbuf_read(db, NULL, db_flags);
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens if (err != 0) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock dbuf_rele(db, tag);
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens *dbp = NULL;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (err);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensint
fa9e4066f08beec538e775443c5be79dd423fcabahrensdmu_bonus_max(void)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (DN_MAX_BONUSLEN);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
1934e92fc930c49429ad71a8ca97340f33227e78maybeeint
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Ericksondmu_set_bonus(dmu_buf_t *db_fake, int newsize, dmu_tx_t *tx)
1934e92fc930c49429ad71a8ca97340f33227e78maybee{
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dmu_buf_impl_t *db = (dmu_buf_impl_t *)db_fake;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dnode_t *dn;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson int error;
1934e92fc930c49429ad71a8ca97340f33227e78maybee
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_ENTER(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dn = DB_DNODE(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson if (dn->dn_bonus != db) {
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens error = SET_ERROR(EINVAL);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson } else if (newsize < 0 || newsize > db_fake->db_size) {
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens error = SET_ERROR(EINVAL);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson } else {
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dnode_setbonuslen(dn, newsize, tx);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson error = 0;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson }
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_EXIT(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson return (error);
1934e92fc930c49429ad71a8ca97340f33227e78maybee}
1934e92fc930c49429ad71a8ca97340f33227e78maybee
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaumint
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Ericksondmu_set_bonustype(dmu_buf_t *db_fake, dmu_object_type_t type, dmu_tx_t *tx)
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum{
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dmu_buf_impl_t *db = (dmu_buf_impl_t *)db_fake;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dnode_t *dn;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson int error;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_ENTER(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dn = DB_DNODE(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden if (!DMU_OT_IS_VALID(type)) {
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens error = SET_ERROR(EINVAL);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson } else if (dn->dn_bonus != db) {
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens error = SET_ERROR(EINVAL);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson } else {
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dnode_setbonus_type(dn, type, tx);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson error = 0;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson }
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_EXIT(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson return (error);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson}
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Ericksondmu_object_type_t
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Ericksondmu_get_bonustype(dmu_buf_t *db_fake)
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson{
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dmu_buf_impl_t *db = (dmu_buf_impl_t *)db_fake;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dnode_t *dn;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dmu_object_type_t type;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_ENTER(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dn = DB_DNODE(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson type = dn->dn_bonustype;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_EXIT(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson return (type);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum}
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaumint
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaumdmu_rm_spill(objset_t *os, uint64_t object, dmu_tx_t *tx)
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum{
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum dnode_t *dn;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum int error;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum error = dnode_hold(os, object, FTAG, &dn);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum dbuf_rm_spill(dn, tx);
06e0070d70ba2ee95f5aa2645423eb2cf1546788Mark Shellenbaum rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
06e0070d70ba2ee95f5aa2645423eb2cf1546788Mark Shellenbaum dnode_rm_spill(dn, tx);
06e0070d70ba2ee95f5aa2645423eb2cf1546788Mark Shellenbaum rw_exit(&dn->dn_struct_rwlock);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum dnode_rele(dn, FTAG);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum return (error);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum}
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * returns ENOENT, EIO, or 0.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockint
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockdmu_bonus_hold(objset_t *os, uint64_t object, void *tag, dmu_buf_t **dbp)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock dnode_t *dn;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmu_buf_impl_t *db;
1934e92fc930c49429ad71a8ca97340f33227e78maybee int error;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens error = dnode_hold(os, object, FTAG, &dn);
1934e92fc930c49429ad71a8ca97340f33227e78maybee if (error)
1934e92fc930c49429ad71a8ca97340f33227e78maybee return (error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock rw_enter(&dn->dn_struct_rwlock, RW_READER);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (dn->dn_bonus == NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens rw_exit(&dn->dn_struct_rwlock);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (dn->dn_bonus == NULL)
1934e92fc930c49429ad71a8ca97340f33227e78maybee dbuf_create_bonus(dn);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock db = dn->dn_bonus;
1934e92fc930c49429ad71a8ca97340f33227e78maybee
1934e92fc930c49429ad71a8ca97340f33227e78maybee /* as long as the bonus buf is held, the dnode will be held */
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson if (refcount_add(&db->db_holds, tag) == 1) {
1934e92fc930c49429ad71a8ca97340f33227e78maybee VERIFY(dnode_add_ref(dn, db));
640c1670a105457bb0040e8e11037b53ab6ebcfaJosef 'Jeff' Sipek atomic_inc_32(&dn->dn_dbufs_count);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson }
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson /*
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson * Wait to drop dn_struct_rwlock until after adding the bonus dbuf's
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson * hold and incrementing the dbuf count to ensure that dnode_move() sees
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson * a dnode hold for every dbuf.
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson */
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson rw_exit(&dn->dn_struct_rwlock);
1934e92fc930c49429ad71a8ca97340f33227e78maybee
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnode_rele(dn, FTAG);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
47cb52daa729f19e298c85a84e8df069365c5232Jeff Bonwick VERIFY(0 == dbuf_read(db, NULL, DB_RF_MUST_SUCCEED | DB_RF_NOPREFETCH));
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock *dbp = &db->db;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum/*
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum * returns ENOENT, EIO, or 0.
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum *
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum * This interface will allocate a blank spill dbuf when a spill blk
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum * doesn't already exist on the dnode.
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum *
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum * if you only want to find an already existing spill db, then
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum * dmu_spill_hold_existing() should be used.
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum */
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaumint
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaumdmu_spill_hold_by_dnode(dnode_t *dn, uint32_t flags, void *tag, dmu_buf_t **dbp)
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum{
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum dmu_buf_impl_t *db = NULL;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum int err;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum if ((flags & DB_RF_HAVESTRUCT) == 0)
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum rw_enter(&dn->dn_struct_rwlock, RW_READER);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum db = dbuf_hold(dn, DMU_SPILL_BLKID, tag);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum if ((flags & DB_RF_HAVESTRUCT) == 0)
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum rw_exit(&dn->dn_struct_rwlock);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum ASSERT(db != NULL);
1d8ccc7bfd8ab0f27a23c5253d95c22ceb9c27f4Mark Shellenbaum err = dbuf_read(db, NULL, flags);
1d8ccc7bfd8ab0f27a23c5253d95c22ceb9c27f4Mark Shellenbaum if (err == 0)
1d8ccc7bfd8ab0f27a23c5253d95c22ceb9c27f4Mark Shellenbaum *dbp = &db->db;
1d8ccc7bfd8ab0f27a23c5253d95c22ceb9c27f4Mark Shellenbaum else
1d8ccc7bfd8ab0f27a23c5253d95c22ceb9c27f4Mark Shellenbaum dbuf_rele(db, tag);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum return (err);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum}
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaumint
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaumdmu_spill_hold_existing(dmu_buf_t *bonus, void *tag, dmu_buf_t **dbp)
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum{
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dmu_buf_impl_t *db = (dmu_buf_impl_t *)bonus;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dnode_t *dn;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum int err;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_ENTER(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dn = DB_DNODE(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson if (spa_version(dn->dn_objset->os_spa) < SPA_VERSION_SA) {
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens err = SET_ERROR(EINVAL);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson } else {
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson rw_enter(&dn->dn_struct_rwlock, RW_READER);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson if (!dn->dn_have_spill) {
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens err = SET_ERROR(ENOENT);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson } else {
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson err = dmu_spill_hold_by_dnode(dn,
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_RF_HAVESTRUCT | DB_RF_CANFAIL, tag, dbp);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson }
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum rw_exit(&dn->dn_struct_rwlock);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum }
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_EXIT(db);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum return (err);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum}
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaumint
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaumdmu_spill_hold_by_bonus(dmu_buf_t *bonus, void *tag, dmu_buf_t **dbp)
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum{
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dmu_buf_impl_t *db = (dmu_buf_impl_t *)bonus;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dnode_t *dn;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson int err;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_ENTER(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dn = DB_DNODE(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson err = dmu_spill_hold_by_dnode(dn, DB_RF_CANFAIL, tag, dbp);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_EXIT(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson return (err);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum}
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee/*
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee * Note: longer-term, we should modify all of the dmu_buf_*() interfaces
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee * to take a held dnode rather than <os, object> -- the lookup is wasteful,
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee * and can induce severe lock contention when writing to several files
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee * whose dnodes are in the same block.
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee */
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybeestatic int
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrindmu_buf_hold_array_by_dnode(dnode_t *dn, uint64_t offset, uint64_t length,
cf6106c8a0d6598b045811f9650d66e07eb332afMatthew Ahrens boolean_t read, void *tag, int *numbufsp, dmu_buf_t ***dbpp, uint32_t flags)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmu_buf_t **dbp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t blkid, nblks, i;
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrin uint32_t dbuf_flags;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock int err;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock zio_t *zio;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock ASSERT(length <= DMU_MAX_ACCESS);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
cf6106c8a0d6598b045811f9650d66e07eb332afMatthew Ahrens /*
cf6106c8a0d6598b045811f9650d66e07eb332afMatthew Ahrens * Note: We directly notify the prefetch code of this read, so that
cf6106c8a0d6598b045811f9650d66e07eb332afMatthew Ahrens * we can tell it about the multi-block read. dbuf_read() only knows
cf6106c8a0d6598b045811f9650d66e07eb332afMatthew Ahrens * about the one block it is accessing.
cf6106c8a0d6598b045811f9650d66e07eb332afMatthew Ahrens */
cf6106c8a0d6598b045811f9650d66e07eb332afMatthew Ahrens dbuf_flags = DB_RF_CANFAIL | DB_RF_NEVERWAIT | DB_RF_HAVESTRUCT |
cf6106c8a0d6598b045811f9650d66e07eb332afMatthew Ahrens DB_RF_NOPREFETCH;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
fa9e4066f08beec538e775443c5be79dd423fcabahrens rw_enter(&dn->dn_struct_rwlock, RW_READER);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (dn->dn_datablkshift) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens int blkshift = dn->dn_datablkshift;
cf6106c8a0d6598b045811f9650d66e07eb332afMatthew Ahrens nblks = (P2ROUNDUP(offset + length, 1ULL << blkshift) -
cf6106c8a0d6598b045811f9650d66e07eb332afMatthew Ahrens P2ALIGN(offset, 1ULL << blkshift)) >> blkshift;
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
0125049cd6136d1d2ca9e982382a915b6d7916ceahrens if (offset + length > dn->dn_datablksz) {
0125049cd6136d1d2ca9e982382a915b6d7916ceahrens zfs_panic_recover("zfs: accessing past end of object "
0125049cd6136d1d2ca9e982382a915b6d7916ceahrens "%llx/%llx (size=%u access=%llu+%llu)",
0125049cd6136d1d2ca9e982382a915b6d7916ceahrens (longlong_t)dn->dn_objset->
0125049cd6136d1d2ca9e982382a915b6d7916ceahrens os_dsl_dataset->ds_object,
0125049cd6136d1d2ca9e982382a915b6d7916ceahrens (longlong_t)dn->dn_object, dn->dn_datablksz,
0125049cd6136d1d2ca9e982382a915b6d7916ceahrens (longlong_t)offset, (longlong_t)length);
c87b8fc5c906791122d9de2dab7eeb51f2e91049Mark J Musante rw_exit(&dn->dn_struct_rwlock);
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EIO));
0125049cd6136d1d2ca9e982382a915b6d7916ceahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens nblks = 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock dbp = kmem_zalloc(sizeof (dmu_buf_t *) * nblks, KM_SLEEP);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick zio = zio_root(dn->dn_objset->os_spa, NULL, NULL, ZIO_FLAG_CANFAIL);
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie blkid = dbuf_whichblock(dn, 0, offset);
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; i < nblks; i++) {
cf6106c8a0d6598b045811f9650d66e07eb332afMatthew Ahrens dmu_buf_impl_t *db = dbuf_hold(dn, blkid + i, tag);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (db == NULL) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock rw_exit(&dn->dn_struct_rwlock);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock dmu_buf_rele_array(dbp, nblks, tag);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock zio_nowait(zio);
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EIO));
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
cf6106c8a0d6598b045811f9650d66e07eb332afMatthew Ahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /* initiate async i/o */
cf6106c8a0d6598b045811f9650d66e07eb332afMatthew Ahrens if (read)
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrin (void) dbuf_read(db, zio, dbuf_flags);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock dbp[i] = &db->db;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
cf6106c8a0d6598b045811f9650d66e07eb332afMatthew Ahrens
cb92f4130ce5b2c4ae1fa5fa6c776f4d4dc28ad9Alexander Motin if ((flags & DMU_READ_NO_PREFETCH) == 0 &&
cb92f4130ce5b2c4ae1fa5fa6c776f4d4dc28ad9Alexander Motin DNODE_META_IS_CACHEABLE(dn) && length <= zfetch_array_rd_sz) {
cb92f4130ce5b2c4ae1fa5fa6c776f4d4dc28ad9Alexander Motin dmu_zfetch(&dn->dn_zfetch, blkid, nblks,
cb92f4130ce5b2c4ae1fa5fa6c776f4d4dc28ad9Alexander Motin read && DNODE_IS_CACHEABLE(dn));
cf6106c8a0d6598b045811f9650d66e07eb332afMatthew Ahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens rw_exit(&dn->dn_struct_rwlock);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /* wait for async i/o */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock err = zio_wait(zio);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (err) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock dmu_buf_rele_array(dbp, nblks, tag);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (err);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /* wait for other io to complete */
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (read) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock for (i = 0; i < nblks; i++) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock dmu_buf_impl_t *db = (dmu_buf_impl_t *)dbp[i];
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock mutex_enter(&db->db_mtx);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock while (db->db_state == DB_READ ||
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock db->db_state == DB_FILL)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock cv_wait(&db->db_changed, &db->db_mtx);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (db->db_state == DB_UNCACHED)
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens err = SET_ERROR(EIO);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock mutex_exit(&db->db_mtx);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (err) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock dmu_buf_rele_array(dbp, nblks, tag);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (err);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock *numbufsp = nblks;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock *dbpp = dbp;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
a2eea2e101e6a163a537dcc6d4e3c4da2a0ea5b2ahrensstatic int
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybeedmu_buf_hold_array(objset_t *os, uint64_t object, uint64_t offset,
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee uint64_t length, int read, void *tag, int *numbufsp, dmu_buf_t ***dbpp)
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee{
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee dnode_t *dn;
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee int err;
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens err = dnode_hold(os, object, FTAG, &dn);
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee if (err)
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee return (err);
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee err = dmu_buf_hold_array_by_dnode(dn, offset, length, read, tag,
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrin numbufsp, dbpp, DMU_READ_PREFETCH);
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee dnode_rele(dn, FTAG);
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee return (err);
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee}
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybeeint
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Ericksondmu_buf_hold_array_by_bonus(dmu_buf_t *db_fake, uint64_t offset,
cf6106c8a0d6598b045811f9650d66e07eb332afMatthew Ahrens uint64_t length, boolean_t read, void *tag, int *numbufsp,
cf6106c8a0d6598b045811f9650d66e07eb332afMatthew Ahrens dmu_buf_t ***dbpp)
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee{
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dmu_buf_impl_t *db = (dmu_buf_impl_t *)db_fake;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dnode_t *dn;
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee int err;
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_ENTER(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dn = DB_DNODE(db);
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee err = dmu_buf_hold_array_by_dnode(dn, offset, length, read, tag,
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrin numbufsp, dbpp, DMU_READ_PREFETCH);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_EXIT(db);
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee return (err);
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee}
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockdmu_buf_rele_array(dmu_buf_t **dbp_fake, int numbufs, void *tag)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens int i;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmu_buf_impl_t **dbp = (dmu_buf_impl_t **)dbp_fake;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (numbufs == 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock for (i = 0; i < numbufs; i++) {
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (dbp[i])
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock dbuf_rele(dbp[i], tag);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens kmem_free(dbp, sizeof (dmu_buf_t *) * numbufs);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
69962b5647e4a8b9b14998733b765925381b727eMatthew Ahrens/*
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie * Issue prefetch i/os for the given blocks. If level is greater than 0, the
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie * indirect blocks prefeteched will be those that point to the blocks containing
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie * the data starting at offset, and continuing to offset + len.
69962b5647e4a8b9b14998733b765925381b727eMatthew Ahrens *
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie * Note that if the indirect blocks above the blocks being prefetched are not in
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie * cache, they will be asychronously read in.
69962b5647e4a8b9b14998733b765925381b727eMatthew Ahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagneliedmu_prefetch(objset_t *os, uint64_t object, int64_t level, uint64_t offset,
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie uint64_t len, zio_priority_t pri)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnode_t *dn;
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t blkid;
69962b5647e4a8b9b14998733b765925381b727eMatthew Ahrens int nblks, err;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (len == 0) { /* they're interested in the bonus buffer */
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dn = DMU_META_DNODE(os);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (object == 0 || object >= DN_MAX_OBJECT)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens rw_enter(&dn->dn_struct_rwlock, RW_READER);
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie blkid = dbuf_whichblock(dn, level,
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie object * sizeof (dnode_phys_t));
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie dbuf_prefetch(dn, level, blkid, pri, 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens rw_exit(&dn->dn_struct_rwlock);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * XXX - Note, if the dnode for the requested object is not
fa9e4066f08beec538e775443c5be79dd423fcabahrens * already cached, we will do a *synchronous* read in the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * dnode_hold() call. The same is true for any indirects.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens err = dnode_hold(os, object, FTAG, &dn);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (err != 0)
fa9e4066f08beec538e775443c5be79dd423fcabahrens return;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens rw_enter(&dn->dn_struct_rwlock, RW_READER);
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie /*
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie * offset + len - 1 is the last byte we want to prefetch for, and offset
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie * is the first. Then dbuf_whichblk(dn, level, off + len - 1) is the
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie * last block we want to prefetch, and dbuf_whichblock(dn, level,
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie * offset) is the first. Then the number we need to prefetch is the
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie * last - first + 1.
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie */
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie if (level > 0 || dn->dn_datablkshift != 0) {
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie nblks = dbuf_whichblock(dn, level, offset + len - 1) -
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie dbuf_whichblock(dn, level, offset) + 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens nblks = (offset < dn->dn_datablksz);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (nblks != 0) {
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie blkid = dbuf_whichblock(dn, level, offset);
69962b5647e4a8b9b14998733b765925381b727eMatthew Ahrens for (int i = 0; i < nblks; i++)
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie dbuf_prefetch(dn, level, blkid + i, pri, 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens rw_exit(&dn->dn_struct_rwlock);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnode_rele(dn, FTAG);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
762562058c49df3abfc6555f5b8174f3900e5c78Mark Maybee/*
762562058c49df3abfc6555f5b8174f3900e5c78Mark Maybee * Get the next "chunk" of file data to free. We traverse the file from
762562058c49df3abfc6555f5b8174f3900e5c78Mark Maybee * the end so that the file gets shorter over time (if we crashes in the
762562058c49df3abfc6555f5b8174f3900e5c78Mark Maybee * middle, this will leave us in a better state). We find allocated file
762562058c49df3abfc6555f5b8174f3900e5c78Mark Maybee * data by simply searching the allocated level 1 indirects.
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens *
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens * On input, *start should be the first offset that does not need to be
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens * freed (e.g. "offset + length"). On return, *start will be the first
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens * offset that should be freed.
762562058c49df3abfc6555f5b8174f3900e5c78Mark Maybee */
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybeestatic int
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrensget_next_chunk(dnode_t *dn, uint64_t *start, uint64_t minimum)
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee{
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens uint64_t maxblks = DMU_MAX_ACCESS >> (dn->dn_indblkshift + 1);
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens /* bytes of data covered by a level-1 indirect block */
762562058c49df3abfc6555f5b8174f3900e5c78Mark Maybee uint64_t iblkrange =
1c8564a7573482b45fcc6f9bc0c2de70f92c193cMark Maybee dn->dn_datablksz * EPB(dn->dn_indblkshift, SPA_BLKPTRSHIFT);
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens ASSERT3U(minimum, <=, *start);
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens if (*start - minimum <= iblkrange * maxblks) {
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens *start = minimum;
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee return (0);
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee }
762562058c49df3abfc6555f5b8174f3900e5c78Mark Maybee ASSERT(ISP2(iblkrange));
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens for (uint64_t blks = 0; *start > minimum && blks < maxblks; blks++) {
1c8564a7573482b45fcc6f9bc0c2de70f92c193cMark Maybee int err;
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens /*
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens * dnode_next_offset(BACKWARDS) will find an allocated L1
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens * indirect block at or before the input offset. We must
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens * decrement *start so that it is at the end of the region
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens * to search.
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens */
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens (*start)--;
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee err = dnode_next_offset(dn,
762562058c49df3abfc6555f5b8174f3900e5c78Mark Maybee DNODE_FIND_BACKWARDS, start, 2, 1, 0);
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens /* if there are no indirect blocks before start, we are done */
762562058c49df3abfc6555f5b8174f3900e5c78Mark Maybee if (err == ESRCH) {
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens *start = minimum;
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens break;
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens } else if (err != 0) {
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee return (err);
762562058c49df3abfc6555f5b8174f3900e5c78Mark Maybee }
762562058c49df3abfc6555f5b8174f3900e5c78Mark Maybee
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens /* set start to the beginning of this L1 indirect */
762562058c49df3abfc6555f5b8174f3900e5c78Mark Maybee *start = P2ALIGN(*start, iblkrange);
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee }
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens if (*start < minimum)
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens *start = minimum;
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee return (0);
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee}
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk/*
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk * If this objset is of type OST_ZFS return true if vfs's unmounted flag is set,
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk * otherwise return false.
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk * Used below in dmu_free_long_range_impl() to enable abort when unmounting
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk */
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk/*ARGSUSED*/
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchukstatic boolean_t
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchukdmu_objset_zfs_unmounting(objset_t *os)
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk{
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk#ifdef _KERNEL
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk if (dmu_objset_type(os) == DMU_OST_ZFS)
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk return (zfs_get_vfs_flag_unmounted(os));
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk#endif
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk return (B_FALSE);
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk}
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybeestatic int
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybeedmu_free_long_range_impl(objset_t *os, dnode_t *dn, uint64_t offset,
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens uint64_t length)
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee{
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens uint64_t object_size = (dn->dn_maxblkid + 1) * dn->dn_datablksz;
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens int err;
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens if (offset >= object_size)
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee return (0);
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens if (length == DMU_OBJECT_END || offset + length > object_size)
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens length = object_size - offset;
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens while (length != 0) {
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens uint64_t chunk_end, chunk_begin;
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk if (dmu_objset_zfs_unmounting(dn->dn_objset))
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk return (SET_ERROR(EINTR));
eb721827677c553ce8dd0d4390630a857f923f98Alek Pinchuk
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens chunk_end = chunk_begin = offset + length;
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens /* move chunk_begin backwards to the beginning of this chunk */
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens err = get_next_chunk(dn, &chunk_begin, offset);
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee if (err)
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee return (err);
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens ASSERT3U(chunk_begin, >=, offset);
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens ASSERT3U(chunk_begin, <=, chunk_end);
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens dmu_tx_t *tx = dmu_tx_create(os);
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens dmu_tx_hold_free(tx, dn->dn_object,
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens chunk_begin, chunk_end - chunk_begin);
4bb73804952172060c9efb163b89c17f56804fe8Matthew Ahrens
4bb73804952172060c9efb163b89c17f56804fe8Matthew Ahrens /*
4bb73804952172060c9efb163b89c17f56804fe8Matthew Ahrens * Mark this transaction as typically resulting in a net
4bb73804952172060c9efb163b89c17f56804fe8Matthew Ahrens * reduction in space used.
4bb73804952172060c9efb163b89c17f56804fe8Matthew Ahrens */
4bb73804952172060c9efb163b89c17f56804fe8Matthew Ahrens dmu_tx_mark_netfree(tx);
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee err = dmu_tx_assign(tx, TXG_WAIT);
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee if (err) {
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee dmu_tx_abort(tx);
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee return (err);
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee }
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens dnode_free_range(dn, chunk_begin, chunk_end - chunk_begin, tx);
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee dmu_tx_commit(tx);
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens length -= chunk_end - chunk_begin;
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee }
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee return (0);
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee}
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybeeint
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybeedmu_free_long_range(objset_t *os, uint64_t object,
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee uint64_t offset, uint64_t length)
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee{
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee dnode_t *dn;
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee int err;
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens err = dnode_hold(os, object, FTAG, &dn);
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee if (err != 0)
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee return (err);
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens err = dmu_free_long_range_impl(os, dn, offset, length);
5253393b09789ec67bec153b866d7285a1cf1645Matthew Ahrens
5253393b09789ec67bec153b866d7285a1cf1645Matthew Ahrens /*
5253393b09789ec67bec153b866d7285a1cf1645Matthew Ahrens * It is important to zero out the maxblkid when freeing the entire
5253393b09789ec67bec153b866d7285a1cf1645Matthew Ahrens * file, so that (a) subsequent calls to dmu_free_long_range_impl()
5253393b09789ec67bec153b866d7285a1cf1645Matthew Ahrens * will take the fast path, and (b) dnode_reallocate() can verify
5253393b09789ec67bec153b866d7285a1cf1645Matthew Ahrens * that the entire file has been freed.
5253393b09789ec67bec153b866d7285a1cf1645Matthew Ahrens */
43466aae47bfcd2ad9bf501faec8e75c08095e4fMax Grossman if (err == 0 && offset == 0 && length == DMU_OBJECT_END)
5253393b09789ec67bec153b866d7285a1cf1645Matthew Ahrens dn->dn_maxblkid = 0;
5253393b09789ec67bec153b866d7285a1cf1645Matthew Ahrens
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee dnode_rele(dn, FTAG);
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee return (err);
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee}
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybeeint
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrensdmu_free_long_object(objset_t *os, uint64_t object)
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee{
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee dmu_tx_t *tx;
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee int err;
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens err = dmu_free_long_range(os, object, 0, DMU_OBJECT_END);
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee if (err != 0)
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee return (err);
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens tx = dmu_tx_create(os);
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens dmu_tx_hold_bonus(tx, object);
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens dmu_tx_hold_free(tx, object, 0, DMU_OBJECT_END);
4bb73804952172060c9efb163b89c17f56804fe8Matthew Ahrens dmu_tx_mark_netfree(tx);
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens err = dmu_tx_assign(tx, TXG_WAIT);
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens if (err == 0) {
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens err = dmu_object_free(os, object, tx);
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens dmu_tx_commit(tx);
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee } else {
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens dmu_tx_abort(tx);
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee }
713d6c208802cfbb806329ec0d154b641b80c355Matthew Ahrens
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee return (err);
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee}
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockint
fa9e4066f08beec538e775443c5be79dd423fcabahrensdmu_free_range(objset_t *os, uint64_t object, uint64_t offset,
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t size, dmu_tx_t *tx)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock dnode_t *dn;
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens int err = dnode_hold(os, object, FTAG, &dn);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (err)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (err);
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(offset < UINT64_MAX);
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(size == -1ULL || size <= UINT64_MAX - offset);
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnode_free_range(dn, offset, size, tx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnode_rele(dn, FTAG);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockint
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrockdmu_read(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrin void *buf, uint32_t flags)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnode_t *dn;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmu_buf_t **dbp;
c87b8fc5c906791122d9de2dab7eeb51f2e91049Mark J Musante int numbufs, err;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens err = dnode_hold(os, object, FTAG, &dn);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (err)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (err);
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm /*
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm * Deal with odd block sizes, where there can't be data past the first
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm * block. If we ever do the tail block optimization, we will need to
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm * handle that here as well.
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm */
c87b8fc5c906791122d9de2dab7eeb51f2e91049Mark J Musante if (dn->dn_maxblkid == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens int newsz = offset > dn->dn_datablksz ? 0 :
fa9e4066f08beec538e775443c5be79dd423fcabahrens MIN(size, dn->dn_datablksz - offset);
fa9e4066f08beec538e775443c5be79dd423fcabahrens bzero((char *)buf + newsz, size - newsz);
fa9e4066f08beec538e775443c5be79dd423fcabahrens size = newsz;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens while (size > 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t mylen = MIN(size, DMU_MAX_ACCESS / 2);
c87b8fc5c906791122d9de2dab7eeb51f2e91049Mark J Musante int i;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * NB: we could do this block-at-a-time, but it's nice
fa9e4066f08beec538e775443c5be79dd423fcabahrens * to be reading in parallel.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
a2eea2e101e6a163a537dcc6d4e3c4da2a0ea5b2ahrens err = dmu_buf_hold_array_by_dnode(dn, offset, mylen,
7bfdf011e081684f853a3242d0296695110d9d84Neil Perrin TRUE, FTAG, &numbufs, &dbp, flags);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (err)
1934e92fc930c49429ad71a8ca97340f33227e78maybee break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; i < numbufs; i++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens int tocpy;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int bufoff;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmu_buf_t *db = dbp[i];
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(size > 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens bufoff = offset - db->db_offset;
fa9e4066f08beec538e775443c5be79dd423fcabahrens tocpy = (int)MIN(db->db_size - bufoff, size);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens bcopy((char *)db->db_data + bufoff, buf, tocpy);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens offset += tocpy;
fa9e4066f08beec538e775443c5be79dd423fcabahrens size -= tocpy;
fa9e4066f08beec538e775443c5be79dd423fcabahrens buf = (char *)buf + tocpy;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock dmu_buf_rele_array(dbp, numbufs, FTAG);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
a2eea2e101e6a163a537dcc6d4e3c4da2a0ea5b2ahrens dnode_rele(dn, FTAG);
1934e92fc930c49429ad71a8ca97340f33227e78maybee return (err);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid
fa9e4066f08beec538e775443c5be79dd423fcabahrensdmu_write(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
fa9e4066f08beec538e775443c5be79dd423fcabahrens const void *buf, dmu_tx_t *tx)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmu_buf_t **dbp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int numbufs, i;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee if (size == 0)
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee return;
13506d1eefbbc37e2f12a0528831d9f6d4c361d7maybee
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock VERIFY(0 == dmu_buf_hold_array(os, object, offset, size,
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock FALSE, FTAG, &numbufs, &dbp));
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; i < numbufs; i++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens int tocpy;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int bufoff;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmu_buf_t *db = dbp[i];
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(size > 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens bufoff = offset - db->db_offset;
fa9e4066f08beec538e775443c5be79dd423fcabahrens tocpy = (int)MIN(db->db_size - bufoff, size);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(i == 0 || i == numbufs-1 || tocpy == db->db_size);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (tocpy == db->db_size)
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmu_buf_will_fill(db, tx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens else
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmu_buf_will_dirty(db, tx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens bcopy(buf, (char *)db->db_data + bufoff, tocpy);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (tocpy == db->db_size)
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmu_buf_fill_done(db, tx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens offset += tocpy;
fa9e4066f08beec538e775443c5be79dd423fcabahrens size -= tocpy;
fa9e4066f08beec538e775443c5be79dd423fcabahrens buf = (char *)buf + tocpy;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock dmu_buf_rele_array(dbp, numbufs, FTAG);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
82c9918f28a2d8d9e93769e16f7fa7bee347e80fTim Haleyvoid
82c9918f28a2d8d9e93769e16f7fa7bee347e80fTim Haleydmu_prealloc(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
82c9918f28a2d8d9e93769e16f7fa7bee347e80fTim Haley dmu_tx_t *tx)
82c9918f28a2d8d9e93769e16f7fa7bee347e80fTim Haley{
82c9918f28a2d8d9e93769e16f7fa7bee347e80fTim Haley dmu_buf_t **dbp;
82c9918f28a2d8d9e93769e16f7fa7bee347e80fTim Haley int numbufs, i;
82c9918f28a2d8d9e93769e16f7fa7bee347e80fTim Haley
82c9918f28a2d8d9e93769e16f7fa7bee347e80fTim Haley if (size == 0)
82c9918f28a2d8d9e93769e16f7fa7bee347e80fTim Haley return;
82c9918f28a2d8d9e93769e16f7fa7bee347e80fTim Haley
82c9918f28a2d8d9e93769e16f7fa7bee347e80fTim Haley VERIFY(0 == dmu_buf_hold_array(os, object, offset, size,
82c9918f28a2d8d9e93769e16f7fa7bee347e80fTim Haley FALSE, FTAG, &numbufs, &dbp));
82c9918f28a2d8d9e93769e16f7fa7bee347e80fTim Haley
82c9918f28a2d8d9e93769e16f7fa7bee347e80fTim Haley for (i = 0; i < numbufs; i++) {
82c9918f28a2d8d9e93769e16f7fa7bee347e80fTim Haley dmu_buf_t *db = dbp[i];
82c9918f28a2d8d9e93769e16f7fa7bee347e80fTim Haley
82c9918f28a2d8d9e93769e16f7fa7bee347e80fTim Haley dmu_buf_will_not_fill(db, tx);
82c9918f28a2d8d9e93769e16f7fa7bee347e80fTim Haley }
82c9918f28a2d8d9e93769e16f7fa7bee347e80fTim Haley dmu_buf_rele_array(dbp, numbufs, FTAG);
82c9918f28a2d8d9e93769e16f7fa7bee347e80fTim Haley}
82c9918f28a2d8d9e93769e16f7fa7bee347e80fTim Haley
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrensvoid
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrensdmu_write_embedded(objset_t *os, uint64_t object, uint64_t offset,
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens void *data, uint8_t etype, uint8_t comp, int uncompressed_size,
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens int compressed_size, int byteorder, dmu_tx_t *tx)
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens{
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens dmu_buf_t *db;
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens ASSERT3U(etype, <, NUM_BP_EMBEDDED_TYPES);
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens ASSERT3U(comp, <, ZIO_COMPRESS_FUNCTIONS);
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens VERIFY0(dmu_buf_hold_noread(os, object, offset,
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens FTAG, &db));
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens dmu_buf_write_embedded(db,
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens data, (bp_embedded_type_t)etype, (enum zio_compress)comp,
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens uncompressed_size, compressed_size, byteorder, tx);
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens dmu_buf_rele(db, FTAG);
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens}
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States/*
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States * DMU support for xuio
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States */
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United Stateskstat_t *xuio_ksp = NULL;
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United Statesint
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United Statesdmu_xuio_init(xuio_t *xuio, int nblk)
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States{
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States dmu_xuio_t *priv;
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States uio_t *uio = &xuio->xu_uio;
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States uio->uio_iovcnt = nblk;
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States uio->uio_iov = kmem_zalloc(nblk * sizeof (iovec_t), KM_SLEEP);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States priv = kmem_zalloc(sizeof (dmu_xuio_t), KM_SLEEP);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States priv->cnt = nblk;
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States priv->bufs = kmem_zalloc(nblk * sizeof (arc_buf_t *), KM_SLEEP);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States priv->iovp = uio->uio_iov;
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States XUIO_XUZC_PRIV(xuio) = priv;
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States if (XUIO_XUZC_RW(xuio) == UIO_READ)
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States XUIOSTAT_INCR(xuiostat_onloan_rbuf, nblk);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States else
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States XUIOSTAT_INCR(xuiostat_onloan_wbuf, nblk);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States return (0);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States}
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United Statesvoid
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United Statesdmu_xuio_fini(xuio_t *xuio)
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States{
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States dmu_xuio_t *priv = XUIO_XUZC_PRIV(xuio);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States int nblk = priv->cnt;
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States kmem_free(priv->iovp, nblk * sizeof (iovec_t));
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States kmem_free(priv->bufs, nblk * sizeof (arc_buf_t *));
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States kmem_free(priv, sizeof (dmu_xuio_t));
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States if (XUIO_XUZC_RW(xuio) == UIO_READ)
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States XUIOSTAT_INCR(xuiostat_onloan_rbuf, -nblk);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States else
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States XUIOSTAT_INCR(xuiostat_onloan_wbuf, -nblk);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States}
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States/*
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States * Initialize iov[priv->next] and priv->bufs[priv->next] with { off, n, abuf }
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States * and increase priv->next by 1.
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States */
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United Statesint
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United Statesdmu_xuio_add(xuio_t *xuio, arc_buf_t *abuf, offset_t off, size_t n)
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States{
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States struct iovec *iov;
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States uio_t *uio = &xuio->xu_uio;
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States dmu_xuio_t *priv = XUIO_XUZC_PRIV(xuio);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States int i = priv->next++;
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States ASSERT(i < priv->cnt);
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel ASSERT(off + n <= arc_buf_lsize(abuf));
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States iov = uio->uio_iov + i;
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States iov->iov_base = (char *)abuf->b_data + off;
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States iov->iov_len = n;
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States priv->bufs[i] = abuf;
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States return (0);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States}
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United Statesint
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United Statesdmu_xuio_cnt(xuio_t *xuio)
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States{
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States dmu_xuio_t *priv = XUIO_XUZC_PRIV(xuio);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States return (priv->cnt);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States}
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United Statesarc_buf_t *
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United Statesdmu_xuio_arcbuf(xuio_t *xuio, int i)
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States{
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States dmu_xuio_t *priv = XUIO_XUZC_PRIV(xuio);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States ASSERT(i < priv->cnt);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States return (priv->bufs[i]);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States}
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United Statesvoid
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United Statesdmu_xuio_clear(xuio_t *xuio, int i)
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States{
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States dmu_xuio_t *priv = XUIO_XUZC_PRIV(xuio);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States ASSERT(i < priv->cnt);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States priv->bufs[i] = NULL;
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States}
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United Statesstatic void
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United Statesxuio_stat_init(void)
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States{
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States xuio_ksp = kstat_create("zfs", 0, "xuio_stats", "misc",
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States KSTAT_TYPE_NAMED, sizeof (xuio_stats) / sizeof (kstat_named_t),
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States KSTAT_FLAG_VIRTUAL);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States if (xuio_ksp != NULL) {
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States xuio_ksp->ks_data = &xuio_stats;
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States kstat_install(xuio_ksp);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States }
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States}
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United Statesstatic void
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United Statesxuio_stat_fini(void)
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States{
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States if (xuio_ksp != NULL) {
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States kstat_delete(xuio_ksp);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States xuio_ksp = NULL;
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States }
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States}
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United Statesvoid
99aa8b55058e512798eafbd71f72f916bdc10181Prashanth Sreenivasaxuio_stat_wbuf_copied(void)
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States{
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States XUIOSTAT_BUMP(xuiostat_wbuf_copied);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States}
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United Statesvoid
99aa8b55058e512798eafbd71f72f916bdc10181Prashanth Sreenivasaxuio_stat_wbuf_nocopy(void)
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States{
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States XUIOSTAT_BUMP(xuiostat_wbuf_nocopy);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States}
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef _KERNEL
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrensstatic int
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrensdmu_read_uio_dnode(dnode_t *dn, uio_t *uio, uint64_t size)
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm{
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm dmu_buf_t **dbp;
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm int numbufs, i, err;
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States xuio_t *xuio = NULL;
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm /*
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm * NB: we could do this block-at-a-time, but it's nice
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm * to be reading in parallel.
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm */
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens err = dmu_buf_hold_array_by_dnode(dn, uio->uio_loffset, size,
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens TRUE, FTAG, &numbufs, &dbp, 0);
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm if (err)
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm return (err);
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States if (uio->uio_extflg == UIO_XUIO)
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States xuio = (xuio_t *)uio;
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm for (i = 0; i < numbufs; i++) {
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm int tocpy;
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm int bufoff;
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm dmu_buf_t *db = dbp[i];
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm ASSERT(size > 0);
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm bufoff = uio->uio_loffset - db->db_offset;
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm tocpy = (int)MIN(db->db_size - bufoff, size);
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States if (xuio) {
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States dmu_buf_impl_t *dbi = (dmu_buf_impl_t *)db;
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States arc_buf_t *dbuf_abuf = dbi->db_buf;
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States arc_buf_t *abuf = dbuf_loan_arcbuf(dbi);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States err = dmu_xuio_add(xuio, abuf, bufoff, tocpy);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States if (!err) {
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States uio->uio_resid -= tocpy;
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States uio->uio_loffset += tocpy;
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States }
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States if (abuf == dbuf_abuf)
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States XUIOSTAT_BUMP(xuiostat_rbuf_nocopy);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States else
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States XUIOSTAT_BUMP(xuiostat_rbuf_copied);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States } else {
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States err = uiomove((char *)db->db_data + bufoff, tocpy,
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States UIO_READ, uio);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States }
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm if (err)
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm break;
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm size -= tocpy;
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm }
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm dmu_buf_rele_array(dbp, numbufs, FTAG);
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm return (err);
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm}
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens/*
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens * Read 'size' bytes into the uio buffer.
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens * From object zdb->db_object.
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens * Starting at offset uio->uio_loffset.
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens *
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens * If the caller already has a dbuf in the target object
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens * (e.g. its bonus buffer), this routine is faster than dmu_read_uio(),
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens * because we don't have to find the dnode_t for the object.
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens */
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrensint
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrensdmu_read_uio_dbuf(dmu_buf_t *zdb, uio_t *uio, uint64_t size)
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens{
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens dmu_buf_impl_t *db = (dmu_buf_impl_t *)zdb;
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens dnode_t *dn;
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens int err;
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens if (size == 0)
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens return (0);
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens DB_DNODE_ENTER(db);
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens dn = DB_DNODE(db);
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens err = dmu_read_uio_dnode(dn, uio, size);
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens DB_DNODE_EXIT(db);
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens return (err);
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens}
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens/*
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens * Read 'size' bytes into the uio buffer.
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens * From the specified object
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens * Starting at offset uio->uio_loffset.
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens */
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrensint
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrensdmu_read_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size)
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens{
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens dnode_t *dn;
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens int err;
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens if (size == 0)
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens return (0);
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens err = dnode_hold(os, object, FTAG, &dn);
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens if (err)
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens return (err);
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens err = dmu_read_uio_dnode(dn, uio, size);
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens dnode_rele(dn, FTAG);
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens return (err);
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens}
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haleystatic int
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haleydmu_write_uio_dnode(dnode_t *dn, uio_t *uio, uint64_t size, dmu_tx_t *tx)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmu_buf_t **dbp;
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley int numbufs;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int err = 0;
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley int i;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley err = dmu_buf_hold_array_by_dnode(dn, uio->uio_loffset, size,
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley FALSE, FTAG, &numbufs, &dbp, DMU_READ_PREFETCH);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (err)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (err);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; i < numbufs; i++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens int tocpy;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int bufoff;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmu_buf_t *db = dbp[i];
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(size > 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
feb08c6bb47ceffa5bb7a70f2c0549113f40fcc5billm bufoff = uio->uio_loffset - db->db_offset;
fa9e4066f08beec538e775443c5be79dd423fcabahrens tocpy = (int)MIN(db->db_size - bufoff, size);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(i == 0 || i == numbufs-1 || tocpy == db->db_size);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (tocpy == db->db_size)
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmu_buf_will_fill(db, tx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens else
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmu_buf_will_dirty(db, tx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * XXX uiomove could block forever (eg. nfs-backed
fa9e4066f08beec538e775443c5be79dd423fcabahrens * pages). There needs to be a uiolockdown() function
fa9e4066f08beec538e775443c5be79dd423fcabahrens * to lock the pages in memory, so that uiomove won't
fa9e4066f08beec538e775443c5be79dd423fcabahrens * block.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens err = uiomove((char *)db->db_data + bufoff, tocpy,
fa9e4066f08beec538e775443c5be79dd423fcabahrens UIO_WRITE, uio);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (tocpy == db->db_size)
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmu_buf_fill_done(db, tx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (err)
fa9e4066f08beec538e775443c5be79dd423fcabahrens break;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens size -= tocpy;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock dmu_buf_rele_array(dbp, numbufs, FTAG);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (err);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens/*
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens * Write 'size' bytes from the uio buffer.
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens * To object zdb->db_object.
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens * Starting at offset uio->uio_loffset.
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens *
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens * If the caller already has a dbuf in the target object
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens * (e.g. its bonus buffer), this routine is faster than dmu_write_uio(),
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens * because we don't have to find the dnode_t for the object.
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens */
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haleyint
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haleydmu_write_uio_dbuf(dmu_buf_t *zdb, uio_t *uio, uint64_t size,
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley dmu_tx_t *tx)
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley{
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dmu_buf_impl_t *db = (dmu_buf_impl_t *)zdb;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dnode_t *dn;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson int err;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley if (size == 0)
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley return (0);
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_ENTER(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dn = DB_DNODE(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson err = dmu_write_uio_dnode(dn, uio, size, tx);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_EXIT(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson return (err);
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley}
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens/*
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens * Write 'size' bytes from the uio buffer.
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens * To the specified object.
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens * Starting at offset uio->uio_loffset.
f8554bb92be6be88a684bea58293b41a6168a538Matthew Ahrens */
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haleyint
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haleydmu_write_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size,
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley dmu_tx_t *tx)
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley{
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley dnode_t *dn;
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley int err;
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley if (size == 0)
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley return (0);
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley err = dnode_hold(os, object, FTAG, &dn);
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley if (err)
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley return (err);
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley err = dmu_write_uio_dnode(dn, uio, size, tx);
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley dnode_rele(dn, FTAG);
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley return (err);
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley}
94d1a2100edbb6781ea1c047a6334bb3f15640f5Tim Haley
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybeeint
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybeedmu_write_pages(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee page_t *pp, dmu_tx_t *tx)
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee{
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee dmu_buf_t **dbp;
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee int numbufs, i;
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee int err;
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee if (size == 0)
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee return (0);
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee err = dmu_buf_hold_array(os, object, offset, size,
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee FALSE, FTAG, &numbufs, &dbp);
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee if (err)
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee return (err);
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee for (i = 0; i < numbufs; i++) {
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee int tocpy, copied, thiscpy;
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee int bufoff;
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee dmu_buf_t *db = dbp[i];
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee caddr_t va;
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee ASSERT(size > 0);
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee ASSERT3U(db->db_size, >=, PAGESIZE);
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee bufoff = offset - db->db_offset;
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee tocpy = (int)MIN(db->db_size - bufoff, size);
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee ASSERT(i == 0 || i == numbufs-1 || tocpy == db->db_size);
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee if (tocpy == db->db_size)
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee dmu_buf_will_fill(db, tx);
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee else
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee dmu_buf_will_dirty(db, tx);
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee for (copied = 0; copied < tocpy; copied += PAGESIZE) {
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee ASSERT3U(pp->p_offset, ==, db->db_offset + bufoff);
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee thiscpy = MIN(PAGESIZE, tocpy - copied);
0fab61babcfe4e703c15518d8ef8d07e1a545650Jonathan W Adams va = zfs_map_page(pp, S_READ);
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee bcopy(va, (char *)db->db_data + bufoff, thiscpy);
0fab61babcfe4e703c15518d8ef8d07e1a545650Jonathan W Adams zfs_unmap_page(pp, va);
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee pp = pp->p_next;
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee bufoff += PAGESIZE;
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee }
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee if (tocpy == db->db_size)
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee dmu_buf_fill_done(db, tx);
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee offset += tocpy;
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee size -= tocpy;
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee }
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee dmu_buf_rele_array(dbp, numbufs, FTAG);
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee return (err);
44eda4d76a9383a159e44aa60b63a17644ddd5b1maybee}
fa9e4066f08beec538e775443c5be79dd423fcabahrens#endif
fa9e4066f08beec538e775443c5be79dd423fcabahrens
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy/*
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * Allocate a loaned anonymous arc buffer.
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiyarc_buf_t *
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiydmu_request_arcbuf(dmu_buf_t *handle, int size)
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy{
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dmu_buf_impl_t *db = (dmu_buf_impl_t *)handle;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel return (arc_loan_buf(db->db_objset->os_spa, B_FALSE, size));
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy}
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy/*
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * Free a loaned arc buffer.
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiyvoid
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiydmu_return_arcbuf(arc_buf_t *buf)
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy{
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy arc_return_buf(buf, FTAG);
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson arc_buf_destroy(buf, FTAG);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy}
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy/*
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * When possible directly assign passed loaned arc buffer to a dbuf.
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * If this is not possible copy the contents of passed arc buf via
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy * dmu_write().
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy */
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiyvoid
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiydmu_assign_arcbuf(dmu_buf_t *handle, uint64_t offset, arc_buf_t *buf,
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy dmu_tx_t *tx)
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy{
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dmu_buf_impl_t *dbuf = (dmu_buf_impl_t *)handle;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dnode_t *dn;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy dmu_buf_impl_t *db;
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel uint32_t blksz = (uint32_t)arc_buf_lsize(buf);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy uint64_t blkid;
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_ENTER(dbuf);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dn = DB_DNODE(dbuf);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy rw_enter(&dn->dn_struct_rwlock, RW_READER);
a2cdcdd260232b58202b11a9bfc0103c9449ed52Paul Dagnelie blkid = dbuf_whichblock(dn, 0, offset);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy VERIFY((db = dbuf_hold(dn, blkid, FTAG)) != NULL);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy rw_exit(&dn->dn_struct_rwlock);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_EXIT(dbuf);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
8a9047098ad8ce5afa38b6d012c8b509bb619f40Matthew Ahrens /*
8a9047098ad8ce5afa38b6d012c8b509bb619f40Matthew Ahrens * We can only assign if the offset is aligned, the arc buf is the
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel * same size as the dbuf, and the dbuf is not metadata.
8a9047098ad8ce5afa38b6d012c8b509bb619f40Matthew Ahrens */
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel if (offset == db->db.db_offset && blksz == db->db.db_size) {
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy dbuf_assign_arcbuf(db, buf, tx);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy dbuf_rele(db, FTAG);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy } else {
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson objset_t *os;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson uint64_t object;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel /* compressed bufs must always be assignable to their dbuf */
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel ASSERT3U(arc_get_compression(buf), ==, ZIO_COMPRESS_OFF);
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel ASSERT(!(buf->b_flags & ARC_BUF_FLAG_COMPRESSED));
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_ENTER(dbuf);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dn = DB_DNODE(dbuf);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson os = dn->dn_objset;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson object = dn->dn_object;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_EXIT(dbuf);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy dbuf_rele(db, FTAG);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dmu_write(os, object, offset, blksz, buf->b_data, tx);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy dmu_return_arcbuf(buf);
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States XUIOSTAT_BUMP(xuiostat_wbuf_copied);
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy }
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy}
2fdbea25c2ba89186b8a6b7c6840ebc9f4dff245Aleksandr Guzovskiy
c5c6ffa0498b9c8555798756141b4a3061a138c1maybeetypedef struct {
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dbuf_dirty_record_t *dsa_dr;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dmu_sync_cb_t *dsa_done;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick zgd_t *dsa_zgd;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dmu_tx_t *dsa_tx;
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee} dmu_sync_arg_t;
c5c6ffa0498b9c8555798756141b4a3061a138c1maybee
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick/* ARGSUSED */
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwickstatic void
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwickdmu_sync_ready(zio_t *zio, arc_buf_t *buf, void *varg)
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick{
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dmu_sync_arg_t *dsa = varg;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dmu_buf_t *db = dsa->dsa_zgd->zgd_db;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick blkptr_t *bp = zio->io_bp;
975c32a05c38c6fa808592dd35fa6dba183ca077Neil Perrin
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick if (zio->io_error == 0) {
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick if (BP_IS_HOLE(bp)) {
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick /*
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * A block of zeros may compress to a hole, but the
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * block size still needs to be known for replay.
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick */
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick BP_SET_LSIZE(bp, db->db_size);
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens } else if (!BP_IS_EMBEDDED(bp)) {
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick ASSERT(BP_GET_LEVEL(bp) == 0);
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick bp->blk_fill = 1;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick }
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick }
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick}
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwickstatic void
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwickdmu_sync_late_arrival_ready(zio_t *zio)
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick{
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dmu_sync_ready(zio, NULL, zio->io_private);
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick}
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick
c5c6ffa0498b9c8555798756141b4a3061a138c1maybee/* ARGSUSED */
c5c6ffa0498b9c8555798756141b4a3061a138c1maybeestatic void
c5c6ffa0498b9c8555798756141b4a3061a138c1maybeedmu_sync_done(zio_t *zio, arc_buf_t *buf, void *varg)
c5c6ffa0498b9c8555798756141b4a3061a138c1maybee{
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dmu_sync_arg_t *dsa = varg;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dbuf_dirty_record_t *dr = dsa->dsa_dr;
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee dmu_buf_impl_t *db = dr->dr_dbuf;
c5c6ffa0498b9c8555798756141b4a3061a138c1maybee
b50a0fe0a71cfbd8811ad06ae54e0986ff73b9deNeil Perrin mutex_enter(&db->db_mtx);
b50a0fe0a71cfbd8811ad06ae54e0986ff73b9deNeil Perrin ASSERT(dr->dt.dl.dr_override_state == DR_IN_DMU_SYNC);
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick if (zio->io_error == 0) {
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson dr->dt.dl.dr_nopwrite = !!(zio->io_flags & ZIO_FLAG_NOPWRITE);
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson if (dr->dt.dl.dr_nopwrite) {
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson blkptr_t *bp = zio->io_bp;
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson blkptr_t *bp_orig = &zio->io_bp_orig;
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson uint8_t chksum = BP_GET_CHECKSUM(bp_orig);
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson ASSERT(BP_EQUAL(bp, bp_orig));
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson ASSERT(zio->io_prop.zp_compress != ZIO_COMPRESS_OFF);
45818ee124adeaaf947698996b4f4c722afc6d1fMatthew Ahrens ASSERT(zio_checksum_table[chksum].ci_flags &
45818ee124adeaaf947698996b4f4c722afc6d1fMatthew Ahrens ZCHECKSUM_FLAG_NOPWRITE);
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson }
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dr->dt.dl.dr_overridden_by = *zio->io_bp;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dr->dt.dl.dr_override_state = DR_OVERRIDDEN;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dr->dt.dl.dr_copies = zio->io_prop.zp_copies;
70163ac57e58ace1c5c94dfbe85dca5a974eff36Prakash Surya
70163ac57e58ace1c5c94dfbe85dca5a974eff36Prakash Surya /*
70163ac57e58ace1c5c94dfbe85dca5a974eff36Prakash Surya * Old style holes are filled with all zeros, whereas
70163ac57e58ace1c5c94dfbe85dca5a974eff36Prakash Surya * new-style holes maintain their lsize, type, level,
70163ac57e58ace1c5c94dfbe85dca5a974eff36Prakash Surya * and birth time (see zio_write_compress). While we
70163ac57e58ace1c5c94dfbe85dca5a974eff36Prakash Surya * need to reset the BP_SET_LSIZE() call that happened
70163ac57e58ace1c5c94dfbe85dca5a974eff36Prakash Surya * in dmu_sync_ready for old style holes, we do *not*
70163ac57e58ace1c5c94dfbe85dca5a974eff36Prakash Surya * want to wipe out the information contained in new
70163ac57e58ace1c5c94dfbe85dca5a974eff36Prakash Surya * style holes. Thus, only zero out the block pointer if
70163ac57e58ace1c5c94dfbe85dca5a974eff36Prakash Surya * it's an old style hole.
70163ac57e58ace1c5c94dfbe85dca5a974eff36Prakash Surya */
70163ac57e58ace1c5c94dfbe85dca5a974eff36Prakash Surya if (BP_IS_HOLE(&dr->dt.dl.dr_overridden_by) &&
70163ac57e58ace1c5c94dfbe85dca5a974eff36Prakash Surya dr->dt.dl.dr_overridden_by.blk_birth == 0)
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick BP_ZERO(&dr->dt.dl.dr_overridden_by);
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick } else {
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dr->dt.dl.dr_override_state = DR_NOT_OVERRIDDEN;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick }
c5c6ffa0498b9c8555798756141b4a3061a138c1maybee cv_broadcast(&db->db_changed);
b50a0fe0a71cfbd8811ad06ae54e0986ff73b9deNeil Perrin mutex_exit(&db->db_mtx);
b50a0fe0a71cfbd8811ad06ae54e0986ff73b9deNeil Perrin
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dsa->dsa_done(dsa->dsa_zgd, zio->io_error);
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick kmem_free(dsa, sizeof (*dsa));
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick}
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwickstatic void
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwickdmu_sync_late_arrival_done(zio_t *zio)
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick{
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick blkptr_t *bp = zio->io_bp;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dmu_sync_arg_t *dsa = zio->io_private;
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson blkptr_t *bp_orig = &zio->io_bp_orig;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick if (zio->io_error == 0 && !BP_IS_HOLE(bp)) {
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson /*
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson * If we didn't allocate a new block (i.e. ZIO_FLAG_NOPWRITE)
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson * then there is nothing to do here. Otherwise, free the
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson * newly allocated block in this txg.
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson */
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson if (zio->io_flags & ZIO_FLAG_NOPWRITE) {
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson ASSERT(BP_EQUAL(bp, bp_orig));
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson } else {
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson ASSERT(BP_IS_HOLE(bp_orig) || !BP_EQUAL(bp, bp_orig));
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson ASSERT(zio->io_bp->blk_birth == zio->io_txg);
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson ASSERT(zio->io_txg > spa_syncing_txg(zio->io_spa));
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson zio_free(zio->io_spa, zio->io_txg, zio->io_bp);
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson }
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick }
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dmu_tx_commit(dsa->dsa_tx);
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dsa->dsa_done(dsa->dsa_zgd, zio->io_error);
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick kmem_free(dsa, sizeof (*dsa));
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick}
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwickstatic int
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwickdmu_sync_late_arrival(zio_t *pio, objset_t *os, dmu_sync_cb_t *done, zgd_t *zgd,
7802d7bf98dec568dadf72286893b1fe5abd8602Matthew Ahrens zio_prop_t *zp, zbookmark_phys_t *zb)
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick{
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dmu_sync_arg_t *dsa;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dmu_tx_t *tx;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick tx = dmu_tx_create(os);
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dmu_tx_hold_space(tx, zgd->zgd_db->db_size);
6e1f5caa9321646aa4212d48e32a0d241866d85dNeil Perrin if (dmu_tx_assign(tx, TXG_WAIT) != 0) {
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dmu_tx_abort(tx);
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens /* Make zl_get_data do txg_waited_synced() */
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EIO));
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick }
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dsa = kmem_alloc(sizeof (dmu_sync_arg_t), KM_SLEEP);
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dsa->dsa_dr = NULL;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dsa->dsa_done = done;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dsa->dsa_zgd = zgd;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dsa->dsa_tx = tx;
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel zio_nowait(zio_write(pio, os->os_spa, dmu_tx_get_txg(tx), zgd->zgd_bp,
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel zgd->zgd_db->db_data, zgd->zgd_db->db_size, zgd->zgd_db->db_size,
8df0bcf0df7622a075cc6e52f659d2fcfdd08cdcPaul Dagnelie zp, dmu_sync_late_arrival_ready, NULL,
8df0bcf0df7622a075cc6e52f659d2fcfdd08cdcPaul Dagnelie NULL, dmu_sync_late_arrival_done, dsa, ZIO_PRIORITY_SYNC_WRITE,
8df0bcf0df7622a075cc6e52f659d2fcfdd08cdcPaul Dagnelie ZIO_FLAG_CANFAIL, zb));
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick return (0);
c5c6ffa0498b9c8555798756141b4a3061a138c1maybee}
c5c6ffa0498b9c8555798756141b4a3061a138c1maybee
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
c5c6ffa0498b9c8555798756141b4a3061a138c1maybee * Intent log support: sync the block associated with db to disk.
c5c6ffa0498b9c8555798756141b4a3061a138c1maybee * N.B. and XXX: the caller is responsible for making sure that the
c5c6ffa0498b9c8555798756141b4a3061a138c1maybee * data isn't changing while dmu_sync() is writing it.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Return values:
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson * EEXIST: this txg has already been synced, so there's nothing to do.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The caller should not log the write.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * ENOENT: the block was dbuf_free_range()'d, so there's nothing to do.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The caller should not log the write.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
c5c6ffa0498b9c8555798756141b4a3061a138c1maybee * EALREADY: this block is already in the process of being synced.
c5c6ffa0498b9c8555798756141b4a3061a138c1maybee * The caller should track its progress (somehow).
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * EIO: could not do the I/O.
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * The caller should do a txg_wait_synced().
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * 0: the I/O has been initiated.
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * The caller should log this blkptr in the done callback.
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * It is possible that the I/O will fail, in which case
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * the error will be reported to the done callback and
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * propagated to pio from zio_done().
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensint
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwickdmu_sync(zio_t *pio, uint64_t txg, dmu_sync_cb_t *done, zgd_t *zgd)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick blkptr_t *bp = zgd->zgd_bp;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dmu_buf_impl_t *db = (dmu_buf_impl_t *)zgd->zgd_db;
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens objset_t *os = db->db_objset;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dsl_dataset_t *ds = os->os_dsl_dataset;
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee dbuf_dirty_record_t *dr;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dmu_sync_arg_t *dsa;
7802d7bf98dec568dadf72286893b1fe5abd8602Matthew Ahrens zbookmark_phys_t zb;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick zio_prop_t zp;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dnode_t *dn;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick ASSERT(pio != NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT(txg != 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick SET_BOOKMARK(&zb, ds->ds_object,
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick db->db.db_object, db->db_level, db->db_blkid);
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_ENTER(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dn = DB_DNODE(db);
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel dmu_write_policy(os, dn, db->db_level, WP_DMU_SYNC,
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel ZIO_COMPRESS_INHERIT, &zp);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_EXIT(db);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock /*
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * If we're frozen (running ziltest), we always need to generate a bp.
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock */
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick if (txg > spa_freeze_txg(os->os_spa))
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick return (dmu_sync_late_arrival(pio, os, done, zgd, &zp, &zb));
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * Grabbing db_mtx now provides a barrier between dbuf_sync_leaf()
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * and us. If we determine that this txg is not yet syncing,
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * but it begins to sync a moment later, that's OK because the
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * sync thread will block in dbuf_sync_leaf() until we drop db_mtx.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick mutex_enter(&db->db_mtx);
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick if (txg <= spa_last_synced_txg(os->os_spa)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * This txg has already synced. There's nothing to do.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick mutex_exit(&db->db_mtx);
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EEXIST));
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick if (txg <= spa_syncing_txg(os->os_spa)) {
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick /*
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * This txg is currently syncing, so we can't mess with
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * the dirty record anymore; just write a new log block.
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick */
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick mutex_exit(&db->db_mtx);
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick return (dmu_sync_late_arrival(pio, os, done, zgd, &zp, &zb));
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee dr = db->db_last_dirty;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick while (dr && dr->dr_txg != txg)
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee dr = dr->dr_next;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick if (dr == NULL) {
c5c6ffa0498b9c8555798756141b4a3061a138c1maybee /*
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * There's no dr for this dbuf, so it must have been freed.
c5c6ffa0498b9c8555798756141b4a3061a138c1maybee * There's no need to log writes to freed blocks, so we're done.
c5c6ffa0498b9c8555798756141b4a3061a138c1maybee */
c5c6ffa0498b9c8555798756141b4a3061a138c1maybee mutex_exit(&db->db_mtx);
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(ENOENT));
c5c6ffa0498b9c8555798756141b4a3061a138c1maybee }
c5c6ffa0498b9c8555798756141b4a3061a138c1maybee
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson ASSERT(dr->dr_next == NULL || dr->dr_next->dr_txg < txg);
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson /*
34e8acef009195effafdcf6417aec385e241796eMatthew Ahrens * Assume the on-disk data is X, the current syncing data (in
34e8acef009195effafdcf6417aec385e241796eMatthew Ahrens * txg - 1) is Y, and the current in-memory data is Z (currently
34e8acef009195effafdcf6417aec385e241796eMatthew Ahrens * in dmu_sync).
34e8acef009195effafdcf6417aec385e241796eMatthew Ahrens *
34e8acef009195effafdcf6417aec385e241796eMatthew Ahrens * We usually want to perform a nopwrite if X and Z are the
34e8acef009195effafdcf6417aec385e241796eMatthew Ahrens * same. However, if Y is different (i.e. the BP is going to
34e8acef009195effafdcf6417aec385e241796eMatthew Ahrens * change before this write takes effect), then a nopwrite will
34e8acef009195effafdcf6417aec385e241796eMatthew Ahrens * be incorrect - we would override with X, which could have
34e8acef009195effafdcf6417aec385e241796eMatthew Ahrens * been freed when Y was written.
34e8acef009195effafdcf6417aec385e241796eMatthew Ahrens *
34e8acef009195effafdcf6417aec385e241796eMatthew Ahrens * (Note that this is not a concern when we are nop-writing from
34e8acef009195effafdcf6417aec385e241796eMatthew Ahrens * syncing context, because X and Y must be identical, because
34e8acef009195effafdcf6417aec385e241796eMatthew Ahrens * all previous txgs have been synced.)
34e8acef009195effafdcf6417aec385e241796eMatthew Ahrens *
34e8acef009195effafdcf6417aec385e241796eMatthew Ahrens * Therefore, we disable nopwrite if the current BP could change
34e8acef009195effafdcf6417aec385e241796eMatthew Ahrens * before this TXG. There are two ways it could change: by
34e8acef009195effafdcf6417aec385e241796eMatthew Ahrens * being dirty (dr_next is non-NULL), or by being freed
34e8acef009195effafdcf6417aec385e241796eMatthew Ahrens * (dnode_block_freed()). This behavior is verified by
34e8acef009195effafdcf6417aec385e241796eMatthew Ahrens * zio_done(), which VERIFYs that the override BP is identical
34e8acef009195effafdcf6417aec385e241796eMatthew Ahrens * to the on-disk BP.
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson */
34e8acef009195effafdcf6417aec385e241796eMatthew Ahrens DB_DNODE_ENTER(db);
34e8acef009195effafdcf6417aec385e241796eMatthew Ahrens dn = DB_DNODE(db);
34e8acef009195effafdcf6417aec385e241796eMatthew Ahrens if (dr->dr_next != NULL || dnode_block_freed(dn, db->db_blkid))
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson zp.zp_nopwrite = B_FALSE;
34e8acef009195effafdcf6417aec385e241796eMatthew Ahrens DB_DNODE_EXIT(db);
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee ASSERT(dr->dr_txg == txg);
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick if (dr->dt.dl.dr_override_state == DR_IN_DMU_SYNC ||
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dr->dt.dl.dr_override_state == DR_OVERRIDDEN) {
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee /*
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * We have already issued a sync write for this buffer,
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * or this buffer has already been synced. It could not
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee * have been dirtied since, or we would have cleared the state.
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee */
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee mutex_exit(&db->db_mtx);
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EALREADY));
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee }
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick ASSERT(dr->dt.dl.dr_override_state == DR_NOT_OVERRIDDEN);
c717a56157ae0e6fca6a1e3689ae1edc385716a3maybee dr->dt.dl.dr_override_state = DR_IN_DMU_SYNC;
fa9e4066f08beec538e775443c5be79dd423fcabahrens mutex_exit(&db->db_mtx);
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dsa = kmem_alloc(sizeof (dmu_sync_arg_t), KM_SLEEP);
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dsa->dsa_dr = dr;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dsa->dsa_done = done;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dsa->dsa_zgd = zgd;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dsa->dsa_tx = NULL;
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick zio_nowait(arc_write(pio, os->os_spa, txg,
aad02571bc59671aa3103bb070ae365f531b0b62Saso Kiselkov bp, dr->dt.dl.dr_data, DBUF_IS_L2CACHEABLE(db),
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson &zp, dmu_sync_ready, NULL, NULL, dmu_sync_done, dsa,
8df0bcf0df7622a075cc6e52f659d2fcfdd08cdcPaul Dagnelie ZIO_PRIORITY_SYNC_WRITE, ZIO_FLAG_CANFAIL, &zb));
e14bb3258d05c1b1077e2db7cf77088924e56919Jeff Bonwick
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensint
fa9e4066f08beec538e775443c5be79dd423fcabahrensdmu_object_set_blocksize(objset_t *os, uint64_t object, uint64_t size, int ibs,
9a686fbc186e8e2a64e9a5094d44c7d6fa0ea167Paul Dagnelie dmu_tx_t *tx)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock dnode_t *dn;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock int err;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens err = dnode_hold(os, object, FTAG, &dn);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (err)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (err);
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock err = dnode_set_blksz(dn, size, ibs, tx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnode_rele(dn, FTAG);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (err);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid
fa9e4066f08beec538e775443c5be79dd423fcabahrensdmu_object_set_checksum(objset_t *os, uint64_t object, uint8_t checksum,
9a686fbc186e8e2a64e9a5094d44c7d6fa0ea167Paul Dagnelie dmu_tx_t *tx)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock dnode_t *dn;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens /*
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens * Send streams include each object's checksum function. This
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens * check ensures that the receiving system can understand the
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens * checksum function transmitted.
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens */
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens ASSERT3U(checksum, <, ZIO_CHECKSUM_LEGACY_FUNCTIONS);
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens VERIFY0(dnode_hold(os, object, FTAG, &dn));
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens ASSERT3U(checksum, <, ZIO_CHECKSUM_FUNCTIONS);
fa9e4066f08beec538e775443c5be79dd423fcabahrens dn->dn_checksum = checksum;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnode_setdirty(dn, tx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnode_rele(dn, FTAG);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid
fa9e4066f08beec538e775443c5be79dd423fcabahrensdmu_object_set_compress(objset_t *os, uint64_t object, uint8_t compress,
9a686fbc186e8e2a64e9a5094d44c7d6fa0ea167Paul Dagnelie dmu_tx_t *tx)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock dnode_t *dn;
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens /*
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens * Send streams include each object's compression function. This
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens * check ensures that the receiving system can understand the
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens * compression function transmitted.
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens */
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens ASSERT3U(compress, <, ZIO_COMPRESS_LEGACY_FUNCTIONS);
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens VERIFY0(dnode_hold(os, object, FTAG, &dn));
fa9e4066f08beec538e775443c5be79dd423fcabahrens dn->dn_compress = compress;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnode_setdirty(dn, tx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnode_rele(dn, FTAG);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwickint zfs_mdcomp_disable = 0;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick
edf345e6b8342e8627ec20ce821a977a62cee19dMatthew Ahrens/*
edf345e6b8342e8627ec20ce821a977a62cee19dMatthew Ahrens * When the "redundant_metadata" property is set to "most", only indirect
edf345e6b8342e8627ec20ce821a977a62cee19dMatthew Ahrens * blocks of this level and higher will have an additional ditto block.
edf345e6b8342e8627ec20ce821a977a62cee19dMatthew Ahrens */
edf345e6b8342e8627ec20ce821a977a62cee19dMatthew Ahrensint zfs_redundant_metadata_most_ditto_level = 2;
edf345e6b8342e8627ec20ce821a977a62cee19dMatthew Ahrens
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwickvoid
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmeldmu_write_policy(objset_t *os, dnode_t *dn, int level, int wp,
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel enum zio_compress override_compress, zio_prop_t *zp)
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick{
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dmu_object_type_t type = dn ? dn->dn_type : DMU_OT_OBJSET;
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden boolean_t ismd = (level > 0 || DMU_OT_IS_METADATA(type) ||
1d8ccc7bfd8ab0f27a23c5253d95c22ceb9c27f4Mark Shellenbaum (wp & WP_SPILL));
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick enum zio_checksum checksum = os->os_checksum;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick enum zio_compress compress = os->os_compress;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick enum zio_checksum dedup_checksum = os->os_dedup_checksum;
7540df39e407a55c887fa4ab85d85abc26cc0cf2George Wilson boolean_t dedup = B_FALSE;
7540df39e407a55c887fa4ab85d85abc26cc0cf2George Wilson boolean_t nopwrite = B_FALSE;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick boolean_t dedup_verify = os->os_dedup_verify;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick int copies = os->os_copies;
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel boolean_t lz4_ac = spa_feature_is_active(os->os_spa,
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel SPA_FEATURE_LZ4_COMPRESS);
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel IMPLY(override_compress == ZIO_COMPRESS_LZ4, lz4_ac);
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick /*
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson * We maintain different write policies for each of the following
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson * types of data:
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson * 1. metadata
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson * 2. preallocated blocks (i.e. level-0 blocks of a dump device)
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson * 3. all other level 0 blocks
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick */
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick if (ismd) {
b8289d24d866c1af02d7007348f7f057693c15d3Daniil Lunev if (zfs_mdcomp_disable) {
b8289d24d866c1af02d7007348f7f057693c15d3Daniil Lunev compress = ZIO_COMPRESS_EMPTY;
b8289d24d866c1af02d7007348f7f057693c15d3Daniil Lunev } else {
db1741f555ec79def5e9846e6bfd132248514ffeJustin T. Gibbs /*
db1741f555ec79def5e9846e6bfd132248514ffeJustin T. Gibbs * XXX -- we should design a compression algorithm
db1741f555ec79def5e9846e6bfd132248514ffeJustin T. Gibbs * that specializes in arrays of bps.
db1741f555ec79def5e9846e6bfd132248514ffeJustin T. Gibbs */
db1741f555ec79def5e9846e6bfd132248514ffeJustin T. Gibbs compress = zio_compress_select(os->os_spa,
db1741f555ec79def5e9846e6bfd132248514ffeJustin T. Gibbs ZIO_COMPRESS_ON, ZIO_COMPRESS_ON);
b8289d24d866c1af02d7007348f7f057693c15d3Daniil Lunev }
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick /*
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * Metadata always gets checksummed. If the data
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * checksum is multi-bit correctable, and it's not a
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * ZBT-style checksum, then it's suitable for metadata
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * as well. Otherwise, the metadata checksum defaults
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick * to fletcher4.
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick */
45818ee124adeaaf947698996b4f4c722afc6d1fMatthew Ahrens if (!(zio_checksum_table[checksum].ci_flags &
45818ee124adeaaf947698996b4f4c722afc6d1fMatthew Ahrens ZCHECKSUM_FLAG_METADATA) ||
45818ee124adeaaf947698996b4f4c722afc6d1fMatthew Ahrens (zio_checksum_table[checksum].ci_flags &
45818ee124adeaaf947698996b4f4c722afc6d1fMatthew Ahrens ZCHECKSUM_FLAG_EMBEDDED))
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick checksum = ZIO_CHECKSUM_FLETCHER_4;
edf345e6b8342e8627ec20ce821a977a62cee19dMatthew Ahrens
edf345e6b8342e8627ec20ce821a977a62cee19dMatthew Ahrens if (os->os_redundant_metadata == ZFS_REDUNDANT_METADATA_ALL ||
edf345e6b8342e8627ec20ce821a977a62cee19dMatthew Ahrens (os->os_redundant_metadata ==
edf345e6b8342e8627ec20ce821a977a62cee19dMatthew Ahrens ZFS_REDUNDANT_METADATA_MOST &&
edf345e6b8342e8627ec20ce821a977a62cee19dMatthew Ahrens (level >= zfs_redundant_metadata_most_ditto_level ||
edf345e6b8342e8627ec20ce821a977a62cee19dMatthew Ahrens DMU_OT_IS_METADATA(type) || (wp & WP_SPILL))))
edf345e6b8342e8627ec20ce821a977a62cee19dMatthew Ahrens copies++;
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson } else if (wp & WP_NOFILL) {
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson ASSERT(level == 0);
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick /*
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson * If we're writing preallocated blocks, we aren't actually
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson * writing them so don't set any policy properties. These
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson * blocks are currently only used by an external subsystem
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson * outside of zfs (i.e. dump) and not written by the zio
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson * pipeline.
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick */
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson compress = ZIO_COMPRESS_OFF;
810e43b2eb0e320833671a403fdda51917e8b036Bill Pijewski checksum = ZIO_CHECKSUM_NOPARITY;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick } else {
db1741f555ec79def5e9846e6bfd132248514ffeJustin T. Gibbs compress = zio_compress_select(os->os_spa, dn->dn_compress,
db1741f555ec79def5e9846e6bfd132248514ffeJustin T. Gibbs compress);
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson checksum = (dedup_checksum == ZIO_CHECKSUM_OFF) ?
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson zio_checksum_select(dn->dn_checksum, checksum) :
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson dedup_checksum;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson /*
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson * Determine dedup setting. If we are in dmu_sync(),
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson * we won't actually dedup now because that's all
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson * done in syncing context; but we do want to use the
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson * dedup checkum. If the checksum is not strong
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson * enough to ensure unique signatures, force
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson * dedup_verify.
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson */
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson if (dedup_checksum != ZIO_CHECKSUM_OFF) {
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson dedup = (wp & WP_DMU_SYNC) ? B_FALSE : B_TRUE;
45818ee124adeaaf947698996b4f4c722afc6d1fMatthew Ahrens if (!(zio_checksum_table[checksum].ci_flags &
45818ee124adeaaf947698996b4f4c722afc6d1fMatthew Ahrens ZCHECKSUM_FLAG_DEDUP))
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson dedup_verify = B_TRUE;
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson }
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson /*
45818ee124adeaaf947698996b4f4c722afc6d1fMatthew Ahrens * Enable nopwrite if we have secure enough checksum
45818ee124adeaaf947698996b4f4c722afc6d1fMatthew Ahrens * algorithm (see comment in zio_nop_write) and
45818ee124adeaaf947698996b4f4c722afc6d1fMatthew Ahrens * compression is enabled. We don't enable nopwrite if
45818ee124adeaaf947698996b4f4c722afc6d1fMatthew Ahrens * dedup is enabled as the two features are mutually
45818ee124adeaaf947698996b4f4c722afc6d1fMatthew Ahrens * exclusive.
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson */
45818ee124adeaaf947698996b4f4c722afc6d1fMatthew Ahrens nopwrite = (!dedup && (zio_checksum_table[checksum].ci_flags &
45818ee124adeaaf947698996b4f4c722afc6d1fMatthew Ahrens ZCHECKSUM_FLAG_NOPWRITE) &&
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson compress != ZIO_COMPRESS_OFF && zfs_nopwrite_enabled);
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick }
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick zp->zp_checksum = checksum;
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel /*
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel * If we're writing a pre-compressed buffer, the compression type we use
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel * must match the data. If it hasn't been compressed yet, then we should
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel * use the value dictated by the policies above.
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel */
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel zp->zp_compress = override_compress != ZIO_COMPRESS_INHERIT
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel ? override_compress : compress;
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel ASSERT3U(zp->zp_compress, !=, ZIO_COMPRESS_INHERIT);
5602294fda888d923d57a78bafdaf48ae6223deaDan Kimmel
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum zp->zp_type = (wp & WP_SPILL) ? dn->dn_bonustype : type;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick zp->zp_level = level;
edf345e6b8342e8627ec20ce821a977a62cee19dMatthew Ahrens zp->zp_copies = MIN(copies, spa_max_replication(os->os_spa));
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick zp->zp_dedup = dedup;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick zp->zp_dedup_verify = dedup && dedup_verify;
80901aea8e78a2c20751f61f01bebd1d5b5c2ba5George Wilson zp->zp_nopwrite = nopwrite;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick}
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick
fa9e4066f08beec538e775443c5be79dd423fcabahrensint
fa9e4066f08beec538e775443c5be79dd423fcabahrensdmu_offset_next(objset_t *os, uint64_t object, boolean_t hole, uint64_t *off)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnode_t *dn;
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman int err;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Sync any current changes before
fa9e4066f08beec538e775443c5be79dd423fcabahrens * we go trundling through the block pointers.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman err = dmu_object_wait_synced(os, object);
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman if (err) {
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman return (err);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman err = dnode_hold(os, object, FTAG, &dn);
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman if (err) {
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman return (err);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee err = dnode_next_offset(dn, (hole ? DNODE_FIND_HOLE : 0), off, 1, 1, 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnode_rele(dn, FTAG);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (err);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman/*
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman * Given the ZFS object, if it contains any dirty nodes
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman * this function flushes all dirty blocks to disk. This
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman * ensures the DMU object info is updated. A more efficient
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman * future version might just find the TXG with the maximum
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman * ID and wait for that to be synced.
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman */
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossmanint
9a686fbc186e8e2a64e9a5094d44c7d6fa0ea167Paul Dagneliedmu_object_wait_synced(objset_t *os, uint64_t object)
9a686fbc186e8e2a64e9a5094d44c7d6fa0ea167Paul Dagnelie{
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman dnode_t *dn;
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman int error, i;
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman error = dnode_hold(os, object, FTAG, &dn);
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman if (error) {
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman return (error);
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman }
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman for (i = 0; i < TXG_SIZE; i++) {
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman if (list_link_active(&dn->dn_dirty_link[i])) {
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman break;
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman }
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman }
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman dnode_rele(dn, FTAG);
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman if (i != TXG_SIZE) {
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman txg_wait_synced(dmu_objset_pool(os), 0);
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman }
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman return (0);
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman}
2bcf0248e992f292c7b814458bcdce2f004925d6Max Grossman
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid
fa9e4066f08beec538e775443c5be79dd423fcabahrensdmu_object_info_from_dnode(dnode_t *dn, dmu_object_info_t *doi)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dnode_phys_t *dnp;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick
fa9e4066f08beec538e775443c5be79dd423fcabahrens rw_enter(&dn->dn_struct_rwlock, RW_READER);
fa9e4066f08beec538e775443c5be79dd423fcabahrens mutex_enter(&dn->dn_mtx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick dnp = dn->dn_phys;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick
fa9e4066f08beec538e775443c5be79dd423fcabahrens doi->doi_data_block_size = dn->dn_datablksz;
fa9e4066f08beec538e775443c5be79dd423fcabahrens doi->doi_metadata_block_size = dn->dn_indblkshift ?
fa9e4066f08beec538e775443c5be79dd423fcabahrens 1ULL << dn->dn_indblkshift : 0;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick doi->doi_type = dn->dn_type;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick doi->doi_bonus_type = dn->dn_bonustype;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick doi->doi_bonus_size = dn->dn_bonuslen;
fa9e4066f08beec538e775443c5be79dd423fcabahrens doi->doi_indirection = dn->dn_nlevels;
fa9e4066f08beec538e775443c5be79dd423fcabahrens doi->doi_checksum = dn->dn_checksum;
fa9e4066f08beec538e775443c5be79dd423fcabahrens doi->doi_compress = dn->dn_compress;
e77d42eaa49fe55bfae1e0e0065c6e99affc001bMatthew Ahrens doi->doi_nblkptr = dn->dn_nblkptr;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick doi->doi_physical_blocks_512 = (DN_USED_BYTES(dnp) + 256) >> 9;
d04756377ddd1cf28ebcf652541094e17b03c889Matthew Ahrens doi->doi_max_offset = (dn->dn_maxblkid + 1) * dn->dn_datablksz;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick doi->doi_fill_count = 0;
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick for (int i = 0; i < dnp->dn_nblkptr; i++)
5d7b4d438c4a51eccc95e77a83a437b4d48380ebMatthew Ahrens doi->doi_fill_count += BP_GET_FILL(&dnp->dn_blkptr[i]);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens mutex_exit(&dn->dn_mtx);
fa9e4066f08beec538e775443c5be79dd423fcabahrens rw_exit(&dn->dn_struct_rwlock);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Get information on a DMU object.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If doi is NULL, just indicates whether the object exists.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensint
fa9e4066f08beec538e775443c5be79dd423fcabahrensdmu_object_info(objset_t *os, uint64_t object, dmu_object_info_t *doi)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock dnode_t *dn;
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens int err = dnode_hold(os, object, FTAG, &dn);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock if (err)
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock return (err);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (doi != NULL)
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmu_object_info_from_dnode(dn, doi);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnode_rele(dn, FTAG);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * As above, but faster; can be used when you have a held dbuf in hand.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Ericksondmu_object_info_from_db(dmu_buf_t *db_fake, dmu_object_info_t *doi)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dmu_buf_impl_t *db = (dmu_buf_impl_t *)db_fake;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_ENTER(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dmu_object_info_from_dnode(DB_DNODE(db), doi);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_EXIT(db);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Faster still when you only care about the size.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * This is specifically optimized for zfs_getattr().
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Ericksondmu_object_size_from_db(dmu_buf_t *db_fake, uint32_t *blksize,
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson u_longlong_t *nblk512)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dmu_buf_impl_t *db = (dmu_buf_impl_t *)db_fake;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dnode_t *dn;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_ENTER(db);
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dn = DB_DNODE(db);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens *blksize = dn->dn_datablksz;
99653d4ee642c6528e88224f12409a5f23060994eschrock /* add 1 for dnode space */
99653d4ee642c6528e88224f12409a5f23060994eschrock *nblk512 = ((DN_USED_BYTES(dn->dn_phys) + SPA_MINBLOCKSIZE/2) >>
99653d4ee642c6528e88224f12409a5f23060994eschrock SPA_MINBLOCKSHIFT) + 1;
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson DB_DNODE_EXIT(db);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid
fa9e4066f08beec538e775443c5be79dd423fcabahrensbyteswap_uint64_array(void *vbuf, size_t size)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t *buf = vbuf;
fa9e4066f08beec538e775443c5be79dd423fcabahrens size_t count = size >> 3;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int i;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT((size & 7) == 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; i < count; i++)
fa9e4066f08beec538e775443c5be79dd423fcabahrens buf[i] = BSWAP_64(buf[i]);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid
fa9e4066f08beec538e775443c5be79dd423fcabahrensbyteswap_uint32_array(void *vbuf, size_t size)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint32_t *buf = vbuf;
fa9e4066f08beec538e775443c5be79dd423fcabahrens size_t count = size >> 2;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int i;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT((size & 3) == 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; i < count; i++)
fa9e4066f08beec538e775443c5be79dd423fcabahrens buf[i] = BSWAP_32(buf[i]);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid
fa9e4066f08beec538e775443c5be79dd423fcabahrensbyteswap_uint16_array(void *vbuf, size_t size)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint16_t *buf = vbuf;
fa9e4066f08beec538e775443c5be79dd423fcabahrens size_t count = size >> 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int i;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens ASSERT((size & 1) == 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = 0; i < count; i++)
fa9e4066f08beec538e775443c5be79dd423fcabahrens buf[i] = BSWAP_16(buf[i]);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* ARGSUSED */
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid
fa9e4066f08beec538e775443c5be79dd423fcabahrensbyteswap_uint8_array(void *vbuf, size_t size)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid
fa9e4066f08beec538e775443c5be79dd423fcabahrensdmu_init(void)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling zfs_dbgmsg_init();
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson sa_cache_init();
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson xuio_stat_init();
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dmu_objset_init();
fa9e4066f08beec538e775443c5be79dd423fcabahrens dnode_init();
7cbf8b4321709b0e17bf7f2a0fb387730a1b03c1Rich Morris zfetch_init();
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan l2arc_init();
ce636f8b38e8c9ff484e880d9abb27251a882860Matthew Ahrens arc_init();
dcbf3bd6a1f1360fc1afcee9e22c6dcff7844bf2George Wilson dbuf_init();
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid
fa9e4066f08beec538e775443c5be79dd423fcabahrensdmu_fini(void)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
3e30c24aeefdee1631958ecf17f18da671781956Will Andrews arc_fini(); /* arc depends on l2arc, so arc must go first */
ce636f8b38e8c9ff484e880d9abb27251a882860Matthew Ahrens l2arc_fini();
7cbf8b4321709b0e17bf7f2a0fb387730a1b03c1Rich Morris zfetch_fini();
fa9e4066f08beec538e775443c5be79dd423fcabahrens dbuf_fini();
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dnode_fini();
744947dc83c634d985ed3ad79ac9c5e28d1865fdTom Erickson dmu_objset_fini();
c242f9a02a2ef021449275ae0a1d2581ee77231dchunli zhang - Sun Microsystems - Irvine United States xuio_stat_fini();
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum sa_cache_fini();
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling zfs_dbgmsg_fini();
fa9e4066f08beec538e775443c5be79dd423fcabahrens}