dmu_send.c revision 4e3c9f4489a18514e5e8caeb91d4e6db07c98415
efb80947b01107dafbbf0157de0d7e1af6551259ahrens/*
efb80947b01107dafbbf0157de0d7e1af6551259ahrens * CDDL HEADER START
efb80947b01107dafbbf0157de0d7e1af6551259ahrens *
efb80947b01107dafbbf0157de0d7e1af6551259ahrens * The contents of this file are subject to the terms of the
efb80947b01107dafbbf0157de0d7e1af6551259ahrens * Common Development and Distribution License (the "License").
efb80947b01107dafbbf0157de0d7e1af6551259ahrens * You may not use this file except in compliance with the License.
efb80947b01107dafbbf0157de0d7e1af6551259ahrens *
efb80947b01107dafbbf0157de0d7e1af6551259ahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
efb80947b01107dafbbf0157de0d7e1af6551259ahrens * or http://www.opensolaris.org/os/licensing.
efb80947b01107dafbbf0157de0d7e1af6551259ahrens * See the License for the specific language governing permissions
efb80947b01107dafbbf0157de0d7e1af6551259ahrens * and limitations under the License.
efb80947b01107dafbbf0157de0d7e1af6551259ahrens *
efb80947b01107dafbbf0157de0d7e1af6551259ahrens * When distributing Covered Code, include this CDDL HEADER in each
efb80947b01107dafbbf0157de0d7e1af6551259ahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
efb80947b01107dafbbf0157de0d7e1af6551259ahrens * If applicable, add the following below this CDDL HEADER, with the
efb80947b01107dafbbf0157de0d7e1af6551259ahrens * fields enclosed by brackets "[]" replaced with your own identifying
efb80947b01107dafbbf0157de0d7e1af6551259ahrens * information: Portions Copyright [yyyy] [name of copyright owner]
efb80947b01107dafbbf0157de0d7e1af6551259ahrens *
efb80947b01107dafbbf0157de0d7e1af6551259ahrens * CDDL HEADER END
efb80947b01107dafbbf0157de0d7e1af6551259ahrens */
efb80947b01107dafbbf0157de0d7e1af6551259ahrens/*
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens * Copyright (c) 2011 by Delphix. All rights reserved.
efb80947b01107dafbbf0157de0d7e1af6551259ahrens */
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko/*
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens * Copyright (c) 2011 by Delphix. All rights reserved.
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski * Copyright (c) 2012, Joyent, Inc. All rights reserved.
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko */
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens#include <sys/dmu.h>
efb80947b01107dafbbf0157de0d7e1af6551259ahrens#include <sys/dmu_impl.h>
efb80947b01107dafbbf0157de0d7e1af6551259ahrens#include <sys/dmu_tx.h>
efb80947b01107dafbbf0157de0d7e1af6551259ahrens#include <sys/dbuf.h>
efb80947b01107dafbbf0157de0d7e1af6551259ahrens#include <sys/dnode.h>
efb80947b01107dafbbf0157de0d7e1af6551259ahrens#include <sys/zfs_context.h>
efb80947b01107dafbbf0157de0d7e1af6551259ahrens#include <sys/dmu_objset.h>
efb80947b01107dafbbf0157de0d7e1af6551259ahrens#include <sys/dmu_traverse.h>
efb80947b01107dafbbf0157de0d7e1af6551259ahrens#include <sys/dsl_dataset.h>
efb80947b01107dafbbf0157de0d7e1af6551259ahrens#include <sys/dsl_dir.h>
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson#include <sys/dsl_prop.h>
efb80947b01107dafbbf0157de0d7e1af6551259ahrens#include <sys/dsl_pool.h>
efb80947b01107dafbbf0157de0d7e1af6551259ahrens#include <sys/dsl_synctask.h>
efb80947b01107dafbbf0157de0d7e1af6551259ahrens#include <sys/zfs_ioctl.h>
efb80947b01107dafbbf0157de0d7e1af6551259ahrens#include <sys/zap.h>
efb80947b01107dafbbf0157de0d7e1af6551259ahrens#include <sys/zio_checksum.h>
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum#include <sys/zfs_znode.h>
cde58dbc6a23d4d38db7c8866312be83221c765fMatthew Ahrens#include <zfs_fletcher.h>
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt#include <sys/avl.h>
8e7144747a94247ce9dbb4fb1f67bdcb666b30d8Lori Alt#include <sys/ddt.h>
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby#include <sys/zfs_onexit.h>
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens/* Set this tunable to TRUE to replace corrupt data with 0x2f5baddb10c */
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrensint zfs_send_corrupt_data = B_FALSE;
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrensstatic char *dmu_recv_tag = "dmu_recv_tag";
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrensstatic int
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewskidump_bytes(dmu_sendarg_t *dsp, void *buf, int len)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens{
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsl_dataset_t *ds = dsp->dsa_os->os_dsl_dataset;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens ssize_t resid; /* have to get resid to get detailed errno */
efb80947b01107dafbbf0157de0d7e1af6551259ahrens ASSERT3U(len % 8, ==, 0);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski fletcher_4_incremental_native(buf, len, &dsp->dsa_zc);
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_err = vn_rdwr(UIO_WRITE, dsp->dsa_vp,
efb80947b01107dafbbf0157de0d7e1af6551259ahrens (caddr_t)buf, len,
efb80947b01107dafbbf0157de0d7e1af6551259ahrens 0, UIO_SYSSPACE, FAPPEND, RLIM64_INFINITY, CRED(), &resid);
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski mutex_enter(&ds->ds_sendstream_lock);
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski *dsp->dsa_off += len;
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski mutex_exit(&ds->ds_sendstream_lock);
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski return (dsp->dsa_err);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens}
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrensstatic int
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewskidump_free(dmu_sendarg_t *dsp, uint64_t object, uint64_t offset,
efb80947b01107dafbbf0157de0d7e1af6551259ahrens uint64_t length)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens{
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski struct drr_free *drrf = &(dsp->dsa_drr->drr_u.drr_free);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt /*
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * If there is a pending op, but it's not PENDING_FREE, push it out,
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * since free block aggregation can only be done for blocks of the
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * same type (i.e., DRR_FREE records can only be aggregated with
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * other DRR_FREE records. DRR_FREEOBJECTS records can only be
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * aggregated with other DRR_FREEOBJECTS records.
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt */
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dsp->dsa_pending_op != PENDING_NONE &&
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_pending_op != PENDING_FREE) {
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dump_bytes(dsp, dsp->dsa_drr,
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski sizeof (dmu_replay_record_t)) != 0)
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt return (EINTR);
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_pending_op = PENDING_NONE;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt }
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dsp->dsa_pending_op == PENDING_FREE) {
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt /*
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * There should never be a PENDING_FREE if length is -1
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * (because dump_dnode is the only place where this
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * function is called with a -1, and only after flushing
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * any pending record).
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt */
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt ASSERT(length != -1ULL);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt /*
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * Check to see whether this free block can be aggregated
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * with pending one.
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt */
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt if (drrf->drr_object == object && drrf->drr_offset +
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drrf->drr_length == offset) {
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drrf->drr_length += length;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt return (0);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt } else {
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt /* not a continuation. Push out pending record */
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dump_bytes(dsp, dsp->dsa_drr,
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt sizeof (dmu_replay_record_t)) != 0)
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt return (EINTR);
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_pending_op = PENDING_NONE;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt }
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt }
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt /* create a FREE record and make it pending */
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski bzero(dsp->dsa_drr, sizeof (dmu_replay_record_t));
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_drr->drr_type = DRR_FREE;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drrf->drr_object = object;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drrf->drr_offset = offset;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drrf->drr_length = length;
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski drrf->drr_toguid = dsp->dsa_toguid;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt if (length == -1ULL) {
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dump_bytes(dsp, dsp->dsa_drr,
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski sizeof (dmu_replay_record_t)) != 0)
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt return (EINTR);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt } else {
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_pending_op = PENDING_FREE;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (0);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens}
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrensstatic int
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewskidump_data(dmu_sendarg_t *dsp, dmu_object_type_t type,
8e7144747a94247ce9dbb4fb1f67bdcb666b30d8Lori Alt uint64_t object, uint64_t offset, int blksz, const blkptr_t *bp, void *data)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens{
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski struct drr_write *drrw = &(dsp->dsa_drr->drr_u.drr_write);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt
8e7144747a94247ce9dbb4fb1f67bdcb666b30d8Lori Alt
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt /*
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * If there is any kind of pending aggregation (currently either
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * a grouping of free objects or free blocks), push it out to
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * the stream, since aggregation can't be done across operations
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * of different types.
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt */
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dsp->dsa_pending_op != PENDING_NONE) {
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dump_bytes(dsp, dsp->dsa_drr,
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski sizeof (dmu_replay_record_t)) != 0)
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt return (EINTR);
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_pending_op = PENDING_NONE;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens /* write a DATA record */
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski bzero(dsp->dsa_drr, sizeof (dmu_replay_record_t));
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_drr->drr_type = DRR_WRITE;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drrw->drr_object = object;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drrw->drr_type = type;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drrw->drr_offset = offset;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drrw->drr_length = blksz;
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski drrw->drr_toguid = dsp->dsa_toguid;
8e7144747a94247ce9dbb4fb1f67bdcb666b30d8Lori Alt drrw->drr_checksumtype = BP_GET_CHECKSUM(bp);
8e7144747a94247ce9dbb4fb1f67bdcb666b30d8Lori Alt if (zio_checksum_table[drrw->drr_checksumtype].ci_dedup)
8e7144747a94247ce9dbb4fb1f67bdcb666b30d8Lori Alt drrw->drr_checksumflags |= DRR_CHECKSUM_DEDUP;
8e7144747a94247ce9dbb4fb1f67bdcb666b30d8Lori Alt DDK_SET_LSIZE(&drrw->drr_key, BP_GET_LSIZE(bp));
8e7144747a94247ce9dbb4fb1f67bdcb666b30d8Lori Alt DDK_SET_PSIZE(&drrw->drr_key, BP_GET_PSIZE(bp));
8e7144747a94247ce9dbb4fb1f67bdcb666b30d8Lori Alt DDK_SET_COMPRESS(&drrw->drr_key, BP_GET_COMPRESS(bp));
8e7144747a94247ce9dbb4fb1f67bdcb666b30d8Lori Alt drrw->drr_key.ddk_cksum = bp->blk_cksum;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dump_bytes(dsp, dsp->dsa_drr, sizeof (dmu_replay_record_t)) != 0)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (EINTR);
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dump_bytes(dsp, data, blksz) != 0)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (EINTR);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (0);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens}
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaumstatic int
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewskidump_spill(dmu_sendarg_t *dsp, uint64_t object, int blksz, void *data)
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum{
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski struct drr_spill *drrs = &(dsp->dsa_drr->drr_u.drr_spill);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dsp->dsa_pending_op != PENDING_NONE) {
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dump_bytes(dsp, dsp->dsa_drr,
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski sizeof (dmu_replay_record_t)) != 0)
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum return (EINTR);
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_pending_op = PENDING_NONE;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum }
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum /* write a SPILL record */
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski bzero(dsp->dsa_drr, sizeof (dmu_replay_record_t));
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_drr->drr_type = DRR_SPILL;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum drrs->drr_object = object;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum drrs->drr_length = blksz;
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski drrs->drr_toguid = dsp->dsa_toguid;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dump_bytes(dsp, dsp->dsa_drr, sizeof (dmu_replay_record_t)))
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum return (EINTR);
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dump_bytes(dsp, data, blksz))
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum return (EINTR);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum return (0);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum}
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
efb80947b01107dafbbf0157de0d7e1af6551259ahrensstatic int
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewskidump_freeobjects(dmu_sendarg_t *dsp, uint64_t firstobj, uint64_t numobjs)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens{
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski struct drr_freeobjects *drrfo = &(dsp->dsa_drr->drr_u.drr_freeobjects);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt /*
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * If there is a pending op, but it's not PENDING_FREEOBJECTS,
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * push it out, since free block aggregation can only be done for
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * blocks of the same type (i.e., DRR_FREE records can only be
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * aggregated with other DRR_FREE records. DRR_FREEOBJECTS records
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * can only be aggregated with other DRR_FREEOBJECTS records.
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt */
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dsp->dsa_pending_op != PENDING_NONE &&
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_pending_op != PENDING_FREEOBJECTS) {
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dump_bytes(dsp, dsp->dsa_drr,
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski sizeof (dmu_replay_record_t)) != 0)
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt return (EINTR);
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_pending_op = PENDING_NONE;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt }
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dsp->dsa_pending_op == PENDING_FREEOBJECTS) {
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt /*
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * See whether this free object array can be aggregated
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * with pending one
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt */
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt if (drrfo->drr_firstobj + drrfo->drr_numobjs == firstobj) {
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drrfo->drr_numobjs += numobjs;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt return (0);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt } else {
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt /* can't be aggregated. Push out pending record */
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dump_bytes(dsp, dsp->dsa_drr,
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt sizeof (dmu_replay_record_t)) != 0)
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt return (EINTR);
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_pending_op = PENDING_NONE;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt }
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt }
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt
efb80947b01107dafbbf0157de0d7e1af6551259ahrens /* write a FREEOBJECTS record */
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski bzero(dsp->dsa_drr, sizeof (dmu_replay_record_t));
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_drr->drr_type = DRR_FREEOBJECTS;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drrfo->drr_firstobj = firstobj;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drrfo->drr_numobjs = numobjs;
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski drrfo->drr_toguid = dsp->dsa_toguid;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_pending_op = PENDING_FREEOBJECTS;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (0);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens}
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrensstatic int
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewskidump_dnode(dmu_sendarg_t *dsp, uint64_t object, dnode_phys_t *dnp)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens{
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski struct drr_object *drro = &(dsp->dsa_drr->drr_u.drr_object);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (dnp == NULL || dnp->dn_type == DMU_OT_NONE)
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski return (dump_freeobjects(dsp, object, 1));
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dsp->dsa_pending_op != PENDING_NONE) {
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dump_bytes(dsp, dsp->dsa_drr,
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski sizeof (dmu_replay_record_t)) != 0)
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt return (EINTR);
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_pending_op = PENDING_NONE;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt }
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt
efb80947b01107dafbbf0157de0d7e1af6551259ahrens /* write an OBJECT record */
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski bzero(dsp->dsa_drr, sizeof (dmu_replay_record_t));
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_drr->drr_type = DRR_OBJECT;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drro->drr_object = object;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drro->drr_type = dnp->dn_type;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drro->drr_bonustype = dnp->dn_bonustype;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drro->drr_blksz = dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drro->drr_bonuslen = dnp->dn_bonuslen;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drro->drr_checksumtype = dnp->dn_checksum;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drro->drr_compress = dnp->dn_compress;
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski drro->drr_toguid = dsp->dsa_toguid;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dump_bytes(dsp, dsp->dsa_drr, sizeof (dmu_replay_record_t)) != 0)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (EINTR);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dump_bytes(dsp, DN_BONUS(dnp), P2ROUNDUP(dnp->dn_bonuslen, 8)) != 0)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (EINTR);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens /* free anything past the end of the file */
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dump_free(dsp, object, (dnp->dn_maxblkid + 1) *
efb80947b01107dafbbf0157de0d7e1af6551259ahrens (dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT), -1ULL))
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (EINTR);
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dsp->dsa_err)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (EINTR);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (0);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens}
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens#define BP_SPAN(dnp, level) \
efb80947b01107dafbbf0157de0d7e1af6551259ahrens (((uint64_t)dnp->dn_datablkszsec) << (SPA_MINBLOCKSHIFT + \
efb80947b01107dafbbf0157de0d7e1af6551259ahrens (level) * (dnp->dn_indblkshift - SPA_BLKPTRSHIFT)))
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick/* ARGSUSED */
efb80947b01107dafbbf0157de0d7e1af6551259ahrensstatic int
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Lingbackup_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, arc_buf_t *pbuf,
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens{
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dmu_sendarg_t *dsp = arg;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens dmu_object_type_t type = bp ? BP_GET_TYPE(bp) : DMU_OT_NONE;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens int err = 0;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (issig(JUSTLOOKING) && issig(FORREAL))
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (EINTR);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick if (zb->zb_object != DMU_META_DNODE_OBJECT &&
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick DMU_OBJECT_IS_SPECIAL(zb->zb_object)) {
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens return (0);
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick } else if (bp == NULL && zb->zb_object == DMU_META_DNODE_OBJECT) {
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens uint64_t span = BP_SPAN(dnp, zb->zb_level);
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens uint64_t dnobj = (zb->zb_blkid * span) >> DNODE_SHIFT;
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski err = dump_freeobjects(dsp, dnobj, span >> DNODE_SHIFT);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens } else if (bp == NULL) {
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens uint64_t span = BP_SPAN(dnp, zb->zb_level);
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski err = dump_free(dsp, zb->zb_object, zb->zb_blkid * span, span);
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens } else if (zb->zb_level > 0 || type == DMU_OT_OBJSET) {
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens return (0);
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens } else if (type == DMU_OT_DNODE) {
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens dnode_phys_t *blk;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens int i;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens int blksz = BP_GET_LSIZE(bp);
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens uint32_t aflags = ARC_WAIT;
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens arc_buf_t *abuf;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling if (dsl_read(NULL, spa, bp, pbuf,
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens arc_getbuf_func, &abuf, ZIO_PRIORITY_ASYNC_READ,
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens ZIO_FLAG_CANFAIL, &aflags, zb) != 0)
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens return (EIO);
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens blk = abuf->b_data;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens for (i = 0; i < blksz >> DNODE_SHIFT; i++) {
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens uint64_t dnobj = (zb->zb_blkid <<
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens (DNODE_BLOCK_SHIFT - DNODE_SHIFT)) + i;
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski err = dump_dnode(dsp, dnobj, blk+i);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (err)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens break;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens (void) arc_buf_remove_ref(abuf, &abuf);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum } else if (type == DMU_OT_SA) {
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum uint32_t aflags = ARC_WAIT;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum arc_buf_t *abuf;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum int blksz = BP_GET_LSIZE(bp);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum if (arc_read_nolock(NULL, spa, bp,
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum arc_getbuf_func, &abuf, ZIO_PRIORITY_ASYNC_READ,
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum ZIO_FLAG_CANFAIL, &aflags, zb) != 0)
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum return (EIO);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski err = dump_spill(dsp, zb->zb_object, blksz, abuf->b_data);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum (void) arc_buf_remove_ref(abuf, &abuf);
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens } else { /* it's a level-0 block of a regular object */
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens uint32_t aflags = ARC_WAIT;
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens arc_buf_t *abuf;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens int blksz = BP_GET_LSIZE(bp);
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling if (dsl_read(NULL, spa, bp, pbuf,
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens arc_getbuf_func, &abuf, ZIO_PRIORITY_ASYNC_READ,
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens ZIO_FLAG_CANFAIL, &aflags, zb) != 0) {
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens if (zfs_send_corrupt_data) {
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens /* Send a block filled with 0x"zfs badd bloc" */
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens abuf = arc_buf_alloc(spa, blksz, &abuf,
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens ARC_BUFC_DATA);
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens uint64_t *ptr;
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens for (ptr = abuf->b_data;
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens (char *)ptr < (char *)abuf->b_data + blksz;
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens ptr++)
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens *ptr = 0x2f5baddb10c;
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens } else {
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens return (EIO);
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens }
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens }
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski err = dump_data(dsp, type, zb->zb_object, zb->zb_blkid * blksz,
8e7144747a94247ce9dbb4fb1f67bdcb666b30d8Lori Alt blksz, bp, abuf->b_data);
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens (void) arc_buf_remove_ref(abuf, &abuf);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens ASSERT(err == 0 || err == EINTR);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (err);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens}
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrensint
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewskidmu_send(objset_t *tosnap, objset_t *fromsnap, boolean_t fromorigin,
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski int outfd, vnode_t *vp, offset_t *off)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens{
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens dsl_dataset_t *ds = tosnap->os_dsl_dataset;
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens dsl_dataset_t *fromds = fromsnap ? fromsnap->os_dsl_dataset : NULL;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens dmu_replay_record_t *drr;
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dmu_sendarg_t *dsp;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens int err;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens uint64_t fromtxg = 0;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens /* tosnap must be a snapshot */
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (ds->ds_phys->ds_next_snap_obj == 0)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (EINVAL);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens /* fromsnap must be an earlier snapshot from the same fs as tosnap */
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (fromds && (ds->ds_dir != fromds->ds_dir ||
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens fromds->ds_phys->ds_creation_txg >= ds->ds_phys->ds_creation_txg))
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (EXDEV);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens if (fromorigin) {
088f389458728c464569a5506b58070254fa4f7dahrens dsl_pool_t *dp = ds->ds_dir->dd_pool;
088f389458728c464569a5506b58070254fa4f7dahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens if (fromsnap)
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens return (EINVAL);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
088f389458728c464569a5506b58070254fa4f7dahrens if (dsl_dir_is_clone(ds->ds_dir)) {
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens rw_enter(&dp->dp_config_rwlock, RW_READER);
745cd3c5371d020efae7a911c58c526aa1fd0dbamaybee err = dsl_dataset_hold_obj(dp,
745cd3c5371d020efae7a911c58c526aa1fd0dbamaybee ds->ds_dir->dd_phys->dd_origin_obj, FTAG, &fromds);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens rw_exit(&dp->dp_config_rwlock);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens if (err)
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens return (err);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens } else {
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens fromorigin = B_FALSE;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens }
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens }
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drr = kmem_zalloc(sizeof (dmu_replay_record_t), KM_SLEEP);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drr->drr_type = DRR_BEGIN;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drr->drr_u.drr_begin.drr_magic = DMU_BACKUP_MAGIC;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt DMU_SET_STREAM_HDRTYPE(drr->drr_u.drr_begin.drr_versioninfo,
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt DMU_SUBSTREAM);
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum#ifdef _KERNEL
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum if (dmu_objset_type(tosnap) == DMU_OST_ZFS) {
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum uint64_t version;
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (zfs_get_zplprop(tosnap, ZFS_PROP_VERSION, &version) != 0) {
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski kmem_free(drr, sizeof (dmu_replay_record_t));
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum return (EINVAL);
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski }
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum if (version == ZPL_VERSION_SA) {
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum DMU_SET_FEATUREFLAGS(
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum drr->drr_u.drr_begin.drr_versioninfo,
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum DMU_BACKUP_FEATURE_SA_SPILL);
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum }
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum }
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum#endif
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drr->drr_u.drr_begin.drr_creation_time =
efb80947b01107dafbbf0157de0d7e1af6551259ahrens ds->ds_phys->ds_creation_time;
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens drr->drr_u.drr_begin.drr_type = tosnap->os_phys->os_type;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens if (fromorigin)
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens drr->drr_u.drr_begin.drr_flags |= DRR_FLAG_CLONE;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drr->drr_u.drr_begin.drr_toguid = ds->ds_phys->ds_guid;
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh if (ds->ds_phys->ds_flags & DS_FLAG_CI_DATASET)
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh drr->drr_u.drr_begin.drr_flags |= DRR_FLAG_CI_DATA;
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (fromds)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drr->drr_u.drr_begin.drr_fromguid = fromds->ds_phys->ds_guid;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens dsl_dataset_name(ds, drr->drr_u.drr_begin.drr_toname);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens if (fromds)
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens fromtxg = fromds->ds_phys->ds_creation_txg;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens if (fromorigin)
745cd3c5371d020efae7a911c58c526aa1fd0dbamaybee dsl_dataset_rele(fromds, FTAG);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp = kmem_zalloc(sizeof (dmu_sendarg_t), KM_SLEEP);
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_drr = drr;
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_vp = vp;
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_outfd = outfd;
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_proc = curproc;
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_os = tosnap;
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_off = off;
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_toguid = ds->ds_phys->ds_guid;
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski ZIO_SET_CHECKSUM(&dsp->dsa_zc, 0, 0, 0, 0);
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski dsp->dsa_pending_op = PENDING_NONE;
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski mutex_enter(&ds->ds_sendstream_lock);
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski list_insert_head(&ds->ds_sendstreams, dsp);
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski mutex_exit(&ds->ds_sendstream_lock);
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dump_bytes(dsp, drr, sizeof (dmu_replay_record_t)) != 0) {
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski err = dsp->dsa_err;
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski goto out;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
88b7b0f29b20b808b9e06071885b1d6a3ddb6328Matthew Ahrens err = traverse_dataset(ds, fromtxg, TRAVERSE_PRE | TRAVERSE_PREFETCH,
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski backup_cb, dsp);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dsp->dsa_pending_op != PENDING_NONE)
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dump_bytes(dsp, drr, sizeof (dmu_replay_record_t)) != 0)
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt err = EINTR;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (err) {
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (err == EINTR && dsp->dsa_err)
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski err = dsp->dsa_err;
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski goto out;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens bzero(drr, sizeof (dmu_replay_record_t));
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drr->drr_type = DRR_END;
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski drr->drr_u.drr_end.drr_checksum = dsp->dsa_zc;
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski drr->drr_u.drr_end.drr_toguid = dsp->dsa_toguid;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski if (dump_bytes(dsp, drr, sizeof (dmu_replay_record_t)) != 0) {
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski err = dsp->dsa_err;
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski goto out;
7b5309bba99e6b16a38c04114a3a6003c94ffe81gw }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewskiout:
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski mutex_enter(&ds->ds_sendstream_lock);
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski list_remove(&ds->ds_sendstreams, dsp);
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski mutex_exit(&ds->ds_sendstream_lock);
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski
efb80947b01107dafbbf0157de0d7e1af6551259ahrens kmem_free(drr, sizeof (dmu_replay_record_t));
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski kmem_free(dsp, sizeof (dmu_sendarg_t));
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
4e3c9f4489a18514e5e8caeb91d4e6db07c98415Bill Pijewski return (err);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens}
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrensint
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrensdmu_send_estimate(objset_t *tosnap, objset_t *fromsnap, boolean_t fromorigin,
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens uint64_t *sizep)
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens{
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens dsl_dataset_t *ds = tosnap->os_dsl_dataset;
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens dsl_dataset_t *fromds = fromsnap ? fromsnap->os_dsl_dataset : NULL;
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens dsl_pool_t *dp = ds->ds_dir->dd_pool;
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens int err;
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens uint64_t size;
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens /* tosnap must be a snapshot */
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens if (ds->ds_phys->ds_next_snap_obj == 0)
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens return (EINVAL);
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens /* fromsnap must be an earlier snapshot from the same fs as tosnap */
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens if (fromds && (ds->ds_dir != fromds->ds_dir ||
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens fromds->ds_phys->ds_creation_txg >= ds->ds_phys->ds_creation_txg))
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens return (EXDEV);
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens if (fromorigin) {
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens if (fromsnap)
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens return (EINVAL);
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens if (dsl_dir_is_clone(ds->ds_dir)) {
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens rw_enter(&dp->dp_config_rwlock, RW_READER);
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens err = dsl_dataset_hold_obj(dp,
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens ds->ds_dir->dd_phys->dd_origin_obj, FTAG, &fromds);
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens rw_exit(&dp->dp_config_rwlock);
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens if (err)
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens return (err);
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens } else {
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens fromorigin = B_FALSE;
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens }
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens }
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens /* Get uncompressed size estimate of changed data. */
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens if (fromds == NULL) {
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens size = ds->ds_phys->ds_uncompressed_bytes;
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens } else {
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens uint64_t used, comp;
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens err = dsl_dataset_space_written(fromds, ds,
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens &used, &comp, &size);
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens if (fromorigin)
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens dsl_dataset_rele(fromds, FTAG);
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens if (err)
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens return (err);
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens }
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens /*
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens * Assume that space (both on-disk and in-stream) is dominated by
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens * data. We will adjust for indirect blocks and the copies property,
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens * but ignore per-object space used (eg, dnodes and DRR_OBJECT records).
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens */
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens /*
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens * Subtract out approximate space used by indirect blocks.
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens * Assume most space is used by data blocks (non-indirect, non-dnode).
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens * Assume all blocks are recordsize. Assume ditto blocks and
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens * internal fragmentation counter out compression.
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens *
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens * Therefore, space used by indirect blocks is sizeof(blkptr_t) per
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens * block, which we observe in practice.
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens */
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens uint64_t recordsize;
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens rw_enter(&dp->dp_config_rwlock, RW_READER);
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens err = dsl_prop_get_ds(ds, "recordsize",
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens sizeof (recordsize), 1, &recordsize, NULL);
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens rw_exit(&dp->dp_config_rwlock);
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens if (err)
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens return (err);
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens size -= size / recordsize * sizeof (blkptr_t);
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens /* Add in the space for the record associated with each block. */
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens size += size / recordsize * sizeof (dmu_replay_record_t);
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens *sizep = size;
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens return (0);
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens}
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrensstruct recvbeginsyncarg {
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens const char *tofs;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens const char *tosnap;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens dsl_dataset_t *origin;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens uint64_t fromguid;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens dmu_objset_type_t type;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens void *tag;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens boolean_t force;
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh uint64_t dsflags;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens char clonelastname[MAXNAMELEN];
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens dsl_dataset_t *ds; /* the ds to recv into; returned from the syncfunc */
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling cred_t *cr;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens};
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens/* ARGSUSED */
efb80947b01107dafbbf0157de0d7e1af6551259ahrensstatic int
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrensrecv_new_check(void *arg1, void *arg2, dmu_tx_t *tx)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens{
efb80947b01107dafbbf0157de0d7e1af6551259ahrens dsl_dir_t *dd = arg1;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens struct recvbeginsyncarg *rbsa = arg2;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens objset_t *mos = dd->dd_pool->dp_meta_objset;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens uint64_t val;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens int err;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens err = zap_lookup(mos, dd->dd_phys->dd_child_dir_zapobj,
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens strrchr(rbsa->tofs, '/') + 1, sizeof (uint64_t), 1, &val);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (err != ENOENT)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (err ? err : EEXIST);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens if (rbsa->origin) {
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens /* make sure it's a snap in the same pool */
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens if (rbsa->origin->ds_dir->dd_pool != dd->dd_pool)
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens return (EXDEV);
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens if (!dsl_dataset_is_snapshot(rbsa->origin))
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens return (EINVAL);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens if (rbsa->origin->ds_phys->ds_guid != rbsa->fromguid)
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens return (ENODEV);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens }
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (0);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens}
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrensstatic void
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Lingrecv_new_sync(void *arg1, void *arg2, dmu_tx_t *tx)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens{
efb80947b01107dafbbf0157de0d7e1af6551259ahrens dsl_dir_t *dd = arg1;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens struct recvbeginsyncarg *rbsa = arg2;
745cd3c5371d020efae7a911c58c526aa1fd0dbamaybee uint64_t flags = DS_FLAG_INCONSISTENT | rbsa->dsflags;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens uint64_t dsobj;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens /* Create and open new dataset. */
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens dsobj = dsl_dataset_create_sync(dd, strrchr(rbsa->tofs, '/') + 1,
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling rbsa->origin, flags, rbsa->cr, tx);
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens VERIFY(0 == dsl_dataset_own_obj(dd->dd_pool, dsobj,
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens B_TRUE, dmu_recv_tag, &rbsa->ds));
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens if (rbsa->origin == NULL) {
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens (void) dmu_objset_create_impl(dd->dd_pool->dp_spa,
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens rbsa->ds, &rbsa->ds->ds_phys->ds_bp, rbsa->type, tx);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling spa_history_log_internal(LOG_DS_REPLAY_FULL_SYNC,
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling dd->dd_pool->dp_spa, tx, "dataset = %lld", dsobj);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens}
f18faf3f3e5def85fdfff681617d227703ace2adek
f18faf3f3e5def85fdfff681617d227703ace2adek/* ARGSUSED */
f18faf3f3e5def85fdfff681617d227703ace2adekstatic int
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrensrecv_existing_check(void *arg1, void *arg2, dmu_tx_t *tx)
f18faf3f3e5def85fdfff681617d227703ace2adek{
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens dsl_dataset_t *ds = arg1;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens struct recvbeginsyncarg *rbsa = arg2;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens int err;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens uint64_t val;
f18faf3f3e5def85fdfff681617d227703ace2adek
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens /* must not have any changes since most recent snapshot */
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens if (!rbsa->force && dsl_dataset_modified_since_lastsnap(ds))
f18faf3f3e5def85fdfff681617d227703ace2adek return (ETXTBSY);
f18faf3f3e5def85fdfff681617d227703ace2adek
feaa74e41c407fe56e66a47e097c2842d4f65b9fMark Maybee /* new snapshot name must not exist */
feaa74e41c407fe56e66a47e097c2842d4f65b9fMark Maybee err = zap_lookup(ds->ds_dir->dd_pool->dp_meta_objset,
feaa74e41c407fe56e66a47e097c2842d4f65b9fMark Maybee ds->ds_phys->ds_snapnames_zapobj, rbsa->tosnap, 8, 1, &val);
feaa74e41c407fe56e66a47e097c2842d4f65b9fMark Maybee if (err == 0)
feaa74e41c407fe56e66a47e097c2842d4f65b9fMark Maybee return (EEXIST);
feaa74e41c407fe56e66a47e097c2842d4f65b9fMark Maybee if (err != ENOENT)
feaa74e41c407fe56e66a47e097c2842d4f65b9fMark Maybee return (err);
feaa74e41c407fe56e66a47e097c2842d4f65b9fMark Maybee
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens if (rbsa->fromguid) {
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens /* if incremental, most recent snapshot must match fromguid */
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens if (ds->ds_prev == NULL)
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens return (ENODEV);
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson /*
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson * most recent snapshot must match fromguid, or there are no
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson * changes since the fromguid one
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson */
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson if (ds->ds_prev->ds_phys->ds_guid != rbsa->fromguid) {
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson uint64_t birth = ds->ds_prev->ds_phys->ds_bp.blk_birth;
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson uint64_t obj = ds->ds_prev->ds_phys->ds_prev_snap_obj;
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson while (obj != 0) {
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson dsl_dataset_t *snap;
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson err = dsl_dataset_hold_obj(ds->ds_dir->dd_pool,
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson obj, FTAG, &snap);
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson if (err)
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson return (ENODEV);
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson if (snap->ds_phys->ds_creation_txg < birth) {
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson dsl_dataset_rele(snap, FTAG);
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson return (ENODEV);
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson }
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson if (snap->ds_phys->ds_guid == rbsa->fromguid) {
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson dsl_dataset_rele(snap, FTAG);
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson break; /* it's ok */
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson }
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson obj = snap->ds_phys->ds_prev_snap_obj;
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson dsl_dataset_rele(snap, FTAG);
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson }
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson if (obj == 0)
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson return (ENODEV);
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson }
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens } else {
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens /* if full, most recent snapshot must be $ORIGIN */
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens if (ds->ds_phys->ds_prev_snap_txg >= TXG_INITIAL)
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens return (ENODEV);
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens }
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
47f263f4211a47222fcc65b18b0cfa06d33f3c33ek /* temporary clone name must not exist */
47f263f4211a47222fcc65b18b0cfa06d33f3c33ek err = zap_lookup(ds->ds_dir->dd_pool->dp_meta_objset,
47f263f4211a47222fcc65b18b0cfa06d33f3c33ek ds->ds_dir->dd_phys->dd_child_dir_zapobj,
47f263f4211a47222fcc65b18b0cfa06d33f3c33ek rbsa->clonelastname, 8, 1, &val);
47f263f4211a47222fcc65b18b0cfa06d33f3c33ek if (err == 0)
47f263f4211a47222fcc65b18b0cfa06d33f3c33ek return (EEXIST);
47f263f4211a47222fcc65b18b0cfa06d33f3c33ek if (err != ENOENT)
47f263f4211a47222fcc65b18b0cfa06d33f3c33ek return (err);
47f263f4211a47222fcc65b18b0cfa06d33f3c33ek
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens return (0);
f18faf3f3e5def85fdfff681617d227703ace2adek}
f18faf3f3e5def85fdfff681617d227703ace2adek
f18faf3f3e5def85fdfff681617d227703ace2adek/* ARGSUSED */
f18faf3f3e5def85fdfff681617d227703ace2adekstatic void
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Lingrecv_existing_sync(void *arg1, void *arg2, dmu_tx_t *tx)
f18faf3f3e5def85fdfff681617d227703ace2adek{
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens dsl_dataset_t *ohds = arg1;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens struct recvbeginsyncarg *rbsa = arg2;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens dsl_pool_t *dp = ohds->ds_dir->dd_pool;
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens dsl_dataset_t *cds;
745cd3c5371d020efae7a911c58c526aa1fd0dbamaybee uint64_t flags = DS_FLAG_INCONSISTENT | rbsa->dsflags;
f18faf3f3e5def85fdfff681617d227703ace2adek uint64_t dsobj;
f18faf3f3e5def85fdfff681617d227703ace2adek
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens /* create and open the temporary clone */
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens dsobj = dsl_dataset_create_sync(ohds->ds_dir, rbsa->clonelastname,
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling ohds->ds_prev, flags, rbsa->cr, tx);
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens VERIFY(0 == dsl_dataset_own_obj(dp, dsobj, B_TRUE, dmu_recv_tag, &cds));
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens /*
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens * If we actually created a non-clone, we need to create the
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens * objset in our new dataset.
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens */
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens if (BP_IS_HOLE(dsl_dataset_get_blkptr(cds))) {
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens (void) dmu_objset_create_impl(dp->dp_spa,
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens cds, dsl_dataset_get_blkptr(cds), rbsa->type, tx);
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens }
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens rbsa->ds = cds;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling spa_history_log_internal(LOG_DS_REPLAY_INC_SYNC,
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling dp->dp_spa, tx, "dataset = %lld", dsobj);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens}
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaumstatic boolean_t
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaumdmu_recv_verify_features(dsl_dataset_t *ds, struct drr_begin *drrb)
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum{
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum int featureflags;
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum featureflags = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo);
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum /* Verify pool version supports SA if SA_SPILL feature set */
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum return ((featureflags & DMU_BACKUP_FEATURE_SA_SPILL) &&
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum (spa_version(dsl_dataset_get_spa(ds)) < SPA_VERSION_SA));
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum}
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens/*
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens * NB: callers *MUST* call dmu_recv_stream() if dmu_recv_begin()
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens * succeeds; otherwise we will leak the holds on the datasets.
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens */
3cb34c601f3ef3016f638574f5982e80c3735c71ahrensint
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Altdmu_recv_begin(char *tofs, char *tosnap, char *top_ds, struct drr_begin *drrb,
f4b94bde302dc950da6b4ec29936dd9a7b9d61abMatthew Ahrens boolean_t force, objset_t *origin, dmu_recv_cookie_t *drc)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens{
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens int err = 0;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens boolean_t byteswap;
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens struct recvbeginsyncarg rbsa = { 0 };
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt uint64_t versioninfo;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens int flags;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens dsl_dataset_t *ds;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens if (drrb->drr_magic == DMU_BACKUP_MAGIC)
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens byteswap = FALSE;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens else if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC))
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens byteswap = TRUE;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens else
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens return (EINVAL);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens rbsa.tofs = tofs;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens rbsa.tosnap = tosnap;
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens rbsa.origin = origin ? origin->os_dsl_dataset : NULL;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens rbsa.fromguid = drrb->drr_fromguid;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens rbsa.type = drrb->drr_type;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens rbsa.tag = FTAG;
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh rbsa.dsflags = 0;
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling rbsa.cr = CRED();
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt versioninfo = drrb->drr_versioninfo;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens flags = drrb->drr_flags;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens if (byteswap) {
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens rbsa.type = BSWAP_32(rbsa.type);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens rbsa.fromguid = BSWAP_64(rbsa.fromguid);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt versioninfo = BSWAP_64(versioninfo);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens flags = BSWAP_32(flags);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt if (DMU_GET_STREAM_HDRTYPE(versioninfo) == DMU_COMPOUNDSTREAM ||
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens rbsa.type >= DMU_OST_NUMTYPES ||
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens ((flags & DRR_FLAG_CLONE) && origin == NULL))
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (EINVAL);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh if (flags & DRR_FLAG_CI_DATA)
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh rbsa.dsflags = DS_FLAG_CI_DATASET;
ab04eb8ef60d9dc9614d6cccffc474f24ca1d162timh
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens bzero(drc, sizeof (dmu_recv_cookie_t));
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens drc->drc_drrb = drrb;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens drc->drc_tosnap = tosnap;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drc->drc_top_ds = top_ds;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens drc->drc_force = force;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens /*
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens * Process the begin in syncing context.
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens */
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens /* open the dataset we are logically receiving into */
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens err = dsl_dataset_hold(tofs, dmu_recv_tag, &ds);
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens if (err == 0) {
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum if (dmu_recv_verify_features(ds, drrb)) {
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum dsl_dataset_rele(ds, dmu_recv_tag);
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum return (ENOTSUP);
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum }
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens /* target fs already exists; recv into temp clone */
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens /* Can't recv a clone into an existing fs */
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens if (flags & DRR_FLAG_CLONE) {
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens dsl_dataset_rele(ds, dmu_recv_tag);
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens return (EINVAL);
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
f4b94bde302dc950da6b4ec29936dd9a7b9d61abMatthew Ahrens /* must not have an incremental recv already in progress */
f4b94bde302dc950da6b4ec29936dd9a7b9d61abMatthew Ahrens if (!mutex_tryenter(&ds->ds_recvlock)) {
f4b94bde302dc950da6b4ec29936dd9a7b9d61abMatthew Ahrens dsl_dataset_rele(ds, dmu_recv_tag);
f4b94bde302dc950da6b4ec29936dd9a7b9d61abMatthew Ahrens return (EBUSY);
f4b94bde302dc950da6b4ec29936dd9a7b9d61abMatthew Ahrens }
f4b94bde302dc950da6b4ec29936dd9a7b9d61abMatthew Ahrens
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens /* tmp clone name is: tofs/%tosnap" */
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens (void) snprintf(rbsa.clonelastname, sizeof (rbsa.clonelastname),
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens "%%%s", tosnap);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens rbsa.force = force;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens err = dsl_sync_task_do(ds->ds_dir->dd_pool,
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens recv_existing_check, recv_existing_sync, ds, &rbsa, 5);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens if (err) {
f4b94bde302dc950da6b4ec29936dd9a7b9d61abMatthew Ahrens mutex_exit(&ds->ds_recvlock);
745cd3c5371d020efae7a911c58c526aa1fd0dbamaybee dsl_dataset_rele(ds, dmu_recv_tag);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens return (err);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens }
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens drc->drc_logical_ds = ds;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens drc->drc_real_ds = rbsa.ds;
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens } else if (err == ENOENT) {
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens /* target fs does not exist; must be a full backup or clone */
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens char *cp;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens /*
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens * If it's a non-clone incremental, we are missing the
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens * target fs, so fail the recv.
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens */
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens if (rbsa.fromguid && !(flags & DRR_FLAG_CLONE))
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens return (ENOENT);
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens /* Open the parent of tofs */
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens cp = strrchr(tofs, '/');
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens *cp = '\0';
bdd1c119a2da4c25e7b3d9db5c432fd4925e3b0eChris Kirby err = dsl_dataset_hold(tofs, FTAG, &ds);
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens *cp = '/';
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens if (err)
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens return (err);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum if (dmu_recv_verify_features(ds, drrb)) {
8fe33373116e19bc6a8605d999e17e0dbbe0fea7Matthew Ahrens dsl_dataset_rele(ds, FTAG);
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum return (ENOTSUP);
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum }
dc7cd546d81fce970935f08099931c2ad2d57731Mark Shellenbaum
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens err = dsl_sync_task_do(ds->ds_dir->dd_pool,
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens recv_new_check, recv_new_sync, ds->ds_dir, &rbsa, 5);
bdd1c119a2da4c25e7b3d9db5c432fd4925e3b0eChris Kirby dsl_dataset_rele(ds, FTAG);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens if (err)
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens return (err);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens drc->drc_logical_ds = drc->drc_real_ds = rbsa.ds;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens drc->drc_newfs = B_TRUE;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens }
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens return (err);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens}
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrensstruct restorearg {
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens int err;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens int byteswap;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens vnode_t *vp;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens char *buf;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens uint64_t voff;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens int bufsize; /* amount of memory allocated for buf */
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens zio_cksum_t cksum;
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby avl_tree_t *guid_to_ds_map;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens};
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alttypedef struct guid_map_entry {
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt uint64_t guid;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt dsl_dataset_t *gme_ds;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt avl_node_t avlnode;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt} guid_map_entry_t;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Altstatic int
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Altguid_compare(const void *arg1, const void *arg2)
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt{
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt const guid_map_entry_t *gmep1 = arg1;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt const guid_map_entry_t *gmep2 = arg2;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt if (gmep1->guid < gmep2->guid)
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt return (-1);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt else if (gmep1->guid > gmep2->guid)
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt return (1);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt return (0);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt}
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirbystatic void
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirbyfree_guid_map_onexit(void *arg)
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby{
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby avl_tree_t *ca = arg;
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby void *cookie = NULL;
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby guid_map_entry_t *gmep;
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby while ((gmep = avl_destroy_nodes(ca, &cookie)) != NULL) {
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby dsl_dataset_rele(gmep->gme_ds, ca);
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby kmem_free(gmep, sizeof (guid_map_entry_t));
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby }
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby avl_destroy(ca);
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby kmem_free(ca, sizeof (avl_tree_t));
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby}
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby
efb80947b01107dafbbf0157de0d7e1af6551259ahrensstatic void *
efb80947b01107dafbbf0157de0d7e1af6551259ahrensrestore_read(struct restorearg *ra, int len)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens{
efb80947b01107dafbbf0157de0d7e1af6551259ahrens void *rv;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens int done = 0;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens /* some things will require 8-byte alignment, so everything must */
efb80947b01107dafbbf0157de0d7e1af6551259ahrens ASSERT3U(len % 8, ==, 0);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens while (done < len) {
efb80947b01107dafbbf0157de0d7e1af6551259ahrens ssize_t resid;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens ra->err = vn_rdwr(UIO_READ, ra->vp,
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens (caddr_t)ra->buf + done, len - done,
efb80947b01107dafbbf0157de0d7e1af6551259ahrens ra->voff, UIO_SYSSPACE, FAPPEND,
efb80947b01107dafbbf0157de0d7e1af6551259ahrens RLIM64_INFINITY, CRED(), &resid);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens if (resid == len - done)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens ra->err = EINVAL;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens ra->voff += len - done - resid;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens done = len - resid;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (ra->err)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (NULL);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens ASSERT3U(done, ==, len);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens rv = ra->buf;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (ra->byteswap)
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens fletcher_4_incremental_byteswap(rv, len, &ra->cksum);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens else
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens fletcher_4_incremental_native(rv, len, &ra->cksum);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (rv);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens}
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrensstatic void
efb80947b01107dafbbf0157de0d7e1af6551259ahrensbackup_byteswap(dmu_replay_record_t *drr)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens{
efb80947b01107dafbbf0157de0d7e1af6551259ahrens#define DO64(X) (drr->drr_u.X = BSWAP_64(drr->drr_u.X))
efb80947b01107dafbbf0157de0d7e1af6551259ahrens#define DO32(X) (drr->drr_u.X = BSWAP_32(drr->drr_u.X))
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drr->drr_type = BSWAP_32(drr->drr_type);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens drr->drr_payloadlen = BSWAP_32(drr->drr_payloadlen);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens switch (drr->drr_type) {
efb80947b01107dafbbf0157de0d7e1af6551259ahrens case DRR_BEGIN:
efb80947b01107dafbbf0157de0d7e1af6551259ahrens DO64(drr_begin.drr_magic);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt DO64(drr_begin.drr_versioninfo);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens DO64(drr_begin.drr_creation_time);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens DO32(drr_begin.drr_type);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens DO32(drr_begin.drr_flags);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens DO64(drr_begin.drr_toguid);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens DO64(drr_begin.drr_fromguid);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens break;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens case DRR_OBJECT:
efb80947b01107dafbbf0157de0d7e1af6551259ahrens DO64(drr_object.drr_object);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens /* DO64(drr_object.drr_allocation_txg); */
efb80947b01107dafbbf0157de0d7e1af6551259ahrens DO32(drr_object.drr_type);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens DO32(drr_object.drr_bonustype);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens DO32(drr_object.drr_blksz);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens DO32(drr_object.drr_bonuslen);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt DO64(drr_object.drr_toguid);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens break;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens case DRR_FREEOBJECTS:
efb80947b01107dafbbf0157de0d7e1af6551259ahrens DO64(drr_freeobjects.drr_firstobj);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens DO64(drr_freeobjects.drr_numobjs);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt DO64(drr_freeobjects.drr_toguid);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens break;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens case DRR_WRITE:
efb80947b01107dafbbf0157de0d7e1af6551259ahrens DO64(drr_write.drr_object);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens DO32(drr_write.drr_type);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens DO64(drr_write.drr_offset);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens DO64(drr_write.drr_length);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt DO64(drr_write.drr_toguid);
8e7144747a94247ce9dbb4fb1f67bdcb666b30d8Lori Alt DO64(drr_write.drr_key.ddk_cksum.zc_word[0]);
8e7144747a94247ce9dbb4fb1f67bdcb666b30d8Lori Alt DO64(drr_write.drr_key.ddk_cksum.zc_word[1]);
8e7144747a94247ce9dbb4fb1f67bdcb666b30d8Lori Alt DO64(drr_write.drr_key.ddk_cksum.zc_word[2]);
8e7144747a94247ce9dbb4fb1f67bdcb666b30d8Lori Alt DO64(drr_write.drr_key.ddk_cksum.zc_word[3]);
8e7144747a94247ce9dbb4fb1f67bdcb666b30d8Lori Alt DO64(drr_write.drr_key.ddk_prop);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt break;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt case DRR_WRITE_BYREF:
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt DO64(drr_write_byref.drr_object);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt DO64(drr_write_byref.drr_offset);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt DO64(drr_write_byref.drr_length);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt DO64(drr_write_byref.drr_toguid);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt DO64(drr_write_byref.drr_refguid);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt DO64(drr_write_byref.drr_refobject);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt DO64(drr_write_byref.drr_refoffset);
8e7144747a94247ce9dbb4fb1f67bdcb666b30d8Lori Alt DO64(drr_write_byref.drr_key.ddk_cksum.zc_word[0]);
8e7144747a94247ce9dbb4fb1f67bdcb666b30d8Lori Alt DO64(drr_write_byref.drr_key.ddk_cksum.zc_word[1]);
8e7144747a94247ce9dbb4fb1f67bdcb666b30d8Lori Alt DO64(drr_write_byref.drr_key.ddk_cksum.zc_word[2]);
8e7144747a94247ce9dbb4fb1f67bdcb666b30d8Lori Alt DO64(drr_write_byref.drr_key.ddk_cksum.zc_word[3]);
8e7144747a94247ce9dbb4fb1f67bdcb666b30d8Lori Alt DO64(drr_write_byref.drr_key.ddk_prop);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens break;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens case DRR_FREE:
efb80947b01107dafbbf0157de0d7e1af6551259ahrens DO64(drr_free.drr_object);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens DO64(drr_free.drr_offset);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens DO64(drr_free.drr_length);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt DO64(drr_free.drr_toguid);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens break;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum case DRR_SPILL:
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum DO64(drr_spill.drr_object);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum DO64(drr_spill.drr_length);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum DO64(drr_spill.drr_toguid);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum break;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens case DRR_END:
efb80947b01107dafbbf0157de0d7e1af6551259ahrens DO64(drr_end.drr_checksum.zc_word[0]);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens DO64(drr_end.drr_checksum.zc_word[1]);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens DO64(drr_end.drr_checksum.zc_word[2]);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens DO64(drr_end.drr_checksum.zc_word[3]);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt DO64(drr_end.drr_toguid);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens break;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens#undef DO64
efb80947b01107dafbbf0157de0d7e1af6551259ahrens#undef DO32
efb80947b01107dafbbf0157de0d7e1af6551259ahrens}
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrensstatic int
efb80947b01107dafbbf0157de0d7e1af6551259ahrensrestore_object(struct restorearg *ra, objset_t *os, struct drr_object *drro)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens{
efb80947b01107dafbbf0157de0d7e1af6551259ahrens int err;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens dmu_tx_t *tx;
adee0b6f10e370500326bde344e66b6662e0b9dcTim Haley void *data = NULL;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (drro->drr_type == DMU_OT_NONE ||
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drro->drr_type >= DMU_OT_NUMTYPES ||
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drro->drr_bonustype >= DMU_OT_NUMTYPES ||
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drro->drr_checksumtype >= ZIO_CHECKSUM_FUNCTIONS ||
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drro->drr_compress >= ZIO_COMPRESS_FUNCTIONS ||
efb80947b01107dafbbf0157de0d7e1af6551259ahrens P2PHASE(drro->drr_blksz, SPA_MINBLOCKSIZE) ||
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drro->drr_blksz < SPA_MINBLOCKSIZE ||
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drro->drr_blksz > SPA_MAXBLOCKSIZE ||
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drro->drr_bonuslen > DN_MAX_BONUSLEN) {
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (EINVAL);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
2bf405a25eb25f79638fc951ff8d8857ad384417Mark Maybee err = dmu_object_info(os, drro->drr_object, NULL);
2bf405a25eb25f79638fc951ff8d8857ad384417Mark Maybee
2bf405a25eb25f79638fc951ff8d8857ad384417Mark Maybee if (err != 0 && err != ENOENT)
2bf405a25eb25f79638fc951ff8d8857ad384417Mark Maybee return (EINVAL);
2bf405a25eb25f79638fc951ff8d8857ad384417Mark Maybee
adee0b6f10e370500326bde344e66b6662e0b9dcTim Haley if (drro->drr_bonuslen) {
adee0b6f10e370500326bde344e66b6662e0b9dcTim Haley data = restore_read(ra, P2ROUNDUP(drro->drr_bonuslen, 8));
adee0b6f10e370500326bde344e66b6662e0b9dcTim Haley if (ra->err)
adee0b6f10e370500326bde344e66b6662e0b9dcTim Haley return (ra->err);
adee0b6f10e370500326bde344e66b6662e0b9dcTim Haley }
adee0b6f10e370500326bde344e66b6662e0b9dcTim Haley
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (err == ENOENT) {
efb80947b01107dafbbf0157de0d7e1af6551259ahrens /* currently free, want to be allocated */
2bf405a25eb25f79638fc951ff8d8857ad384417Mark Maybee tx = dmu_tx_create(os);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens err = dmu_tx_assign(tx, TXG_WAIT);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (err) {
efb80947b01107dafbbf0157de0d7e1af6551259ahrens dmu_tx_abort(tx);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (err);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens err = dmu_object_claim(os, drro->drr_object,
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drro->drr_type, drro->drr_blksz,
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drro->drr_bonustype, drro->drr_bonuslen, tx);
2bf405a25eb25f79638fc951ff8d8857ad384417Mark Maybee dmu_tx_commit(tx);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens } else {
efb80947b01107dafbbf0157de0d7e1af6551259ahrens /* currently allocated, want to be allocated */
efb80947b01107dafbbf0157de0d7e1af6551259ahrens err = dmu_object_reclaim(os, drro->drr_object,
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drro->drr_type, drro->drr_blksz,
2bf405a25eb25f79638fc951ff8d8857ad384417Mark Maybee drro->drr_bonustype, drro->drr_bonuslen);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum if (err) {
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (EINVAL);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum }
2bf405a25eb25f79638fc951ff8d8857ad384417Mark Maybee
2bf405a25eb25f79638fc951ff8d8857ad384417Mark Maybee tx = dmu_tx_create(os);
2bf405a25eb25f79638fc951ff8d8857ad384417Mark Maybee dmu_tx_hold_bonus(tx, drro->drr_object);
2bf405a25eb25f79638fc951ff8d8857ad384417Mark Maybee err = dmu_tx_assign(tx, TXG_WAIT);
2bf405a25eb25f79638fc951ff8d8857ad384417Mark Maybee if (err) {
2bf405a25eb25f79638fc951ff8d8857ad384417Mark Maybee dmu_tx_abort(tx);
2bf405a25eb25f79638fc951ff8d8857ad384417Mark Maybee return (err);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt dmu_object_set_checksum(os, drro->drr_object, drro->drr_checksumtype,
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt tx);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens dmu_object_set_compress(os, drro->drr_object, drro->drr_compress, tx);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
adee0b6f10e370500326bde344e66b6662e0b9dcTim Haley if (data != NULL) {
efb80947b01107dafbbf0157de0d7e1af6551259ahrens dmu_buf_t *db;
adee0b6f10e370500326bde344e66b6662e0b9dcTim Haley
efb80947b01107dafbbf0157de0d7e1af6551259ahrens VERIFY(0 == dmu_bonus_hold(os, drro->drr_object, FTAG, &db));
efb80947b01107dafbbf0157de0d7e1af6551259ahrens dmu_buf_will_dirty(db, tx);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
1934e92fc930c49429ad71a8ca97340f33227e78maybee ASSERT3U(db->db_size, >=, drro->drr_bonuslen);
1934e92fc930c49429ad71a8ca97340f33227e78maybee bcopy(data, db->db_data, drro->drr_bonuslen);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (ra->byteswap) {
efb80947b01107dafbbf0157de0d7e1af6551259ahrens dmu_ot[drro->drr_bonustype].ot_byteswap(db->db_data,
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drro->drr_bonuslen);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens dmu_buf_rele(db, FTAG);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens dmu_tx_commit(tx);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (0);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens}
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens/* ARGSUSED */
efb80947b01107dafbbf0157de0d7e1af6551259ahrensstatic int
efb80947b01107dafbbf0157de0d7e1af6551259ahrensrestore_freeobjects(struct restorearg *ra, objset_t *os,
efb80947b01107dafbbf0157de0d7e1af6551259ahrens struct drr_freeobjects *drrfo)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens{
efb80947b01107dafbbf0157de0d7e1af6551259ahrens uint64_t obj;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (drrfo->drr_firstobj + drrfo->drr_numobjs < drrfo->drr_firstobj)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (EINVAL);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens for (obj = drrfo->drr_firstobj;
432f72fd2958c0d1ecc680b0573d8f65a22de385ahrens obj < drrfo->drr_firstobj + drrfo->drr_numobjs;
432f72fd2958c0d1ecc680b0573d8f65a22de385ahrens (void) dmu_object_next(os, &obj, FALSE, 0)) {
efb80947b01107dafbbf0157de0d7e1af6551259ahrens int err;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (dmu_object_info(os, obj, NULL) != 0)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens continue;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee err = dmu_free_object(os, obj);
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee if (err)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (err);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (0);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens}
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrensstatic int
efb80947b01107dafbbf0157de0d7e1af6551259ahrensrestore_write(struct restorearg *ra, objset_t *os,
efb80947b01107dafbbf0157de0d7e1af6551259ahrens struct drr_write *drrw)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens{
efb80947b01107dafbbf0157de0d7e1af6551259ahrens dmu_tx_t *tx;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens void *data;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens int err;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (drrw->drr_offset + drrw->drr_length < drrw->drr_offset ||
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drrw->drr_type >= DMU_OT_NUMTYPES)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (EINVAL);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens data = restore_read(ra, drrw->drr_length);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (data == NULL)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (ra->err);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (dmu_object_info(os, drrw->drr_object, NULL) != 0)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (EINVAL);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens tx = dmu_tx_create(os);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens dmu_tx_hold_write(tx, drrw->drr_object,
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drrw->drr_offset, drrw->drr_length);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens err = dmu_tx_assign(tx, TXG_WAIT);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (err) {
efb80947b01107dafbbf0157de0d7e1af6551259ahrens dmu_tx_abort(tx);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (err);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (ra->byteswap)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens dmu_ot[drrw->drr_type].ot_byteswap(data, drrw->drr_length);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens dmu_write(os, drrw->drr_object,
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drrw->drr_offset, drrw->drr_length, data, tx);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens dmu_tx_commit(tx);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (0);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens}
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt/*
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * Handle a DRR_WRITE_BYREF record. This record is used in dedup'ed
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * streams to refer to a copy of the data that is already on the
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * system because it came in earlier in the stream. This function
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * finds the earlier copy of the data, and uses that copy instead of
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * data from the stream to fulfill this write.
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt */
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Altstatic int
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Altrestore_write_byref(struct restorearg *ra, objset_t *os,
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt struct drr_write_byref *drrwbr)
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt{
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt dmu_tx_t *tx;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt int err;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt guid_map_entry_t gmesrch;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt guid_map_entry_t *gmep;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt avl_index_t where;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt objset_t *ref_os = NULL;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt dmu_buf_t *dbp;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt if (drrwbr->drr_offset + drrwbr->drr_length < drrwbr->drr_offset)
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt return (EINVAL);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt /*
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * If the GUID of the referenced dataset is different from the
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt * GUID of the target dataset, find the referenced dataset.
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt */
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt if (drrwbr->drr_toguid != drrwbr->drr_refguid) {
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt gmesrch.guid = drrwbr->drr_refguid;
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby if ((gmep = avl_find(ra->guid_to_ds_map, &gmesrch,
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt &where)) == NULL) {
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt return (EINVAL);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt }
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt if (dmu_objset_from_ds(gmep->gme_ds, &ref_os))
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt return (EINVAL);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt } else {
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt ref_os = os;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt }
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt if (err = dmu_buf_hold(ref_os, drrwbr->drr_refobject,
47cb52daa729f19e298c85a84e8df069365c5232Jeff Bonwick drrwbr->drr_refoffset, FTAG, &dbp, DMU_READ_PREFETCH))
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt return (err);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt tx = dmu_tx_create(os);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt dmu_tx_hold_write(tx, drrwbr->drr_object,
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drrwbr->drr_offset, drrwbr->drr_length);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt err = dmu_tx_assign(tx, TXG_WAIT);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt if (err) {
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt dmu_tx_abort(tx);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt return (err);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt }
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt dmu_write(os, drrwbr->drr_object,
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drrwbr->drr_offset, drrwbr->drr_length, dbp->db_data, tx);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt dmu_buf_rele(dbp, FTAG);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt dmu_tx_commit(tx);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt return (0);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt}
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaumstatic int
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaumrestore_spill(struct restorearg *ra, objset_t *os, struct drr_spill *drrs)
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum{
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum dmu_tx_t *tx;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum void *data;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum dmu_buf_t *db, *db_spill;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum int err;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum if (drrs->drr_length < SPA_MINBLOCKSIZE ||
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum drrs->drr_length > SPA_MAXBLOCKSIZE)
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum return (EINVAL);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum data = restore_read(ra, drrs->drr_length);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum if (data == NULL)
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum return (ra->err);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum if (dmu_object_info(os, drrs->drr_object, NULL) != 0)
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum return (EINVAL);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum VERIFY(0 == dmu_bonus_hold(os, drrs->drr_object, FTAG, &db));
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum if ((err = dmu_spill_hold_by_bonus(db, FTAG, &db_spill)) != 0) {
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum dmu_buf_rele(db, FTAG);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum return (err);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum }
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum tx = dmu_tx_create(os);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum dmu_tx_hold_spill(tx, db->db_object);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum err = dmu_tx_assign(tx, TXG_WAIT);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum if (err) {
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum dmu_buf_rele(db, FTAG);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum dmu_buf_rele(db_spill, FTAG);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum dmu_tx_abort(tx);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum return (err);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum }
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum dmu_buf_will_dirty(db_spill, tx);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum if (db_spill->db_size < drrs->drr_length)
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum VERIFY(0 == dbuf_spill_set_blksz(db_spill,
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum drrs->drr_length, tx));
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum bcopy(data, db_spill->db_data, drrs->drr_length);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum dmu_buf_rele(db, FTAG);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum dmu_buf_rele(db_spill, FTAG);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum dmu_tx_commit(tx);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum return (0);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum}
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum
efb80947b01107dafbbf0157de0d7e1af6551259ahrens/* ARGSUSED */
efb80947b01107dafbbf0157de0d7e1af6551259ahrensstatic int
efb80947b01107dafbbf0157de0d7e1af6551259ahrensrestore_free(struct restorearg *ra, objset_t *os,
efb80947b01107dafbbf0157de0d7e1af6551259ahrens struct drr_free *drrf)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens{
efb80947b01107dafbbf0157de0d7e1af6551259ahrens int err;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (drrf->drr_length != -1ULL &&
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drrf->drr_offset + drrf->drr_length < drrf->drr_offset)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (EINVAL);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (dmu_object_info(os, drrf->drr_object, NULL) != 0)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (EINVAL);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
cdb0ab79ea1af7b8fc339a04d4bf7426dc77ec4emaybee err = dmu_free_long_range(os, drrf->drr_object,
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drrf->drr_offset, drrf->drr_length);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (err);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens}
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens/*
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens * NB: callers *must* call dmu_recv_end() if this succeeds.
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens */
efb80947b01107dafbbf0157de0d7e1af6551259ahrensint
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirbydmu_recv_stream(dmu_recv_cookie_t *drc, vnode_t *vp, offset_t *voffp,
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby int cleanup_fd, uint64_t *action_handlep)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens{
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens struct restorearg ra = { 0 };
efb80947b01107dafbbf0157de0d7e1af6551259ahrens dmu_replay_record_t *drr;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens objset_t *os;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens zio_cksum_t pcksum;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt int featureflags;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens if (drc->drc_drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC))
efb80947b01107dafbbf0157de0d7e1af6551259ahrens ra.byteswap = TRUE;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens {
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens /* compute checksum of drr_begin record */
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens dmu_replay_record_t *drr;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens drr = kmem_zalloc(sizeof (dmu_replay_record_t), KM_SLEEP);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens drr->drr_type = DRR_BEGIN;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens drr->drr_u.drr_begin = *drc->drc_drrb;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens if (ra.byteswap) {
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens fletcher_4_incremental_byteswap(drr,
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens sizeof (dmu_replay_record_t), &ra.cksum);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens } else {
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens fletcher_4_incremental_native(drr,
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens sizeof (dmu_replay_record_t), &ra.cksum);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens }
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens kmem_free(drr, sizeof (dmu_replay_record_t));
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (ra.byteswap) {
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens struct drr_begin *drrb = drc->drc_drrb;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drrb->drr_magic = BSWAP_64(drrb->drr_magic);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drrb->drr_versioninfo = BSWAP_64(drrb->drr_versioninfo);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drrb->drr_creation_time = BSWAP_64(drrb->drr_creation_time);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drrb->drr_type = BSWAP_32(drrb->drr_type);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drrb->drr_toguid = BSWAP_64(drrb->drr_toguid);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drrb->drr_fromguid = BSWAP_64(drrb->drr_fromguid);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens ra.vp = vp;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens ra.voff = *voffp;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens ra.bufsize = 1<<20;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens ra.buf = kmem_alloc(ra.bufsize, KM_SLEEP);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens /* these were verified in dmu_recv_begin */
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt ASSERT(DMU_GET_STREAM_HDRTYPE(drc->drc_drrb->drr_versioninfo) ==
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt DMU_SUBSTREAM);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens ASSERT(drc->drc_drrb->drr_type < DMU_OST_NUMTYPES);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens /*
efb80947b01107dafbbf0157de0d7e1af6551259ahrens * Open the objset we are modifying.
efb80947b01107dafbbf0157de0d7e1af6551259ahrens */
503ad85c168c7992ccc310af845a581cff3c72b5Matthew Ahrens VERIFY(dmu_objset_from_ds(drc->drc_real_ds, &os) == 0);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens ASSERT(drc->drc_real_ds->ds_phys->ds_flags & DS_FLAG_INCONSISTENT);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt featureflags = DMU_GET_FEATUREFLAGS(drc->drc_drrb->drr_versioninfo);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt /* if this stream is dedup'ed, set up the avl tree for guid mapping */
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt if (featureflags & DMU_BACKUP_FEATURE_DEDUP) {
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirby minor_t minor;
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirby
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby if (cleanup_fd == -1) {
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby ra.err = EBADF;
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby goto out;
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby }
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirby ra.err = zfs_onexit_fd_hold(cleanup_fd, &minor);
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirby if (ra.err) {
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirby cleanup_fd = -1;
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirby goto out;
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirby }
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirby
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby if (*action_handlep == 0) {
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby ra.guid_to_ds_map =
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby kmem_alloc(sizeof (avl_tree_t), KM_SLEEP);
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby avl_create(ra.guid_to_ds_map, guid_compare,
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby sizeof (guid_map_entry_t),
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby offsetof(guid_map_entry_t, avlnode));
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirby ra.err = zfs_onexit_add_cb(minor,
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby free_guid_map_onexit, ra.guid_to_ds_map,
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby action_handlep);
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby if (ra.err)
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby goto out;
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby } else {
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirby ra.err = zfs_onexit_cb_data(minor, *action_handlep,
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby (void **)&ra.guid_to_ds_map);
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby if (ra.err)
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby goto out;
c99e4bdccfb4ac4da569c64a43baaf908d726329Chris Kirby }
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko drc->drc_guid_to_ds_map = ra.guid_to_ds_map;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt }
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt
efb80947b01107dafbbf0157de0d7e1af6551259ahrens /*
efb80947b01107dafbbf0157de0d7e1af6551259ahrens * Read records and process them.
efb80947b01107dafbbf0157de0d7e1af6551259ahrens */
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens pcksum = ra.cksum;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens while (ra.err == 0 &&
efb80947b01107dafbbf0157de0d7e1af6551259ahrens NULL != (drr = restore_read(&ra, sizeof (*drr)))) {
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (issig(JUSTLOOKING) && issig(FORREAL)) {
efb80947b01107dafbbf0157de0d7e1af6551259ahrens ra.err = EINTR;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens goto out;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens if (ra.byteswap)
efb80947b01107dafbbf0157de0d7e1af6551259ahrens backup_byteswap(drr);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens switch (drr->drr_type) {
efb80947b01107dafbbf0157de0d7e1af6551259ahrens case DRR_OBJECT:
efb80947b01107dafbbf0157de0d7e1af6551259ahrens {
efb80947b01107dafbbf0157de0d7e1af6551259ahrens /*
efb80947b01107dafbbf0157de0d7e1af6551259ahrens * We need to make a copy of the record header,
efb80947b01107dafbbf0157de0d7e1af6551259ahrens * because restore_{object,write} may need to
efb80947b01107dafbbf0157de0d7e1af6551259ahrens * restore_read(), which will invalidate drr.
efb80947b01107dafbbf0157de0d7e1af6551259ahrens */
efb80947b01107dafbbf0157de0d7e1af6551259ahrens struct drr_object drro = drr->drr_u.drr_object;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens ra.err = restore_object(&ra, os, &drro);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens break;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens case DRR_FREEOBJECTS:
efb80947b01107dafbbf0157de0d7e1af6551259ahrens {
efb80947b01107dafbbf0157de0d7e1af6551259ahrens struct drr_freeobjects drrfo =
efb80947b01107dafbbf0157de0d7e1af6551259ahrens drr->drr_u.drr_freeobjects;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens ra.err = restore_freeobjects(&ra, os, &drrfo);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens break;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens case DRR_WRITE:
efb80947b01107dafbbf0157de0d7e1af6551259ahrens {
efb80947b01107dafbbf0157de0d7e1af6551259ahrens struct drr_write drrw = drr->drr_u.drr_write;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens ra.err = restore_write(&ra, os, &drrw);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens break;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt case DRR_WRITE_BYREF:
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt {
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt struct drr_write_byref drrwbr =
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt drr->drr_u.drr_write_byref;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt ra.err = restore_write_byref(&ra, os, &drrwbr);
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt break;
9e69d7d0feb2a0394435ca1d9746c4c3d7bf9b22Lori Alt }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens case DRR_FREE:
efb80947b01107dafbbf0157de0d7e1af6551259ahrens {
efb80947b01107dafbbf0157de0d7e1af6551259ahrens struct drr_free drrf = drr->drr_u.drr_free;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens ra.err = restore_free(&ra, os, &drrf);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens break;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens case DRR_END:
efb80947b01107dafbbf0157de0d7e1af6551259ahrens {
efb80947b01107dafbbf0157de0d7e1af6551259ahrens struct drr_end drre = drr->drr_u.drr_end;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens /*
efb80947b01107dafbbf0157de0d7e1af6551259ahrens * We compare against the *previous* checksum
efb80947b01107dafbbf0157de0d7e1af6551259ahrens * value, because the stored checksum is of
efb80947b01107dafbbf0157de0d7e1af6551259ahrens * everything before the DRR_END record.
efb80947b01107dafbbf0157de0d7e1af6551259ahrens */
137fa06774810a67312b8142740a4177af4c08dbahrens if (!ZIO_CHECKSUM_EQUAL(drre.drr_checksum, pcksum))
efb80947b01107dafbbf0157de0d7e1af6551259ahrens ra.err = ECKSUM;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens goto out;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum case DRR_SPILL:
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum {
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum struct drr_spill drrs = drr->drr_u.drr_spill;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum ra.err = restore_spill(&ra, os, &drrs);
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum break;
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens default:
efb80947b01107dafbbf0157de0d7e1af6551259ahrens ra.err = EINVAL;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens goto out;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens pcksum = ra.cksum;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
137fa06774810a67312b8142740a4177af4c08dbahrens ASSERT(ra.err != 0);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrensout:
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirby if ((featureflags & DMU_BACKUP_FEATURE_DEDUP) && (cleanup_fd != -1))
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirby zfs_onexit_fd_rele(cleanup_fd);
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirby
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens if (ra.err != 0) {
efb80947b01107dafbbf0157de0d7e1af6551259ahrens /*
f4b94bde302dc950da6b4ec29936dd9a7b9d61abMatthew Ahrens * destroy what we created, so we don't leave it in the
f4b94bde302dc950da6b4ec29936dd9a7b9d61abMatthew Ahrens * inconsistent restoring state.
efb80947b01107dafbbf0157de0d7e1af6551259ahrens */
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens txg_wait_synced(drc->drc_real_ds->ds_dir->dd_pool, 0);
f4b94bde302dc950da6b4ec29936dd9a7b9d61abMatthew Ahrens
842727c2f41f01b380de4f5e787d905702870f23Chris Kirby (void) dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag,
842727c2f41f01b380de4f5e787d905702870f23Chris Kirby B_FALSE);
f4b94bde302dc950da6b4ec29936dd9a7b9d61abMatthew Ahrens if (drc->drc_real_ds != drc->drc_logical_ds) {
f4b94bde302dc950da6b4ec29936dd9a7b9d61abMatthew Ahrens mutex_exit(&drc->drc_logical_ds->ds_recvlock);
f4b94bde302dc950da6b4ec29936dd9a7b9d61abMatthew Ahrens dsl_dataset_rele(drc->drc_logical_ds, dmu_recv_tag);
f4b94bde302dc950da6b4ec29936dd9a7b9d61abMatthew Ahrens }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens }
efb80947b01107dafbbf0157de0d7e1af6551259ahrens
efb80947b01107dafbbf0157de0d7e1af6551259ahrens kmem_free(ra.buf, ra.bufsize);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens *voffp = ra.voff;
efb80947b01107dafbbf0157de0d7e1af6551259ahrens return (ra.err);
efb80947b01107dafbbf0157de0d7e1af6551259ahrens}
f18faf3f3e5def85fdfff681617d227703ace2adek
3cb34c601f3ef3016f638574f5982e80c3735c71ahrensstruct recvendsyncarg {
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens char *tosnap;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens uint64_t creation_time;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens uint64_t toguid;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens};
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrensstatic int
3cb34c601f3ef3016f638574f5982e80c3735c71ahrensrecv_end_check(void *arg1, void *arg2, dmu_tx_t *tx)
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens{
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens dsl_dataset_t *ds = arg1;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens struct recvendsyncarg *resa = arg2;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens return (dsl_dataset_snapshot_check(ds, resa->tosnap, tx));
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens}
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrensstatic void
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Lingrecv_end_sync(void *arg1, void *arg2, dmu_tx_t *tx)
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens{
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens dsl_dataset_t *ds = arg1;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens struct recvendsyncarg *resa = arg2;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling dsl_dataset_snapshot_sync(ds, resa->tosnap, tx);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens /* set snapshot's creation time and guid */
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens dmu_buf_will_dirty(ds->ds_prev->ds_dbuf, tx);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens ds->ds_prev->ds_phys->ds_creation_time = resa->creation_time;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens ds->ds_prev->ds_phys->ds_guid = resa->toguid;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens ds->ds_prev->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens dmu_buf_will_dirty(ds->ds_dbuf, tx);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens ds->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens}
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenkostatic int
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenkoadd_ds_to_guidmap(avl_tree_t *guid_map, dsl_dataset_t *ds)
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko{
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko dsl_pool_t *dp = ds->ds_dir->dd_pool;
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko uint64_t snapobj = ds->ds_phys->ds_prev_snap_obj;
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko dsl_dataset_t *snapds;
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko guid_map_entry_t *gmep;
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko int err;
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko ASSERT(guid_map != NULL);
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko rw_enter(&dp->dp_config_rwlock, RW_READER);
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko err = dsl_dataset_hold_obj(dp, snapobj, guid_map, &snapds);
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko if (err == 0) {
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko gmep = kmem_alloc(sizeof (guid_map_entry_t), KM_SLEEP);
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko gmep->guid = snapds->ds_phys->ds_guid;
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko gmep->gme_ds = snapds;
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko avl_add(guid_map, gmep);
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko }
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko rw_exit(&dp->dp_config_rwlock);
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko return (err);
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko}
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrensstatic int
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrensdmu_recv_existing_end(dmu_recv_cookie_t *drc)
f18faf3f3e5def85fdfff681617d227703ace2adek{
745cd3c5371d020efae7a911c58c526aa1fd0dbamaybee struct recvendsyncarg resa;
745cd3c5371d020efae7a911c58c526aa1fd0dbamaybee dsl_dataset_t *ds = drc->drc_logical_ds;
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens int err, myerr;
f18faf3f3e5def85fdfff681617d227703ace2adek
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens /*
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens * XXX hack; seems the ds is still dirty and dsl_pool_zil_clean()
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens * expects it to have a ds_user_ptr (and zil), but clone_swap()
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens * can close it.
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens */
745cd3c5371d020efae7a911c58c526aa1fd0dbamaybee txg_wait_synced(ds->ds_dir->dd_pool, 0);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens if (dsl_dataset_tryown(ds, FALSE, dmu_recv_tag)) {
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens err = dsl_dataset_clone_swap(drc->drc_real_ds, ds,
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens drc->drc_force);
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens if (err)
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens goto out;
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens } else {
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens mutex_exit(&ds->ds_recvlock);
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens dsl_dataset_rele(ds, dmu_recv_tag);
842727c2f41f01b380de4f5e787d905702870f23Chris Kirby (void) dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag,
842727c2f41f01b380de4f5e787d905702870f23Chris Kirby B_FALSE);
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens return (EBUSY);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens }
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
745cd3c5371d020efae7a911c58c526aa1fd0dbamaybee resa.creation_time = drc->drc_drrb->drr_creation_time;
745cd3c5371d020efae7a911c58c526aa1fd0dbamaybee resa.toguid = drc->drc_drrb->drr_toguid;
745cd3c5371d020efae7a911c58c526aa1fd0dbamaybee resa.tosnap = drc->drc_tosnap;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
745cd3c5371d020efae7a911c58c526aa1fd0dbamaybee err = dsl_sync_task_do(ds->ds_dir->dd_pool,
745cd3c5371d020efae7a911c58c526aa1fd0dbamaybee recv_end_check, recv_end_sync, ds, &resa, 3);
745cd3c5371d020efae7a911c58c526aa1fd0dbamaybee if (err) {
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens /* swap back */
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens (void) dsl_dataset_clone_swap(drc->drc_real_ds, ds, B_TRUE);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens }
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrensout:
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens mutex_exit(&ds->ds_recvlock);
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko if (err == 0 && drc->drc_guid_to_ds_map != NULL)
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko (void) add_ds_to_guidmap(drc->drc_guid_to_ds_map, ds);
745cd3c5371d020efae7a911c58c526aa1fd0dbamaybee dsl_dataset_disown(ds, dmu_recv_tag);
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens myerr = dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag, B_FALSE);
19b94df933188a15d4f0d6c568f0bab3f127892eMatthew Ahrens ASSERT3U(myerr, ==, 0);
f18faf3f3e5def85fdfff681617d227703ace2adek return (err);
f18faf3f3e5def85fdfff681617d227703ace2adek}
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrensstatic int
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrensdmu_recv_new_end(dmu_recv_cookie_t *drc)
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens{
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens struct recvendsyncarg resa;
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens dsl_dataset_t *ds = drc->drc_logical_ds;
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens int err;
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens /*
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens * XXX hack; seems the ds is still dirty and dsl_pool_zil_clean()
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens * expects it to have a ds_user_ptr (and zil), but clone_swap()
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens * can close it.
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens */
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens txg_wait_synced(ds->ds_dir->dd_pool, 0);
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens resa.creation_time = drc->drc_drrb->drr_creation_time;
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens resa.toguid = drc->drc_drrb->drr_toguid;
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens resa.tosnap = drc->drc_tosnap;
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens err = dsl_sync_task_do(ds->ds_dir->dd_pool,
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens recv_end_check, recv_end_sync, ds, &resa, 3);
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens if (err) {
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens /* clean up the fs we just recv'd into */
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens (void) dsl_dataset_destroy(ds, dmu_recv_tag, B_FALSE);
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens } else {
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko if (drc->drc_guid_to_ds_map != NULL)
ec5cf9d53a1d7280f3f1a6eadd7cdabdc99814ebAlexander Stetsenko (void) add_ds_to_guidmap(drc->drc_guid_to_ds_map, ds);
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens /* release the hold from dmu_recv_begin */
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens dsl_dataset_disown(ds, dmu_recv_tag);
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens }
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens return (err);
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens}
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrensint
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrensdmu_recv_end(dmu_recv_cookie_t *drc)
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens{
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens if (drc->drc_logical_ds != drc->drc_real_ds)
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens return (dmu_recv_existing_end(drc));
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens else
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens return (dmu_recv_new_end(drc));
ae46e4c775f2becc5343ff90b60a95acb79735f9Matthew Ahrens}