dmu_send.c revision 254753
1168404Spjd/* 2168404Spjd * CDDL HEADER START 3168404Spjd * 4168404Spjd * The contents of this file are subject to the terms of the 5168404Spjd * Common Development and Distribution License (the "License"). 6168404Spjd * You may not use this file except in compliance with the License. 7168404Spjd * 8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9168404Spjd * or http://www.opensolaris.org/os/licensing. 10168404Spjd * See the License for the specific language governing permissions 11168404Spjd * and limitations under the License. 12168404Spjd * 13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each 14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15168404Spjd * If applicable, add the following below this CDDL HEADER, with the 16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying 17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner] 18168404Spjd * 19168404Spjd * CDDL HEADER END 20168404Spjd */ 21168404Spjd/* 22219089Spjd * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23221263Smm * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 24249195Smm * Copyright (c) 2013 by Delphix. All rights reserved. 25235222Smm * Copyright (c) 2012, Joyent, Inc. All rights reserved. 26235222Smm * Copyright (c) 2012, Martin Matuska <mm@FreeBSD.org>. All rights reserved. 27221263Smm */ 28168404Spjd 29168404Spjd#include <sys/dmu.h> 30168404Spjd#include <sys/dmu_impl.h> 31168404Spjd#include <sys/dmu_tx.h> 32168404Spjd#include <sys/dbuf.h> 33168404Spjd#include <sys/dnode.h> 34168404Spjd#include <sys/zfs_context.h> 35168404Spjd#include <sys/dmu_objset.h> 36168404Spjd#include <sys/dmu_traverse.h> 37168404Spjd#include <sys/dsl_dataset.h> 38168404Spjd#include <sys/dsl_dir.h> 39219089Spjd#include <sys/dsl_prop.h> 40168404Spjd#include <sys/dsl_pool.h> 41168404Spjd#include <sys/dsl_synctask.h> 42168404Spjd#include <sys/zfs_ioctl.h> 43168404Spjd#include <sys/zap.h> 44168404Spjd#include <sys/zio_checksum.h> 45219089Spjd#include <sys/zfs_znode.h> 46219089Spjd#include <zfs_fletcher.h> 47219089Spjd#include <sys/avl.h> 48219089Spjd#include <sys/ddt.h> 49219089Spjd#include <sys/zfs_onexit.h> 50248571Smm#include <sys/dmu_send.h> 51248571Smm#include <sys/dsl_destroy.h> 52168404Spjd 53228103Smm/* Set this tunable to TRUE to replace corrupt data with 0x2f5baddb10c */ 54228103Smmint zfs_send_corrupt_data = B_FALSE; 55228103Smm 56185029Spjdstatic char *dmu_recv_tag = "dmu_recv_tag"; 57248571Smmstatic const char *recv_clone_name = "%recv"; 58185029Spjd 59168404Spjdstatic int 60235222Smmdump_bytes(dmu_sendarg_t *dsp, void *buf, int len) 61168404Spjd{ 62235222Smm dsl_dataset_t *ds = dsp->dsa_os->os_dsl_dataset; 63168404Spjd struct uio auio; 64168404Spjd struct iovec aiov; 65240415Smm ASSERT0(len % 8); 66168404Spjd 67235222Smm fletcher_4_incremental_native(buf, len, &dsp->dsa_zc); 68168404Spjd aiov.iov_base = buf; 69168404Spjd aiov.iov_len = len; 70168404Spjd auio.uio_iov = &aiov; 71168404Spjd auio.uio_iovcnt = 1; 72168404Spjd auio.uio_resid = len; 73169170Spjd auio.uio_segflg = UIO_SYSSPACE; 74168404Spjd auio.uio_rw = UIO_WRITE; 75168404Spjd auio.uio_offset = (off_t)-1; 76235222Smm auio.uio_td = dsp->dsa_td; 77168404Spjd#ifdef _KERNEL 78235222Smm if (dsp->dsa_fp->f_type == DTYPE_VNODE) 79168404Spjd bwillwrite(); 80235222Smm dsp->dsa_err = fo_write(dsp->dsa_fp, &auio, dsp->dsa_td->td_ucred, 0, 81235222Smm dsp->dsa_td); 82168404Spjd#else 83168404Spjd fprintf(stderr, "%s: returning EOPNOTSUPP\n", __func__); 84235222Smm dsp->dsa_err = EOPNOTSUPP; 85168404Spjd#endif 86235222Smm mutex_enter(&ds->ds_sendstream_lock); 87235222Smm *dsp->dsa_off += len; 88235222Smm mutex_exit(&ds->ds_sendstream_lock); 89235222Smm 90235222Smm return (dsp->dsa_err); 91168404Spjd} 92168404Spjd 93168404Spjdstatic int 94235222Smmdump_free(dmu_sendarg_t *dsp, uint64_t object, uint64_t offset, 95168404Spjd uint64_t length) 96168404Spjd{ 97235222Smm struct drr_free *drrf = &(dsp->dsa_drr->drr_u.drr_free); 98219089Spjd 99253821Sdelphij /* 100253821Sdelphij * When we receive a free record, dbuf_free_range() assumes 101253821Sdelphij * that the receiving system doesn't have any dbufs in the range 102253821Sdelphij * being freed. This is always true because there is a one-record 103253821Sdelphij * constraint: we only send one WRITE record for any given 104253821Sdelphij * object+offset. We know that the one-record constraint is 105253821Sdelphij * true because we always send data in increasing order by 106253821Sdelphij * object,offset. 107253821Sdelphij * 108253821Sdelphij * If the increasing-order constraint ever changes, we should find 109253821Sdelphij * another way to assert that the one-record constraint is still 110253821Sdelphij * satisfied. 111253821Sdelphij */ 112253821Sdelphij ASSERT(object > dsp->dsa_last_data_object || 113253821Sdelphij (object == dsp->dsa_last_data_object && 114253821Sdelphij offset > dsp->dsa_last_data_offset)); 115253821Sdelphij 116253821Sdelphij /* 117253821Sdelphij * If we are doing a non-incremental send, then there can't 118253821Sdelphij * be any data in the dataset we're receiving into. Therefore 119253821Sdelphij * a free record would simply be a no-op. Save space by not 120253821Sdelphij * sending it to begin with. 121253821Sdelphij */ 122253821Sdelphij if (!dsp->dsa_incremental) 123253821Sdelphij return (0); 124253821Sdelphij 125237458Smm if (length != -1ULL && offset + length < offset) 126237458Smm length = -1ULL; 127237458Smm 128219089Spjd /* 129219089Spjd * If there is a pending op, but it's not PENDING_FREE, push it out, 130219089Spjd * since free block aggregation can only be done for blocks of the 131219089Spjd * same type (i.e., DRR_FREE records can only be aggregated with 132219089Spjd * other DRR_FREE records. DRR_FREEOBJECTS records can only be 133219089Spjd * aggregated with other DRR_FREEOBJECTS records. 134219089Spjd */ 135235222Smm if (dsp->dsa_pending_op != PENDING_NONE && 136235222Smm dsp->dsa_pending_op != PENDING_FREE) { 137235222Smm if (dump_bytes(dsp, dsp->dsa_drr, 138235222Smm sizeof (dmu_replay_record_t)) != 0) 139249195Smm return (SET_ERROR(EINTR)); 140235222Smm dsp->dsa_pending_op = PENDING_NONE; 141219089Spjd } 142219089Spjd 143235222Smm if (dsp->dsa_pending_op == PENDING_FREE) { 144219089Spjd /* 145219089Spjd * There should never be a PENDING_FREE if length is -1 146219089Spjd * (because dump_dnode is the only place where this 147219089Spjd * function is called with a -1, and only after flushing 148219089Spjd * any pending record). 149219089Spjd */ 150219089Spjd ASSERT(length != -1ULL); 151219089Spjd /* 152219089Spjd * Check to see whether this free block can be aggregated 153219089Spjd * with pending one. 154219089Spjd */ 155219089Spjd if (drrf->drr_object == object && drrf->drr_offset + 156219089Spjd drrf->drr_length == offset) { 157219089Spjd drrf->drr_length += length; 158219089Spjd return (0); 159219089Spjd } else { 160219089Spjd /* not a continuation. Push out pending record */ 161235222Smm if (dump_bytes(dsp, dsp->dsa_drr, 162219089Spjd sizeof (dmu_replay_record_t)) != 0) 163249195Smm return (SET_ERROR(EINTR)); 164235222Smm dsp->dsa_pending_op = PENDING_NONE; 165219089Spjd } 166219089Spjd } 167219089Spjd /* create a FREE record and make it pending */ 168235222Smm bzero(dsp->dsa_drr, sizeof (dmu_replay_record_t)); 169235222Smm dsp->dsa_drr->drr_type = DRR_FREE; 170219089Spjd drrf->drr_object = object; 171219089Spjd drrf->drr_offset = offset; 172219089Spjd drrf->drr_length = length; 173235222Smm drrf->drr_toguid = dsp->dsa_toguid; 174219089Spjd if (length == -1ULL) { 175235222Smm if (dump_bytes(dsp, dsp->dsa_drr, 176235222Smm sizeof (dmu_replay_record_t)) != 0) 177249195Smm return (SET_ERROR(EINTR)); 178219089Spjd } else { 179235222Smm dsp->dsa_pending_op = PENDING_FREE; 180219089Spjd } 181168404Spjd 182168404Spjd return (0); 183168404Spjd} 184168404Spjd 185168404Spjdstatic int 186235222Smmdump_data(dmu_sendarg_t *dsp, dmu_object_type_t type, 187219089Spjd uint64_t object, uint64_t offset, int blksz, const blkptr_t *bp, void *data) 188168404Spjd{ 189235222Smm struct drr_write *drrw = &(dsp->dsa_drr->drr_u.drr_write); 190219089Spjd 191253821Sdelphij /* 192253821Sdelphij * We send data in increasing object, offset order. 193253821Sdelphij * See comment in dump_free() for details. 194253821Sdelphij */ 195253821Sdelphij ASSERT(object > dsp->dsa_last_data_object || 196253821Sdelphij (object == dsp->dsa_last_data_object && 197253821Sdelphij offset > dsp->dsa_last_data_offset)); 198253821Sdelphij dsp->dsa_last_data_object = object; 199253821Sdelphij dsp->dsa_last_data_offset = offset + blksz - 1; 200219089Spjd 201219089Spjd /* 202219089Spjd * If there is any kind of pending aggregation (currently either 203219089Spjd * a grouping of free objects or free blocks), push it out to 204219089Spjd * the stream, since aggregation can't be done across operations 205219089Spjd * of different types. 206219089Spjd */ 207235222Smm if (dsp->dsa_pending_op != PENDING_NONE) { 208235222Smm if (dump_bytes(dsp, dsp->dsa_drr, 209235222Smm sizeof (dmu_replay_record_t)) != 0) 210249195Smm return (SET_ERROR(EINTR)); 211235222Smm dsp->dsa_pending_op = PENDING_NONE; 212219089Spjd } 213168404Spjd /* write a DATA record */ 214235222Smm bzero(dsp->dsa_drr, sizeof (dmu_replay_record_t)); 215235222Smm dsp->dsa_drr->drr_type = DRR_WRITE; 216219089Spjd drrw->drr_object = object; 217219089Spjd drrw->drr_type = type; 218219089Spjd drrw->drr_offset = offset; 219219089Spjd drrw->drr_length = blksz; 220235222Smm drrw->drr_toguid = dsp->dsa_toguid; 221219089Spjd drrw->drr_checksumtype = BP_GET_CHECKSUM(bp); 222219089Spjd if (zio_checksum_table[drrw->drr_checksumtype].ci_dedup) 223219089Spjd drrw->drr_checksumflags |= DRR_CHECKSUM_DEDUP; 224219089Spjd DDK_SET_LSIZE(&drrw->drr_key, BP_GET_LSIZE(bp)); 225219089Spjd DDK_SET_PSIZE(&drrw->drr_key, BP_GET_PSIZE(bp)); 226219089Spjd DDK_SET_COMPRESS(&drrw->drr_key, BP_GET_COMPRESS(bp)); 227219089Spjd drrw->drr_key.ddk_cksum = bp->blk_cksum; 228168404Spjd 229235222Smm if (dump_bytes(dsp, dsp->dsa_drr, sizeof (dmu_replay_record_t)) != 0) 230249195Smm return (SET_ERROR(EINTR)); 231235222Smm if (dump_bytes(dsp, data, blksz) != 0) 232249195Smm return (SET_ERROR(EINTR)); 233219089Spjd return (0); 234219089Spjd} 235219089Spjd 236219089Spjdstatic int 237235222Smmdump_spill(dmu_sendarg_t *dsp, uint64_t object, int blksz, void *data) 238219089Spjd{ 239235222Smm struct drr_spill *drrs = &(dsp->dsa_drr->drr_u.drr_spill); 240219089Spjd 241235222Smm if (dsp->dsa_pending_op != PENDING_NONE) { 242235222Smm if (dump_bytes(dsp, dsp->dsa_drr, 243235222Smm sizeof (dmu_replay_record_t)) != 0) 244249195Smm return (SET_ERROR(EINTR)); 245235222Smm dsp->dsa_pending_op = PENDING_NONE; 246219089Spjd } 247219089Spjd 248219089Spjd /* write a SPILL record */ 249235222Smm bzero(dsp->dsa_drr, sizeof (dmu_replay_record_t)); 250235222Smm dsp->dsa_drr->drr_type = DRR_SPILL; 251219089Spjd drrs->drr_object = object; 252219089Spjd drrs->drr_length = blksz; 253235222Smm drrs->drr_toguid = dsp->dsa_toguid; 254219089Spjd 255235222Smm if (dump_bytes(dsp, dsp->dsa_drr, sizeof (dmu_replay_record_t))) 256249195Smm return (SET_ERROR(EINTR)); 257235222Smm if (dump_bytes(dsp, data, blksz)) 258249195Smm return (SET_ERROR(EINTR)); 259168404Spjd return (0); 260168404Spjd} 261168404Spjd 262168404Spjdstatic int 263235222Smmdump_freeobjects(dmu_sendarg_t *dsp, uint64_t firstobj, uint64_t numobjs) 264168404Spjd{ 265235222Smm struct drr_freeobjects *drrfo = &(dsp->dsa_drr->drr_u.drr_freeobjects); 266219089Spjd 267253821Sdelphij /* See comment in dump_free(). */ 268253821Sdelphij if (!dsp->dsa_incremental) 269253821Sdelphij return (0); 270253821Sdelphij 271219089Spjd /* 272219089Spjd * If there is a pending op, but it's not PENDING_FREEOBJECTS, 273219089Spjd * push it out, since free block aggregation can only be done for 274219089Spjd * blocks of the same type (i.e., DRR_FREE records can only be 275219089Spjd * aggregated with other DRR_FREE records. DRR_FREEOBJECTS records 276219089Spjd * can only be aggregated with other DRR_FREEOBJECTS records. 277219089Spjd */ 278235222Smm if (dsp->dsa_pending_op != PENDING_NONE && 279235222Smm dsp->dsa_pending_op != PENDING_FREEOBJECTS) { 280235222Smm if (dump_bytes(dsp, dsp->dsa_drr, 281235222Smm sizeof (dmu_replay_record_t)) != 0) 282249195Smm return (SET_ERROR(EINTR)); 283235222Smm dsp->dsa_pending_op = PENDING_NONE; 284219089Spjd } 285235222Smm if (dsp->dsa_pending_op == PENDING_FREEOBJECTS) { 286219089Spjd /* 287219089Spjd * See whether this free object array can be aggregated 288219089Spjd * with pending one 289219089Spjd */ 290219089Spjd if (drrfo->drr_firstobj + drrfo->drr_numobjs == firstobj) { 291219089Spjd drrfo->drr_numobjs += numobjs; 292219089Spjd return (0); 293219089Spjd } else { 294219089Spjd /* can't be aggregated. Push out pending record */ 295235222Smm if (dump_bytes(dsp, dsp->dsa_drr, 296219089Spjd sizeof (dmu_replay_record_t)) != 0) 297249195Smm return (SET_ERROR(EINTR)); 298235222Smm dsp->dsa_pending_op = PENDING_NONE; 299219089Spjd } 300219089Spjd } 301219089Spjd 302168404Spjd /* write a FREEOBJECTS record */ 303235222Smm bzero(dsp->dsa_drr, sizeof (dmu_replay_record_t)); 304235222Smm dsp->dsa_drr->drr_type = DRR_FREEOBJECTS; 305219089Spjd drrfo->drr_firstobj = firstobj; 306219089Spjd drrfo->drr_numobjs = numobjs; 307235222Smm drrfo->drr_toguid = dsp->dsa_toguid; 308168404Spjd 309235222Smm dsp->dsa_pending_op = PENDING_FREEOBJECTS; 310219089Spjd 311168404Spjd return (0); 312168404Spjd} 313168404Spjd 314168404Spjdstatic int 315235222Smmdump_dnode(dmu_sendarg_t *dsp, uint64_t object, dnode_phys_t *dnp) 316168404Spjd{ 317235222Smm struct drr_object *drro = &(dsp->dsa_drr->drr_u.drr_object); 318219089Spjd 319168404Spjd if (dnp == NULL || dnp->dn_type == DMU_OT_NONE) 320235222Smm return (dump_freeobjects(dsp, object, 1)); 321168404Spjd 322235222Smm if (dsp->dsa_pending_op != PENDING_NONE) { 323235222Smm if (dump_bytes(dsp, dsp->dsa_drr, 324235222Smm sizeof (dmu_replay_record_t)) != 0) 325249195Smm return (SET_ERROR(EINTR)); 326235222Smm dsp->dsa_pending_op = PENDING_NONE; 327219089Spjd } 328219089Spjd 329168404Spjd /* write an OBJECT record */ 330235222Smm bzero(dsp->dsa_drr, sizeof (dmu_replay_record_t)); 331235222Smm dsp->dsa_drr->drr_type = DRR_OBJECT; 332219089Spjd drro->drr_object = object; 333219089Spjd drro->drr_type = dnp->dn_type; 334219089Spjd drro->drr_bonustype = dnp->dn_bonustype; 335219089Spjd drro->drr_blksz = dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT; 336219089Spjd drro->drr_bonuslen = dnp->dn_bonuslen; 337219089Spjd drro->drr_checksumtype = dnp->dn_checksum; 338219089Spjd drro->drr_compress = dnp->dn_compress; 339235222Smm drro->drr_toguid = dsp->dsa_toguid; 340168404Spjd 341235222Smm if (dump_bytes(dsp, dsp->dsa_drr, sizeof (dmu_replay_record_t)) != 0) 342249195Smm return (SET_ERROR(EINTR)); 343168404Spjd 344235222Smm if (dump_bytes(dsp, DN_BONUS(dnp), P2ROUNDUP(dnp->dn_bonuslen, 8)) != 0) 345249195Smm return (SET_ERROR(EINTR)); 346168404Spjd 347253821Sdelphij /* Free anything past the end of the file. */ 348235222Smm if (dump_free(dsp, object, (dnp->dn_maxblkid + 1) * 349253821Sdelphij (dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT), -1ULL) != 0) 350249195Smm return (SET_ERROR(EINTR)); 351248571Smm if (dsp->dsa_err != 0) 352249195Smm return (SET_ERROR(EINTR)); 353168404Spjd return (0); 354168404Spjd} 355168404Spjd 356168404Spjd#define BP_SPAN(dnp, level) \ 357168404Spjd (((uint64_t)dnp->dn_datablkszsec) << (SPA_MINBLOCKSHIFT + \ 358168404Spjd (level) * (dnp->dn_indblkshift - SPA_BLKPTRSHIFT))) 359168404Spjd 360219089Spjd/* ARGSUSED */ 361168404Spjdstatic int 362246666Smmbackup_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, 363219089Spjd const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg) 364168404Spjd{ 365235222Smm dmu_sendarg_t *dsp = arg; 366168404Spjd dmu_object_type_t type = bp ? BP_GET_TYPE(bp) : DMU_OT_NONE; 367168404Spjd int err = 0; 368168404Spjd 369185029Spjd if (issig(JUSTLOOKING) && issig(FORREAL)) 370249195Smm return (SET_ERROR(EINTR)); 371168404Spjd 372219089Spjd if (zb->zb_object != DMU_META_DNODE_OBJECT && 373219089Spjd DMU_OBJECT_IS_SPECIAL(zb->zb_object)) { 374209962Smm return (0); 375219089Spjd } else if (bp == NULL && zb->zb_object == DMU_META_DNODE_OBJECT) { 376208047Smm uint64_t span = BP_SPAN(dnp, zb->zb_level); 377208047Smm uint64_t dnobj = (zb->zb_blkid * span) >> DNODE_SHIFT; 378235222Smm err = dump_freeobjects(dsp, dnobj, span >> DNODE_SHIFT); 379168404Spjd } else if (bp == NULL) { 380208047Smm uint64_t span = BP_SPAN(dnp, zb->zb_level); 381235222Smm err = dump_free(dsp, zb->zb_object, zb->zb_blkid * span, span); 382208047Smm } else if (zb->zb_level > 0 || type == DMU_OT_OBJSET) { 383208047Smm return (0); 384208047Smm } else if (type == DMU_OT_DNODE) { 385208047Smm dnode_phys_t *blk; 386168404Spjd int i; 387168404Spjd int blksz = BP_GET_LSIZE(bp); 388208047Smm uint32_t aflags = ARC_WAIT; 389208047Smm arc_buf_t *abuf; 390168404Spjd 391246666Smm if (arc_read(NULL, spa, bp, arc_getbuf_func, &abuf, 392246666Smm ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, 393246666Smm &aflags, zb) != 0) 394249195Smm return (SET_ERROR(EIO)); 395208047Smm 396208047Smm blk = abuf->b_data; 397168404Spjd for (i = 0; i < blksz >> DNODE_SHIFT; i++) { 398208047Smm uint64_t dnobj = (zb->zb_blkid << 399208047Smm (DNODE_BLOCK_SHIFT - DNODE_SHIFT)) + i; 400235222Smm err = dump_dnode(dsp, dnobj, blk+i); 401248571Smm if (err != 0) 402168404Spjd break; 403168404Spjd } 404208047Smm (void) arc_buf_remove_ref(abuf, &abuf); 405219089Spjd } else if (type == DMU_OT_SA) { 406208047Smm uint32_t aflags = ARC_WAIT; 407208047Smm arc_buf_t *abuf; 408168404Spjd int blksz = BP_GET_LSIZE(bp); 409168404Spjd 410246666Smm if (arc_read(NULL, spa, bp, arc_getbuf_func, &abuf, 411246666Smm ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, 412246666Smm &aflags, zb) != 0) 413249195Smm return (SET_ERROR(EIO)); 414168404Spjd 415235222Smm err = dump_spill(dsp, zb->zb_object, blksz, abuf->b_data); 416219089Spjd (void) arc_buf_remove_ref(abuf, &abuf); 417219089Spjd } else { /* it's a level-0 block of a regular object */ 418219089Spjd uint32_t aflags = ARC_WAIT; 419219089Spjd arc_buf_t *abuf; 420219089Spjd int blksz = BP_GET_LSIZE(bp); 421219089Spjd 422246666Smm if (arc_read(NULL, spa, bp, arc_getbuf_func, &abuf, 423246666Smm ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, 424246666Smm &aflags, zb) != 0) { 425228103Smm if (zfs_send_corrupt_data) { 426228103Smm /* Send a block filled with 0x"zfs badd bloc" */ 427228103Smm abuf = arc_buf_alloc(spa, blksz, &abuf, 428228103Smm ARC_BUFC_DATA); 429228103Smm uint64_t *ptr; 430228103Smm for (ptr = abuf->b_data; 431228103Smm (char *)ptr < (char *)abuf->b_data + blksz; 432228103Smm ptr++) 433228103Smm *ptr = 0x2f5baddb10c; 434228103Smm } else { 435249195Smm return (SET_ERROR(EIO)); 436228103Smm } 437228103Smm } 438219089Spjd 439235222Smm err = dump_data(dsp, type, zb->zb_object, zb->zb_blkid * blksz, 440219089Spjd blksz, bp, abuf->b_data); 441208047Smm (void) arc_buf_remove_ref(abuf, &abuf); 442168404Spjd } 443168404Spjd 444168404Spjd ASSERT(err == 0 || err == EINTR); 445168404Spjd return (err); 446168404Spjd} 447168404Spjd 448248571Smm/* 449248571Smm * Releases dp, ds, and fromds, using the specified tag. 450248571Smm */ 451248571Smmstatic int 452248571Smmdmu_send_impl(void *tag, dsl_pool_t *dp, dsl_dataset_t *ds, 453248571Smm#ifdef illumos 454248571Smm dsl_dataset_t *fromds, int outfd, vnode_t *vp, offset_t *off) 455248571Smm#else 456248571Smm dsl_dataset_t *fromds, int outfd, struct file *fp, offset_t *off) 457248571Smm#endif 458168404Spjd{ 459248571Smm objset_t *os; 460168404Spjd dmu_replay_record_t *drr; 461235222Smm dmu_sendarg_t *dsp; 462168404Spjd int err; 463185029Spjd uint64_t fromtxg = 0; 464168404Spjd 465248571Smm if (fromds != NULL && !dsl_dataset_is_before(ds, fromds)) { 466248571Smm dsl_dataset_rele(fromds, tag); 467248571Smm dsl_dataset_rele(ds, tag); 468248571Smm dsl_pool_rele(dp, tag); 469249195Smm return (SET_ERROR(EXDEV)); 470248571Smm } 471168404Spjd 472248571Smm err = dmu_objset_from_ds(ds, &os); 473248571Smm if (err != 0) { 474248571Smm if (fromds != NULL) 475248571Smm dsl_dataset_rele(fromds, tag); 476248571Smm dsl_dataset_rele(ds, tag); 477248571Smm dsl_pool_rele(dp, tag); 478248571Smm return (err); 479185029Spjd } 480185029Spjd 481168404Spjd drr = kmem_zalloc(sizeof (dmu_replay_record_t), KM_SLEEP); 482168404Spjd drr->drr_type = DRR_BEGIN; 483168404Spjd drr->drr_u.drr_begin.drr_magic = DMU_BACKUP_MAGIC; 484219089Spjd DMU_SET_STREAM_HDRTYPE(drr->drr_u.drr_begin.drr_versioninfo, 485219089Spjd DMU_SUBSTREAM); 486219089Spjd 487219089Spjd#ifdef _KERNEL 488248571Smm if (dmu_objset_type(os) == DMU_OST_ZFS) { 489219089Spjd uint64_t version; 490248571Smm if (zfs_get_zplprop(os, ZFS_PROP_VERSION, &version) != 0) { 491235222Smm kmem_free(drr, sizeof (dmu_replay_record_t)); 492248571Smm if (fromds != NULL) 493248571Smm dsl_dataset_rele(fromds, tag); 494248571Smm dsl_dataset_rele(ds, tag); 495248571Smm dsl_pool_rele(dp, tag); 496249195Smm return (SET_ERROR(EINVAL)); 497235222Smm } 498248571Smm if (version >= ZPL_VERSION_SA) { 499219089Spjd DMU_SET_FEATUREFLAGS( 500219089Spjd drr->drr_u.drr_begin.drr_versioninfo, 501219089Spjd DMU_BACKUP_FEATURE_SA_SPILL); 502219089Spjd } 503219089Spjd } 504219089Spjd#endif 505219089Spjd 506168404Spjd drr->drr_u.drr_begin.drr_creation_time = 507168404Spjd ds->ds_phys->ds_creation_time; 508248571Smm drr->drr_u.drr_begin.drr_type = dmu_objset_type(os); 509248571Smm if (fromds != NULL && ds->ds_dir != fromds->ds_dir) 510185029Spjd drr->drr_u.drr_begin.drr_flags |= DRR_FLAG_CLONE; 511168404Spjd drr->drr_u.drr_begin.drr_toguid = ds->ds_phys->ds_guid; 512185029Spjd if (ds->ds_phys->ds_flags & DS_FLAG_CI_DATASET) 513185029Spjd drr->drr_u.drr_begin.drr_flags |= DRR_FLAG_CI_DATA; 514185029Spjd 515248571Smm if (fromds != NULL) 516168404Spjd drr->drr_u.drr_begin.drr_fromguid = fromds->ds_phys->ds_guid; 517168404Spjd dsl_dataset_name(ds, drr->drr_u.drr_begin.drr_toname); 518168404Spjd 519248571Smm if (fromds != NULL) { 520185029Spjd fromtxg = fromds->ds_phys->ds_creation_txg; 521248571Smm dsl_dataset_rele(fromds, tag); 522248571Smm fromds = NULL; 523248571Smm } 524185029Spjd 525235222Smm dsp = kmem_zalloc(sizeof (dmu_sendarg_t), KM_SLEEP); 526168404Spjd 527235222Smm dsp->dsa_drr = drr; 528235222Smm dsp->dsa_outfd = outfd; 529235222Smm dsp->dsa_proc = curproc; 530235222Smm dsp->dsa_td = curthread; 531235222Smm dsp->dsa_fp = fp; 532248571Smm dsp->dsa_os = os; 533235222Smm dsp->dsa_off = off; 534235222Smm dsp->dsa_toguid = ds->ds_phys->ds_guid; 535235222Smm ZIO_SET_CHECKSUM(&dsp->dsa_zc, 0, 0, 0, 0); 536235222Smm dsp->dsa_pending_op = PENDING_NONE; 537253821Sdelphij dsp->dsa_incremental = (fromtxg != 0); 538235222Smm 539235222Smm mutex_enter(&ds->ds_sendstream_lock); 540235222Smm list_insert_head(&ds->ds_sendstreams, dsp); 541235222Smm mutex_exit(&ds->ds_sendstream_lock); 542235222Smm 543249042Smm dsl_dataset_long_hold(ds, FTAG); 544249042Smm dsl_pool_rele(dp, tag); 545249042Smm 546235222Smm if (dump_bytes(dsp, drr, sizeof (dmu_replay_record_t)) != 0) { 547235222Smm err = dsp->dsa_err; 548235222Smm goto out; 549168404Spjd } 550168404Spjd 551208047Smm err = traverse_dataset(ds, fromtxg, TRAVERSE_PRE | TRAVERSE_PREFETCH, 552235222Smm backup_cb, dsp); 553168404Spjd 554235222Smm if (dsp->dsa_pending_op != PENDING_NONE) 555235222Smm if (dump_bytes(dsp, drr, sizeof (dmu_replay_record_t)) != 0) 556249195Smm err = SET_ERROR(EINTR); 557219089Spjd 558248571Smm if (err != 0) { 559248571Smm if (err == EINTR && dsp->dsa_err != 0) 560235222Smm err = dsp->dsa_err; 561235222Smm goto out; 562168404Spjd } 563168404Spjd 564168404Spjd bzero(drr, sizeof (dmu_replay_record_t)); 565168404Spjd drr->drr_type = DRR_END; 566235222Smm drr->drr_u.drr_end.drr_checksum = dsp->dsa_zc; 567235222Smm drr->drr_u.drr_end.drr_toguid = dsp->dsa_toguid; 568168404Spjd 569235222Smm if (dump_bytes(dsp, drr, sizeof (dmu_replay_record_t)) != 0) { 570235222Smm err = dsp->dsa_err; 571235222Smm goto out; 572168404Spjd } 573168404Spjd 574235222Smmout: 575235222Smm mutex_enter(&ds->ds_sendstream_lock); 576235222Smm list_remove(&ds->ds_sendstreams, dsp); 577235222Smm mutex_exit(&ds->ds_sendstream_lock); 578235222Smm 579168404Spjd kmem_free(drr, sizeof (dmu_replay_record_t)); 580235222Smm kmem_free(dsp, sizeof (dmu_sendarg_t)); 581168404Spjd 582248571Smm dsl_dataset_long_rele(ds, FTAG); 583248571Smm dsl_dataset_rele(ds, tag); 584248571Smm 585235222Smm return (err); 586168404Spjd} 587168404Spjd 588228103Smmint 589248571Smmdmu_send_obj(const char *pool, uint64_t tosnap, uint64_t fromsnap, 590248571Smm#ifdef illumos 591248571Smm int outfd, vnode_t *vp, offset_t *off) 592248571Smm#else 593248571Smm int outfd, struct file *fp, offset_t *off) 594248571Smm#endif 595228103Smm{ 596248571Smm dsl_pool_t *dp; 597248571Smm dsl_dataset_t *ds; 598248571Smm dsl_dataset_t *fromds = NULL; 599248571Smm int err; 600248571Smm 601248571Smm err = dsl_pool_hold(pool, FTAG, &dp); 602248571Smm if (err != 0) 603248571Smm return (err); 604248571Smm 605248571Smm err = dsl_dataset_hold_obj(dp, tosnap, FTAG, &ds); 606248571Smm if (err != 0) { 607248571Smm dsl_pool_rele(dp, FTAG); 608248571Smm return (err); 609248571Smm } 610248571Smm 611248571Smm if (fromsnap != 0) { 612248571Smm err = dsl_dataset_hold_obj(dp, fromsnap, FTAG, &fromds); 613248571Smm if (err != 0) { 614248571Smm dsl_dataset_rele(ds, FTAG); 615248571Smm dsl_pool_rele(dp, FTAG); 616248571Smm return (err); 617248571Smm } 618248571Smm } 619248571Smm 620248571Smm return (dmu_send_impl(FTAG, dp, ds, fromds, outfd, fp, off)); 621248571Smm} 622248571Smm 623248571Smmint 624248571Smmdmu_send(const char *tosnap, const char *fromsnap, 625248571Smm#ifdef illumos 626248571Smm int outfd, vnode_t *vp, offset_t *off) 627248571Smm#else 628248571Smm int outfd, struct file *fp, offset_t *off) 629248571Smm#endif 630248571Smm{ 631248571Smm dsl_pool_t *dp; 632248571Smm dsl_dataset_t *ds; 633248571Smm dsl_dataset_t *fromds = NULL; 634248571Smm int err; 635248571Smm 636248571Smm if (strchr(tosnap, '@') == NULL) 637249195Smm return (SET_ERROR(EINVAL)); 638248571Smm if (fromsnap != NULL && strchr(fromsnap, '@') == NULL) 639249195Smm return (SET_ERROR(EINVAL)); 640248571Smm 641248571Smm err = dsl_pool_hold(tosnap, FTAG, &dp); 642248571Smm if (err != 0) 643248571Smm return (err); 644248571Smm 645248571Smm err = dsl_dataset_hold(dp, tosnap, FTAG, &ds); 646248571Smm if (err != 0) { 647248571Smm dsl_pool_rele(dp, FTAG); 648248571Smm return (err); 649248571Smm } 650248571Smm 651248571Smm if (fromsnap != NULL) { 652248571Smm err = dsl_dataset_hold(dp, fromsnap, FTAG, &fromds); 653248571Smm if (err != 0) { 654248571Smm dsl_dataset_rele(ds, FTAG); 655248571Smm dsl_pool_rele(dp, FTAG); 656248571Smm return (err); 657248571Smm } 658248571Smm } 659248571Smm return (dmu_send_impl(FTAG, dp, ds, fromds, outfd, fp, off)); 660248571Smm} 661248571Smm 662248571Smmint 663248571Smmdmu_send_estimate(dsl_dataset_t *ds, dsl_dataset_t *fromds, uint64_t *sizep) 664248571Smm{ 665228103Smm dsl_pool_t *dp = ds->ds_dir->dd_pool; 666228103Smm int err; 667228103Smm uint64_t size; 668228103Smm 669248571Smm ASSERT(dsl_pool_config_held(dp)); 670248571Smm 671228103Smm /* tosnap must be a snapshot */ 672248571Smm if (!dsl_dataset_is_snapshot(ds)) 673249195Smm return (SET_ERROR(EINVAL)); 674228103Smm 675248571Smm /* 676248571Smm * fromsnap must be an earlier snapshot from the same fs as tosnap, 677248571Smm * or the origin's fs. 678248571Smm */ 679248571Smm if (fromds != NULL && !dsl_dataset_is_before(ds, fromds)) 680249195Smm return (SET_ERROR(EXDEV)); 681228103Smm 682228103Smm /* Get uncompressed size estimate of changed data. */ 683228103Smm if (fromds == NULL) { 684228103Smm size = ds->ds_phys->ds_uncompressed_bytes; 685228103Smm } else { 686228103Smm uint64_t used, comp; 687228103Smm err = dsl_dataset_space_written(fromds, ds, 688228103Smm &used, &comp, &size); 689248571Smm if (err != 0) 690228103Smm return (err); 691228103Smm } 692228103Smm 693228103Smm /* 694228103Smm * Assume that space (both on-disk and in-stream) is dominated by 695228103Smm * data. We will adjust for indirect blocks and the copies property, 696228103Smm * but ignore per-object space used (eg, dnodes and DRR_OBJECT records). 697228103Smm */ 698228103Smm 699228103Smm /* 700228103Smm * Subtract out approximate space used by indirect blocks. 701228103Smm * Assume most space is used by data blocks (non-indirect, non-dnode). 702228103Smm * Assume all blocks are recordsize. Assume ditto blocks and 703228103Smm * internal fragmentation counter out compression. 704228103Smm * 705228103Smm * Therefore, space used by indirect blocks is sizeof(blkptr_t) per 706228103Smm * block, which we observe in practice. 707228103Smm */ 708228103Smm uint64_t recordsize; 709248571Smm err = dsl_prop_get_int_ds(ds, "recordsize", &recordsize); 710248571Smm if (err != 0) 711228103Smm return (err); 712228103Smm size -= size / recordsize * sizeof (blkptr_t); 713228103Smm 714228103Smm /* Add in the space for the record associated with each block. */ 715228103Smm size += size / recordsize * sizeof (dmu_replay_record_t); 716228103Smm 717228103Smm *sizep = size; 718228103Smm 719228103Smm return (0); 720228103Smm} 721228103Smm 722248571Smmtypedef struct dmu_recv_begin_arg { 723248571Smm const char *drba_origin; 724248571Smm dmu_recv_cookie_t *drba_cookie; 725248571Smm cred_t *drba_cred; 726253820Sdelphij uint64_t drba_snapobj; 727248571Smm} dmu_recv_begin_arg_t; 728168404Spjd 729168404Spjdstatic int 730248571Smmrecv_begin_check_existing_impl(dmu_recv_begin_arg_t *drba, dsl_dataset_t *ds, 731248571Smm uint64_t fromguid) 732168404Spjd{ 733185029Spjd uint64_t val; 734248571Smm int error; 735248571Smm dsl_pool_t *dp = ds->ds_dir->dd_pool; 736185029Spjd 737248571Smm /* temporary clone name must not exist */ 738248571Smm error = zap_lookup(dp->dp_meta_objset, 739248571Smm ds->ds_dir->dd_phys->dd_child_dir_zapobj, recv_clone_name, 740248571Smm 8, 1, &val); 741248571Smm if (error != ENOENT) 742248571Smm return (error == 0 ? EBUSY : error); 743248571Smm 744219089Spjd /* new snapshot name must not exist */ 745248571Smm error = zap_lookup(dp->dp_meta_objset, 746248571Smm ds->ds_phys->ds_snapnames_zapobj, drba->drba_cookie->drc_tosnap, 747248571Smm 8, 1, &val); 748248571Smm if (error != ENOENT) 749248571Smm return (error == 0 ? EEXIST : error); 750168404Spjd 751248571Smm if (fromguid != 0) { 752253820Sdelphij dsl_dataset_t *snap; 753253820Sdelphij uint64_t obj = ds->ds_phys->ds_prev_snap_obj; 754253820Sdelphij 755253820Sdelphij /* Find snapshot in this dir that matches fromguid. */ 756253820Sdelphij while (obj != 0) { 757253820Sdelphij error = dsl_dataset_hold_obj(dp, obj, FTAG, 758253820Sdelphij &snap); 759253820Sdelphij if (error != 0) 760253820Sdelphij return (SET_ERROR(ENODEV)); 761253820Sdelphij if (snap->ds_dir != ds->ds_dir) { 762253820Sdelphij dsl_dataset_rele(snap, FTAG); 763253820Sdelphij return (SET_ERROR(ENODEV)); 764253820Sdelphij } 765253820Sdelphij if (snap->ds_phys->ds_guid == fromguid) 766253820Sdelphij break; 767253820Sdelphij obj = snap->ds_phys->ds_prev_snap_obj; 768253820Sdelphij dsl_dataset_rele(snap, FTAG); 769253820Sdelphij } 770253820Sdelphij if (obj == 0) 771249195Smm return (SET_ERROR(ENODEV)); 772168404Spjd 773253820Sdelphij if (drba->drba_cookie->drc_force) { 774253820Sdelphij drba->drba_snapobj = obj; 775253820Sdelphij } else { 776253820Sdelphij /* 777253820Sdelphij * If we are not forcing, there must be no 778253820Sdelphij * changes since fromsnap. 779253820Sdelphij */ 780253820Sdelphij if (dsl_dataset_modified_since_snap(ds, snap)) { 781219089Spjd dsl_dataset_rele(snap, FTAG); 782253820Sdelphij return (SET_ERROR(ETXTBSY)); 783219089Spjd } 784253820Sdelphij drba->drba_snapobj = ds->ds_prev->ds_object; 785219089Spjd } 786253820Sdelphij 787253820Sdelphij dsl_dataset_rele(snap, FTAG); 788219089Spjd } else { 789219089Spjd /* if full, most recent snapshot must be $ORIGIN */ 790219089Spjd if (ds->ds_phys->ds_prev_snap_txg >= TXG_INITIAL) 791249195Smm return (SET_ERROR(ENODEV)); 792253820Sdelphij drba->drba_snapobj = ds->ds_phys->ds_prev_snap_obj; 793219089Spjd } 794219089Spjd 795248571Smm return (0); 796168404Spjd 797168404Spjd} 798168404Spjd 799248571Smmstatic int 800248571Smmdmu_recv_begin_check(void *arg, dmu_tx_t *tx) 801248571Smm{ 802248571Smm dmu_recv_begin_arg_t *drba = arg; 803248571Smm dsl_pool_t *dp = dmu_tx_pool(tx); 804248571Smm struct drr_begin *drrb = drba->drba_cookie->drc_drrb; 805248571Smm uint64_t fromguid = drrb->drr_fromguid; 806248571Smm int flags = drrb->drr_flags; 807248571Smm int error; 808248571Smm dsl_dataset_t *ds; 809248571Smm const char *tofs = drba->drba_cookie->drc_tofs; 810248571Smm 811248571Smm /* already checked */ 812248571Smm ASSERT3U(drrb->drr_magic, ==, DMU_BACKUP_MAGIC); 813248571Smm 814248571Smm if (DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) == 815248571Smm DMU_COMPOUNDSTREAM || 816248571Smm drrb->drr_type >= DMU_OST_NUMTYPES || 817248571Smm ((flags & DRR_FLAG_CLONE) && drba->drba_origin == NULL)) 818249195Smm return (SET_ERROR(EINVAL)); 819248571Smm 820248571Smm /* Verify pool version supports SA if SA_SPILL feature set */ 821248571Smm if ((DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) & 822248571Smm DMU_BACKUP_FEATURE_SA_SPILL) && 823248571Smm spa_version(dp->dp_spa) < SPA_VERSION_SA) { 824249195Smm return (SET_ERROR(ENOTSUP)); 825248571Smm } 826248571Smm 827248571Smm error = dsl_dataset_hold(dp, tofs, FTAG, &ds); 828248571Smm if (error == 0) { 829248571Smm /* target fs already exists; recv into temp clone */ 830248571Smm 831248571Smm /* Can't recv a clone into an existing fs */ 832248571Smm if (flags & DRR_FLAG_CLONE) { 833248571Smm dsl_dataset_rele(ds, FTAG); 834249195Smm return (SET_ERROR(EINVAL)); 835248571Smm } 836248571Smm 837248571Smm error = recv_begin_check_existing_impl(drba, ds, fromguid); 838248571Smm dsl_dataset_rele(ds, FTAG); 839248571Smm } else if (error == ENOENT) { 840248571Smm /* target fs does not exist; must be a full backup or clone */ 841248571Smm char buf[MAXNAMELEN]; 842248571Smm 843248571Smm /* 844248571Smm * If it's a non-clone incremental, we are missing the 845248571Smm * target fs, so fail the recv. 846248571Smm */ 847248571Smm if (fromguid != 0 && !(flags & DRR_FLAG_CLONE)) 848249195Smm return (SET_ERROR(ENOENT)); 849248571Smm 850248571Smm /* Open the parent of tofs */ 851248571Smm ASSERT3U(strlen(tofs), <, MAXNAMELEN); 852248571Smm (void) strlcpy(buf, tofs, strrchr(tofs, '/') - tofs + 1); 853248571Smm error = dsl_dataset_hold(dp, buf, FTAG, &ds); 854248571Smm if (error != 0) 855248571Smm return (error); 856248571Smm 857248571Smm if (drba->drba_origin != NULL) { 858248571Smm dsl_dataset_t *origin; 859248571Smm error = dsl_dataset_hold(dp, drba->drba_origin, 860248571Smm FTAG, &origin); 861248571Smm if (error != 0) { 862248571Smm dsl_dataset_rele(ds, FTAG); 863248571Smm return (error); 864248571Smm } 865248571Smm if (!dsl_dataset_is_snapshot(origin)) { 866248571Smm dsl_dataset_rele(origin, FTAG); 867248571Smm dsl_dataset_rele(ds, FTAG); 868249195Smm return (SET_ERROR(EINVAL)); 869248571Smm } 870248571Smm if (origin->ds_phys->ds_guid != fromguid) { 871248571Smm dsl_dataset_rele(origin, FTAG); 872248571Smm dsl_dataset_rele(ds, FTAG); 873249195Smm return (SET_ERROR(ENODEV)); 874248571Smm } 875248571Smm dsl_dataset_rele(origin, FTAG); 876248571Smm } 877248571Smm dsl_dataset_rele(ds, FTAG); 878248571Smm error = 0; 879248571Smm } 880248571Smm return (error); 881248571Smm} 882248571Smm 883168404Spjdstatic void 884248571Smmdmu_recv_begin_sync(void *arg, dmu_tx_t *tx) 885168404Spjd{ 886248571Smm dmu_recv_begin_arg_t *drba = arg; 887248571Smm dsl_pool_t *dp = dmu_tx_pool(tx); 888248571Smm struct drr_begin *drrb = drba->drba_cookie->drc_drrb; 889248571Smm const char *tofs = drba->drba_cookie->drc_tofs; 890248571Smm dsl_dataset_t *ds, *newds; 891185029Spjd uint64_t dsobj; 892248571Smm int error; 893248571Smm uint64_t crflags; 894168404Spjd 895248571Smm crflags = (drrb->drr_flags & DRR_FLAG_CI_DATA) ? 896248571Smm DS_FLAG_CI_DATASET : 0; 897168404Spjd 898248571Smm error = dsl_dataset_hold(dp, tofs, FTAG, &ds); 899248571Smm if (error == 0) { 900248571Smm /* create temporary clone */ 901253820Sdelphij dsl_dataset_t *snap = NULL; 902253820Sdelphij if (drba->drba_snapobj != 0) { 903253820Sdelphij VERIFY0(dsl_dataset_hold_obj(dp, 904253820Sdelphij drba->drba_snapobj, FTAG, &snap)); 905253820Sdelphij } 906248571Smm dsobj = dsl_dataset_create_sync(ds->ds_dir, recv_clone_name, 907253820Sdelphij snap, crflags, drba->drba_cred, tx); 908253820Sdelphij dsl_dataset_rele(snap, FTAG); 909248571Smm dsl_dataset_rele(ds, FTAG); 910248571Smm } else { 911248571Smm dsl_dir_t *dd; 912248571Smm const char *tail; 913248571Smm dsl_dataset_t *origin = NULL; 914248571Smm 915248571Smm VERIFY0(dsl_dir_hold(dp, tofs, FTAG, &dd, &tail)); 916248571Smm 917248571Smm if (drba->drba_origin != NULL) { 918248571Smm VERIFY0(dsl_dataset_hold(dp, drba->drba_origin, 919248571Smm FTAG, &origin)); 920248571Smm } 921248571Smm 922248571Smm /* Create new dataset. */ 923248571Smm dsobj = dsl_dataset_create_sync(dd, 924248571Smm strrchr(tofs, '/') + 1, 925248571Smm origin, crflags, drba->drba_cred, tx); 926248571Smm if (origin != NULL) 927248571Smm dsl_dataset_rele(origin, FTAG); 928248571Smm dsl_dir_rele(dd, FTAG); 929248571Smm drba->drba_cookie->drc_newfs = B_TRUE; 930248571Smm } 931248571Smm VERIFY0(dsl_dataset_own_obj(dp, dsobj, dmu_recv_tag, &newds)); 932248571Smm 933248571Smm dmu_buf_will_dirty(newds->ds_dbuf, tx); 934248571Smm newds->ds_phys->ds_flags |= DS_FLAG_INCONSISTENT; 935248571Smm 936219089Spjd /* 937219089Spjd * If we actually created a non-clone, we need to create the 938219089Spjd * objset in our new dataset. 939219089Spjd */ 940248571Smm if (BP_IS_HOLE(dsl_dataset_get_blkptr(newds))) { 941219089Spjd (void) dmu_objset_create_impl(dp->dp_spa, 942248571Smm newds, dsl_dataset_get_blkptr(newds), drrb->drr_type, tx); 943219089Spjd } 944168404Spjd 945248571Smm drba->drba_cookie->drc_ds = newds; 946185029Spjd 947248571Smm spa_history_log_internal_ds(newds, "receive", tx, ""); 948168404Spjd} 949168404Spjd 950185029Spjd/* 951185029Spjd * NB: callers *MUST* call dmu_recv_stream() if dmu_recv_begin() 952185029Spjd * succeeds; otherwise we will leak the holds on the datasets. 953185029Spjd */ 954185029Spjdint 955248571Smmdmu_recv_begin(char *tofs, char *tosnap, struct drr_begin *drrb, 956248571Smm boolean_t force, char *origin, dmu_recv_cookie_t *drc) 957168404Spjd{ 958248571Smm dmu_recv_begin_arg_t drba = { 0 }; 959248571Smm dmu_replay_record_t *drr; 960168404Spjd 961185029Spjd bzero(drc, sizeof (dmu_recv_cookie_t)); 962185029Spjd drc->drc_drrb = drrb; 963185029Spjd drc->drc_tosnap = tosnap; 964248571Smm drc->drc_tofs = tofs; 965185029Spjd drc->drc_force = force; 966168404Spjd 967248571Smm if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC)) 968248571Smm drc->drc_byteswap = B_TRUE; 969248571Smm else if (drrb->drr_magic != DMU_BACKUP_MAGIC) 970249195Smm return (SET_ERROR(EINVAL)); 971168404Spjd 972248571Smm drr = kmem_zalloc(sizeof (dmu_replay_record_t), KM_SLEEP); 973248571Smm drr->drr_type = DRR_BEGIN; 974248571Smm drr->drr_u.drr_begin = *drc->drc_drrb; 975248571Smm if (drc->drc_byteswap) { 976248571Smm fletcher_4_incremental_byteswap(drr, 977248571Smm sizeof (dmu_replay_record_t), &drc->drc_cksum); 978248571Smm } else { 979248571Smm fletcher_4_incremental_native(drr, 980248571Smm sizeof (dmu_replay_record_t), &drc->drc_cksum); 981248571Smm } 982248571Smm kmem_free(drr, sizeof (dmu_replay_record_t)); 983219089Spjd 984248571Smm if (drc->drc_byteswap) { 985248571Smm drrb->drr_magic = BSWAP_64(drrb->drr_magic); 986248571Smm drrb->drr_versioninfo = BSWAP_64(drrb->drr_versioninfo); 987248571Smm drrb->drr_creation_time = BSWAP_64(drrb->drr_creation_time); 988248571Smm drrb->drr_type = BSWAP_32(drrb->drr_type); 989248571Smm drrb->drr_toguid = BSWAP_64(drrb->drr_toguid); 990248571Smm drrb->drr_fromguid = BSWAP_64(drrb->drr_fromguid); 991248571Smm } 992168404Spjd 993248571Smm drba.drba_origin = origin; 994248571Smm drba.drba_cookie = drc; 995248571Smm drba.drba_cred = CRED(); 996219089Spjd 997248571Smm return (dsl_sync_task(tofs, dmu_recv_begin_check, dmu_recv_begin_sync, 998248571Smm &drba, 5)); 999168404Spjd} 1000168404Spjd 1001185029Spjdstruct restorearg { 1002185029Spjd int err; 1003248571Smm boolean_t byteswap; 1004185029Spjd kthread_t *td; 1005185029Spjd struct file *fp; 1006185029Spjd char *buf; 1007185029Spjd uint64_t voff; 1008185029Spjd int bufsize; /* amount of memory allocated for buf */ 1009185029Spjd zio_cksum_t cksum; 1010219089Spjd avl_tree_t *guid_to_ds_map; 1011185029Spjd}; 1012185029Spjd 1013219089Spjdtypedef struct guid_map_entry { 1014219089Spjd uint64_t guid; 1015219089Spjd dsl_dataset_t *gme_ds; 1016219089Spjd avl_node_t avlnode; 1017219089Spjd} guid_map_entry_t; 1018219089Spjd 1019168404Spjdstatic int 1020219089Spjdguid_compare(const void *arg1, const void *arg2) 1021168404Spjd{ 1022219089Spjd const guid_map_entry_t *gmep1 = arg1; 1023219089Spjd const guid_map_entry_t *gmep2 = arg2; 1024219089Spjd 1025219089Spjd if (gmep1->guid < gmep2->guid) 1026219089Spjd return (-1); 1027219089Spjd else if (gmep1->guid > gmep2->guid) 1028219089Spjd return (1); 1029219089Spjd return (0); 1030219089Spjd} 1031219089Spjd 1032219089Spjdstatic void 1033219089Spjdfree_guid_map_onexit(void *arg) 1034219089Spjd{ 1035219089Spjd avl_tree_t *ca = arg; 1036219089Spjd void *cookie = NULL; 1037219089Spjd guid_map_entry_t *gmep; 1038219089Spjd 1039219089Spjd while ((gmep = avl_destroy_nodes(ca, &cookie)) != NULL) { 1040248571Smm dsl_dataset_long_rele(gmep->gme_ds, gmep); 1041249196Smm dsl_dataset_rele(gmep->gme_ds, gmep); 1042219089Spjd kmem_free(gmep, sizeof (guid_map_entry_t)); 1043219089Spjd } 1044219089Spjd avl_destroy(ca); 1045219089Spjd kmem_free(ca, sizeof (avl_tree_t)); 1046219089Spjd} 1047219089Spjd 1048219089Spjdstatic int 1049219089Spjdrestore_bytes(struct restorearg *ra, void *buf, int len, off_t off, ssize_t *resid) 1050219089Spjd{ 1051168404Spjd struct uio auio; 1052168404Spjd struct iovec aiov; 1053168404Spjd int error; 1054168404Spjd 1055168404Spjd aiov.iov_base = buf; 1056168404Spjd aiov.iov_len = len; 1057168404Spjd auio.uio_iov = &aiov; 1058168404Spjd auio.uio_iovcnt = 1; 1059168404Spjd auio.uio_resid = len; 1060169170Spjd auio.uio_segflg = UIO_SYSSPACE; 1061168404Spjd auio.uio_rw = UIO_READ; 1062168404Spjd auio.uio_offset = off; 1063168404Spjd auio.uio_td = ra->td; 1064168404Spjd#ifdef _KERNEL 1065168404Spjd error = fo_read(ra->fp, &auio, ra->td->td_ucred, FOF_OFFSET, ra->td); 1066168404Spjd#else 1067168404Spjd fprintf(stderr, "%s: returning EOPNOTSUPP\n", __func__); 1068168404Spjd error = EOPNOTSUPP; 1069168404Spjd#endif 1070168404Spjd *resid = auio.uio_resid; 1071168404Spjd return (error); 1072168404Spjd} 1073168404Spjd 1074168404Spjdstatic void * 1075168404Spjdrestore_read(struct restorearg *ra, int len) 1076168404Spjd{ 1077168404Spjd void *rv; 1078185029Spjd int done = 0; 1079168404Spjd 1080168404Spjd /* some things will require 8-byte alignment, so everything must */ 1081240415Smm ASSERT0(len % 8); 1082168404Spjd 1083185029Spjd while (done < len) { 1084219089Spjd ssize_t resid; 1085168404Spjd 1086185029Spjd ra->err = restore_bytes(ra, (caddr_t)ra->buf + done, 1087185029Spjd len - done, ra->voff, &resid); 1088168404Spjd 1089185029Spjd if (resid == len - done) 1090249195Smm ra->err = SET_ERROR(EINVAL); 1091185029Spjd ra->voff += len - done - resid; 1092185029Spjd done = len - resid; 1093248571Smm if (ra->err != 0) 1094168404Spjd return (NULL); 1095168404Spjd } 1096168404Spjd 1097185029Spjd ASSERT3U(done, ==, len); 1098185029Spjd rv = ra->buf; 1099168404Spjd if (ra->byteswap) 1100185029Spjd fletcher_4_incremental_byteswap(rv, len, &ra->cksum); 1101168404Spjd else 1102185029Spjd fletcher_4_incremental_native(rv, len, &ra->cksum); 1103168404Spjd return (rv); 1104168404Spjd} 1105168404Spjd 1106168404Spjdstatic void 1107168404Spjdbackup_byteswap(dmu_replay_record_t *drr) 1108168404Spjd{ 1109168404Spjd#define DO64(X) (drr->drr_u.X = BSWAP_64(drr->drr_u.X)) 1110168404Spjd#define DO32(X) (drr->drr_u.X = BSWAP_32(drr->drr_u.X)) 1111168404Spjd drr->drr_type = BSWAP_32(drr->drr_type); 1112185029Spjd drr->drr_payloadlen = BSWAP_32(drr->drr_payloadlen); 1113168404Spjd switch (drr->drr_type) { 1114168404Spjd case DRR_BEGIN: 1115168404Spjd DO64(drr_begin.drr_magic); 1116219089Spjd DO64(drr_begin.drr_versioninfo); 1117168404Spjd DO64(drr_begin.drr_creation_time); 1118168404Spjd DO32(drr_begin.drr_type); 1119185029Spjd DO32(drr_begin.drr_flags); 1120168404Spjd DO64(drr_begin.drr_toguid); 1121168404Spjd DO64(drr_begin.drr_fromguid); 1122168404Spjd break; 1123168404Spjd case DRR_OBJECT: 1124168404Spjd DO64(drr_object.drr_object); 1125168404Spjd /* DO64(drr_object.drr_allocation_txg); */ 1126168404Spjd DO32(drr_object.drr_type); 1127168404Spjd DO32(drr_object.drr_bonustype); 1128168404Spjd DO32(drr_object.drr_blksz); 1129168404Spjd DO32(drr_object.drr_bonuslen); 1130219089Spjd DO64(drr_object.drr_toguid); 1131168404Spjd break; 1132168404Spjd case DRR_FREEOBJECTS: 1133168404Spjd DO64(drr_freeobjects.drr_firstobj); 1134168404Spjd DO64(drr_freeobjects.drr_numobjs); 1135219089Spjd DO64(drr_freeobjects.drr_toguid); 1136168404Spjd break; 1137168404Spjd case DRR_WRITE: 1138168404Spjd DO64(drr_write.drr_object); 1139168404Spjd DO32(drr_write.drr_type); 1140168404Spjd DO64(drr_write.drr_offset); 1141168404Spjd DO64(drr_write.drr_length); 1142219089Spjd DO64(drr_write.drr_toguid); 1143219089Spjd DO64(drr_write.drr_key.ddk_cksum.zc_word[0]); 1144219089Spjd DO64(drr_write.drr_key.ddk_cksum.zc_word[1]); 1145219089Spjd DO64(drr_write.drr_key.ddk_cksum.zc_word[2]); 1146219089Spjd DO64(drr_write.drr_key.ddk_cksum.zc_word[3]); 1147219089Spjd DO64(drr_write.drr_key.ddk_prop); 1148168404Spjd break; 1149219089Spjd case DRR_WRITE_BYREF: 1150219089Spjd DO64(drr_write_byref.drr_object); 1151219089Spjd DO64(drr_write_byref.drr_offset); 1152219089Spjd DO64(drr_write_byref.drr_length); 1153219089Spjd DO64(drr_write_byref.drr_toguid); 1154219089Spjd DO64(drr_write_byref.drr_refguid); 1155219089Spjd DO64(drr_write_byref.drr_refobject); 1156219089Spjd DO64(drr_write_byref.drr_refoffset); 1157219089Spjd DO64(drr_write_byref.drr_key.ddk_cksum.zc_word[0]); 1158219089Spjd DO64(drr_write_byref.drr_key.ddk_cksum.zc_word[1]); 1159219089Spjd DO64(drr_write_byref.drr_key.ddk_cksum.zc_word[2]); 1160219089Spjd DO64(drr_write_byref.drr_key.ddk_cksum.zc_word[3]); 1161219089Spjd DO64(drr_write_byref.drr_key.ddk_prop); 1162219089Spjd break; 1163168404Spjd case DRR_FREE: 1164168404Spjd DO64(drr_free.drr_object); 1165168404Spjd DO64(drr_free.drr_offset); 1166168404Spjd DO64(drr_free.drr_length); 1167219089Spjd DO64(drr_free.drr_toguid); 1168168404Spjd break; 1169219089Spjd case DRR_SPILL: 1170219089Spjd DO64(drr_spill.drr_object); 1171219089Spjd DO64(drr_spill.drr_length); 1172219089Spjd DO64(drr_spill.drr_toguid); 1173219089Spjd break; 1174168404Spjd case DRR_END: 1175168404Spjd DO64(drr_end.drr_checksum.zc_word[0]); 1176168404Spjd DO64(drr_end.drr_checksum.zc_word[1]); 1177168404Spjd DO64(drr_end.drr_checksum.zc_word[2]); 1178168404Spjd DO64(drr_end.drr_checksum.zc_word[3]); 1179219089Spjd DO64(drr_end.drr_toguid); 1180168404Spjd break; 1181168404Spjd } 1182168404Spjd#undef DO64 1183168404Spjd#undef DO32 1184168404Spjd} 1185168404Spjd 1186168404Spjdstatic int 1187168404Spjdrestore_object(struct restorearg *ra, objset_t *os, struct drr_object *drro) 1188168404Spjd{ 1189168404Spjd int err; 1190168404Spjd dmu_tx_t *tx; 1191200727Sdelphij void *data = NULL; 1192168404Spjd 1193168404Spjd if (drro->drr_type == DMU_OT_NONE || 1194236884Smm !DMU_OT_IS_VALID(drro->drr_type) || 1195236884Smm !DMU_OT_IS_VALID(drro->drr_bonustype) || 1196219089Spjd drro->drr_checksumtype >= ZIO_CHECKSUM_FUNCTIONS || 1197168404Spjd drro->drr_compress >= ZIO_COMPRESS_FUNCTIONS || 1198168404Spjd P2PHASE(drro->drr_blksz, SPA_MINBLOCKSIZE) || 1199168404Spjd drro->drr_blksz < SPA_MINBLOCKSIZE || 1200168404Spjd drro->drr_blksz > SPA_MAXBLOCKSIZE || 1201168404Spjd drro->drr_bonuslen > DN_MAX_BONUSLEN) { 1202249195Smm return (SET_ERROR(EINVAL)); 1203168404Spjd } 1204168404Spjd 1205200726Sdelphij err = dmu_object_info(os, drro->drr_object, NULL); 1206168404Spjd 1207200726Sdelphij if (err != 0 && err != ENOENT) 1208249195Smm return (SET_ERROR(EINVAL)); 1209200726Sdelphij 1210201756Sdelphij if (drro->drr_bonuslen) { 1211201756Sdelphij data = restore_read(ra, P2ROUNDUP(drro->drr_bonuslen, 8)); 1212248571Smm if (ra->err != 0) 1213201756Sdelphij return (ra->err); 1214201756Sdelphij } 1215201756Sdelphij 1216168404Spjd if (err == ENOENT) { 1217168404Spjd /* currently free, want to be allocated */ 1218200726Sdelphij tx = dmu_tx_create(os); 1219168404Spjd dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT); 1220168404Spjd err = dmu_tx_assign(tx, TXG_WAIT); 1221248571Smm if (err != 0) { 1222168404Spjd dmu_tx_abort(tx); 1223168404Spjd return (err); 1224168404Spjd } 1225168404Spjd err = dmu_object_claim(os, drro->drr_object, 1226168404Spjd drro->drr_type, drro->drr_blksz, 1227168404Spjd drro->drr_bonustype, drro->drr_bonuslen, tx); 1228200726Sdelphij dmu_tx_commit(tx); 1229168404Spjd } else { 1230168404Spjd /* currently allocated, want to be allocated */ 1231168404Spjd err = dmu_object_reclaim(os, drro->drr_object, 1232168404Spjd drro->drr_type, drro->drr_blksz, 1233200726Sdelphij drro->drr_bonustype, drro->drr_bonuslen); 1234168404Spjd } 1235248571Smm if (err != 0) { 1236249195Smm return (SET_ERROR(EINVAL)); 1237219089Spjd } 1238200726Sdelphij 1239200726Sdelphij tx = dmu_tx_create(os); 1240200726Sdelphij dmu_tx_hold_bonus(tx, drro->drr_object); 1241200726Sdelphij err = dmu_tx_assign(tx, TXG_WAIT); 1242248571Smm if (err != 0) { 1243200726Sdelphij dmu_tx_abort(tx); 1244200726Sdelphij return (err); 1245168404Spjd } 1246168404Spjd 1247219089Spjd dmu_object_set_checksum(os, drro->drr_object, drro->drr_checksumtype, 1248219089Spjd tx); 1249168404Spjd dmu_object_set_compress(os, drro->drr_object, drro->drr_compress, tx); 1250168404Spjd 1251200727Sdelphij if (data != NULL) { 1252168404Spjd dmu_buf_t *db; 1253200727Sdelphij 1254168404Spjd VERIFY(0 == dmu_bonus_hold(os, drro->drr_object, FTAG, &db)); 1255168404Spjd dmu_buf_will_dirty(db, tx); 1256168404Spjd 1257185029Spjd ASSERT3U(db->db_size, >=, drro->drr_bonuslen); 1258185029Spjd bcopy(data, db->db_data, drro->drr_bonuslen); 1259168404Spjd if (ra->byteswap) { 1260236884Smm dmu_object_byteswap_t byteswap = 1261236884Smm DMU_OT_BYTESWAP(drro->drr_bonustype); 1262236884Smm dmu_ot_byteswap[byteswap].ob_func(db->db_data, 1263168404Spjd drro->drr_bonuslen); 1264168404Spjd } 1265168404Spjd dmu_buf_rele(db, FTAG); 1266168404Spjd } 1267168404Spjd dmu_tx_commit(tx); 1268168404Spjd return (0); 1269168404Spjd} 1270168404Spjd 1271168404Spjd/* ARGSUSED */ 1272168404Spjdstatic int 1273168404Spjdrestore_freeobjects(struct restorearg *ra, objset_t *os, 1274168404Spjd struct drr_freeobjects *drrfo) 1275168404Spjd{ 1276168404Spjd uint64_t obj; 1277168404Spjd 1278168404Spjd if (drrfo->drr_firstobj + drrfo->drr_numobjs < drrfo->drr_firstobj) 1279249195Smm return (SET_ERROR(EINVAL)); 1280168404Spjd 1281168404Spjd for (obj = drrfo->drr_firstobj; 1282168404Spjd obj < drrfo->drr_firstobj + drrfo->drr_numobjs; 1283168404Spjd (void) dmu_object_next(os, &obj, FALSE, 0)) { 1284168404Spjd int err; 1285168404Spjd 1286168404Spjd if (dmu_object_info(os, obj, NULL) != 0) 1287168404Spjd continue; 1288168404Spjd 1289254753Sdelphij err = dmu_free_long_object(os, obj); 1290248571Smm if (err != 0) 1291168404Spjd return (err); 1292168404Spjd } 1293168404Spjd return (0); 1294168404Spjd} 1295168404Spjd 1296168404Spjdstatic int 1297168404Spjdrestore_write(struct restorearg *ra, objset_t *os, 1298168404Spjd struct drr_write *drrw) 1299168404Spjd{ 1300168404Spjd dmu_tx_t *tx; 1301168404Spjd void *data; 1302168404Spjd int err; 1303168404Spjd 1304168404Spjd if (drrw->drr_offset + drrw->drr_length < drrw->drr_offset || 1305236884Smm !DMU_OT_IS_VALID(drrw->drr_type)) 1306249195Smm return (SET_ERROR(EINVAL)); 1307168404Spjd 1308168404Spjd data = restore_read(ra, drrw->drr_length); 1309168404Spjd if (data == NULL) 1310168404Spjd return (ra->err); 1311168404Spjd 1312168404Spjd if (dmu_object_info(os, drrw->drr_object, NULL) != 0) 1313249195Smm return (SET_ERROR(EINVAL)); 1314168404Spjd 1315168404Spjd tx = dmu_tx_create(os); 1316168404Spjd 1317168404Spjd dmu_tx_hold_write(tx, drrw->drr_object, 1318168404Spjd drrw->drr_offset, drrw->drr_length); 1319168404Spjd err = dmu_tx_assign(tx, TXG_WAIT); 1320248571Smm if (err != 0) { 1321168404Spjd dmu_tx_abort(tx); 1322168404Spjd return (err); 1323168404Spjd } 1324236884Smm if (ra->byteswap) { 1325236884Smm dmu_object_byteswap_t byteswap = 1326236884Smm DMU_OT_BYTESWAP(drrw->drr_type); 1327236884Smm dmu_ot_byteswap[byteswap].ob_func(data, drrw->drr_length); 1328236884Smm } 1329168404Spjd dmu_write(os, drrw->drr_object, 1330168404Spjd drrw->drr_offset, drrw->drr_length, data, tx); 1331168404Spjd dmu_tx_commit(tx); 1332168404Spjd return (0); 1333168404Spjd} 1334168404Spjd 1335219089Spjd/* 1336219089Spjd * Handle a DRR_WRITE_BYREF record. This record is used in dedup'ed 1337219089Spjd * streams to refer to a copy of the data that is already on the 1338219089Spjd * system because it came in earlier in the stream. This function 1339219089Spjd * finds the earlier copy of the data, and uses that copy instead of 1340219089Spjd * data from the stream to fulfill this write. 1341219089Spjd */ 1342219089Spjdstatic int 1343219089Spjdrestore_write_byref(struct restorearg *ra, objset_t *os, 1344219089Spjd struct drr_write_byref *drrwbr) 1345219089Spjd{ 1346219089Spjd dmu_tx_t *tx; 1347219089Spjd int err; 1348219089Spjd guid_map_entry_t gmesrch; 1349219089Spjd guid_map_entry_t *gmep; 1350219089Spjd avl_index_t where; 1351219089Spjd objset_t *ref_os = NULL; 1352219089Spjd dmu_buf_t *dbp; 1353219089Spjd 1354219089Spjd if (drrwbr->drr_offset + drrwbr->drr_length < drrwbr->drr_offset) 1355249195Smm return (SET_ERROR(EINVAL)); 1356219089Spjd 1357219089Spjd /* 1358219089Spjd * If the GUID of the referenced dataset is different from the 1359219089Spjd * GUID of the target dataset, find the referenced dataset. 1360219089Spjd */ 1361219089Spjd if (drrwbr->drr_toguid != drrwbr->drr_refguid) { 1362219089Spjd gmesrch.guid = drrwbr->drr_refguid; 1363219089Spjd if ((gmep = avl_find(ra->guid_to_ds_map, &gmesrch, 1364219089Spjd &where)) == NULL) { 1365249195Smm return (SET_ERROR(EINVAL)); 1366219089Spjd } 1367219089Spjd if (dmu_objset_from_ds(gmep->gme_ds, &ref_os)) 1368249195Smm return (SET_ERROR(EINVAL)); 1369219089Spjd } else { 1370219089Spjd ref_os = os; 1371219089Spjd } 1372219089Spjd 1373219089Spjd if (err = dmu_buf_hold(ref_os, drrwbr->drr_refobject, 1374219089Spjd drrwbr->drr_refoffset, FTAG, &dbp, DMU_READ_PREFETCH)) 1375219089Spjd return (err); 1376219089Spjd 1377219089Spjd tx = dmu_tx_create(os); 1378219089Spjd 1379219089Spjd dmu_tx_hold_write(tx, drrwbr->drr_object, 1380219089Spjd drrwbr->drr_offset, drrwbr->drr_length); 1381219089Spjd err = dmu_tx_assign(tx, TXG_WAIT); 1382248571Smm if (err != 0) { 1383219089Spjd dmu_tx_abort(tx); 1384219089Spjd return (err); 1385219089Spjd } 1386219089Spjd dmu_write(os, drrwbr->drr_object, 1387219089Spjd drrwbr->drr_offset, drrwbr->drr_length, dbp->db_data, tx); 1388219089Spjd dmu_buf_rele(dbp, FTAG); 1389219089Spjd dmu_tx_commit(tx); 1390219089Spjd return (0); 1391219089Spjd} 1392219089Spjd 1393219089Spjdstatic int 1394219089Spjdrestore_spill(struct restorearg *ra, objset_t *os, struct drr_spill *drrs) 1395219089Spjd{ 1396219089Spjd dmu_tx_t *tx; 1397219089Spjd void *data; 1398219089Spjd dmu_buf_t *db, *db_spill; 1399219089Spjd int err; 1400219089Spjd 1401219089Spjd if (drrs->drr_length < SPA_MINBLOCKSIZE || 1402219089Spjd drrs->drr_length > SPA_MAXBLOCKSIZE) 1403249195Smm return (SET_ERROR(EINVAL)); 1404219089Spjd 1405219089Spjd data = restore_read(ra, drrs->drr_length); 1406219089Spjd if (data == NULL) 1407219089Spjd return (ra->err); 1408219089Spjd 1409219089Spjd if (dmu_object_info(os, drrs->drr_object, NULL) != 0) 1410249195Smm return (SET_ERROR(EINVAL)); 1411219089Spjd 1412219089Spjd VERIFY(0 == dmu_bonus_hold(os, drrs->drr_object, FTAG, &db)); 1413219089Spjd if ((err = dmu_spill_hold_by_bonus(db, FTAG, &db_spill)) != 0) { 1414219089Spjd dmu_buf_rele(db, FTAG); 1415219089Spjd return (err); 1416219089Spjd } 1417219089Spjd 1418219089Spjd tx = dmu_tx_create(os); 1419219089Spjd 1420219089Spjd dmu_tx_hold_spill(tx, db->db_object); 1421219089Spjd 1422219089Spjd err = dmu_tx_assign(tx, TXG_WAIT); 1423248571Smm if (err != 0) { 1424219089Spjd dmu_buf_rele(db, FTAG); 1425219089Spjd dmu_buf_rele(db_spill, FTAG); 1426219089Spjd dmu_tx_abort(tx); 1427219089Spjd return (err); 1428219089Spjd } 1429219089Spjd dmu_buf_will_dirty(db_spill, tx); 1430219089Spjd 1431219089Spjd if (db_spill->db_size < drrs->drr_length) 1432219089Spjd VERIFY(0 == dbuf_spill_set_blksz(db_spill, 1433219089Spjd drrs->drr_length, tx)); 1434219089Spjd bcopy(data, db_spill->db_data, drrs->drr_length); 1435219089Spjd 1436219089Spjd dmu_buf_rele(db, FTAG); 1437219089Spjd dmu_buf_rele(db_spill, FTAG); 1438219089Spjd 1439219089Spjd dmu_tx_commit(tx); 1440219089Spjd return (0); 1441219089Spjd} 1442219089Spjd 1443168404Spjd/* ARGSUSED */ 1444168404Spjdstatic int 1445168404Spjdrestore_free(struct restorearg *ra, objset_t *os, 1446168404Spjd struct drr_free *drrf) 1447168404Spjd{ 1448168404Spjd int err; 1449168404Spjd 1450168404Spjd if (drrf->drr_length != -1ULL && 1451168404Spjd drrf->drr_offset + drrf->drr_length < drrf->drr_offset) 1452249195Smm return (SET_ERROR(EINVAL)); 1453168404Spjd 1454168404Spjd if (dmu_object_info(os, drrf->drr_object, NULL) != 0) 1455249195Smm return (SET_ERROR(EINVAL)); 1456168404Spjd 1457185029Spjd err = dmu_free_long_range(os, drrf->drr_object, 1458168404Spjd drrf->drr_offset, drrf->drr_length); 1459168404Spjd return (err); 1460168404Spjd} 1461168404Spjd 1462248571Smm/* used to destroy the drc_ds on error */ 1463248571Smmstatic void 1464248571Smmdmu_recv_cleanup_ds(dmu_recv_cookie_t *drc) 1465248571Smm{ 1466248571Smm char name[MAXNAMELEN]; 1467248571Smm dsl_dataset_name(drc->drc_ds, name); 1468248571Smm dsl_dataset_disown(drc->drc_ds, dmu_recv_tag); 1469248571Smm (void) dsl_destroy_head(name); 1470248571Smm} 1471248571Smm 1472185029Spjd/* 1473185029Spjd * NB: callers *must* call dmu_recv_end() if this succeeds. 1474185029Spjd */ 1475168404Spjdint 1476219089Spjddmu_recv_stream(dmu_recv_cookie_t *drc, struct file *fp, offset_t *voffp, 1477219089Spjd int cleanup_fd, uint64_t *action_handlep) 1478168404Spjd{ 1479185029Spjd struct restorearg ra = { 0 }; 1480168404Spjd dmu_replay_record_t *drr; 1481185029Spjd objset_t *os; 1482185029Spjd zio_cksum_t pcksum; 1483219089Spjd int featureflags; 1484168404Spjd 1485248571Smm ra.byteswap = drc->drc_byteswap; 1486248571Smm ra.cksum = drc->drc_cksum; 1487219089Spjd ra.td = curthread; 1488185029Spjd ra.fp = fp; 1489185029Spjd ra.voff = *voffp; 1490185029Spjd ra.bufsize = 1<<20; 1491185029Spjd ra.buf = kmem_alloc(ra.bufsize, KM_SLEEP); 1492168404Spjd 1493185029Spjd /* these were verified in dmu_recv_begin */ 1494248571Smm ASSERT3U(DMU_GET_STREAM_HDRTYPE(drc->drc_drrb->drr_versioninfo), ==, 1495219089Spjd DMU_SUBSTREAM); 1496248571Smm ASSERT3U(drc->drc_drrb->drr_type, <, DMU_OST_NUMTYPES); 1497168404Spjd 1498168404Spjd /* 1499168404Spjd * Open the objset we are modifying. 1500168404Spjd */ 1501248571Smm VERIFY0(dmu_objset_from_ds(drc->drc_ds, &os)); 1502168404Spjd 1503248571Smm ASSERT(drc->drc_ds->ds_phys->ds_flags & DS_FLAG_INCONSISTENT); 1504168404Spjd 1505219089Spjd featureflags = DMU_GET_FEATUREFLAGS(drc->drc_drrb->drr_versioninfo); 1506219089Spjd 1507219089Spjd /* if this stream is dedup'ed, set up the avl tree for guid mapping */ 1508219089Spjd if (featureflags & DMU_BACKUP_FEATURE_DEDUP) { 1509219089Spjd minor_t minor; 1510219089Spjd 1511219089Spjd if (cleanup_fd == -1) { 1512249195Smm ra.err = SET_ERROR(EBADF); 1513219089Spjd goto out; 1514219089Spjd } 1515219089Spjd ra.err = zfs_onexit_fd_hold(cleanup_fd, &minor); 1516248571Smm if (ra.err != 0) { 1517219089Spjd cleanup_fd = -1; 1518219089Spjd goto out; 1519219089Spjd } 1520219089Spjd 1521219089Spjd if (*action_handlep == 0) { 1522219089Spjd ra.guid_to_ds_map = 1523219089Spjd kmem_alloc(sizeof (avl_tree_t), KM_SLEEP); 1524219089Spjd avl_create(ra.guid_to_ds_map, guid_compare, 1525219089Spjd sizeof (guid_map_entry_t), 1526219089Spjd offsetof(guid_map_entry_t, avlnode)); 1527219089Spjd ra.err = zfs_onexit_add_cb(minor, 1528219089Spjd free_guid_map_onexit, ra.guid_to_ds_map, 1529219089Spjd action_handlep); 1530248571Smm if (ra.err != 0) 1531219089Spjd goto out; 1532219089Spjd } else { 1533219089Spjd ra.err = zfs_onexit_cb_data(minor, *action_handlep, 1534219089Spjd (void **)&ra.guid_to_ds_map); 1535248571Smm if (ra.err != 0) 1536219089Spjd goto out; 1537219089Spjd } 1538221263Smm 1539221263Smm drc->drc_guid_to_ds_map = ra.guid_to_ds_map; 1540219089Spjd } 1541219089Spjd 1542168404Spjd /* 1543168404Spjd * Read records and process them. 1544168404Spjd */ 1545185029Spjd pcksum = ra.cksum; 1546168404Spjd while (ra.err == 0 && 1547168404Spjd NULL != (drr = restore_read(&ra, sizeof (*drr)))) { 1548185029Spjd if (issig(JUSTLOOKING) && issig(FORREAL)) { 1549249195Smm ra.err = SET_ERROR(EINTR); 1550168404Spjd goto out; 1551168404Spjd } 1552168404Spjd 1553168404Spjd if (ra.byteswap) 1554168404Spjd backup_byteswap(drr); 1555168404Spjd 1556168404Spjd switch (drr->drr_type) { 1557168404Spjd case DRR_OBJECT: 1558168404Spjd { 1559168404Spjd /* 1560168404Spjd * We need to make a copy of the record header, 1561168404Spjd * because restore_{object,write} may need to 1562168404Spjd * restore_read(), which will invalidate drr. 1563168404Spjd */ 1564168404Spjd struct drr_object drro = drr->drr_u.drr_object; 1565168404Spjd ra.err = restore_object(&ra, os, &drro); 1566168404Spjd break; 1567168404Spjd } 1568168404Spjd case DRR_FREEOBJECTS: 1569168404Spjd { 1570168404Spjd struct drr_freeobjects drrfo = 1571168404Spjd drr->drr_u.drr_freeobjects; 1572168404Spjd ra.err = restore_freeobjects(&ra, os, &drrfo); 1573168404Spjd break; 1574168404Spjd } 1575168404Spjd case DRR_WRITE: 1576168404Spjd { 1577168404Spjd struct drr_write drrw = drr->drr_u.drr_write; 1578168404Spjd ra.err = restore_write(&ra, os, &drrw); 1579168404Spjd break; 1580168404Spjd } 1581219089Spjd case DRR_WRITE_BYREF: 1582219089Spjd { 1583219089Spjd struct drr_write_byref drrwbr = 1584219089Spjd drr->drr_u.drr_write_byref; 1585219089Spjd ra.err = restore_write_byref(&ra, os, &drrwbr); 1586219089Spjd break; 1587219089Spjd } 1588168404Spjd case DRR_FREE: 1589168404Spjd { 1590168404Spjd struct drr_free drrf = drr->drr_u.drr_free; 1591168404Spjd ra.err = restore_free(&ra, os, &drrf); 1592168404Spjd break; 1593168404Spjd } 1594168404Spjd case DRR_END: 1595168404Spjd { 1596168404Spjd struct drr_end drre = drr->drr_u.drr_end; 1597168404Spjd /* 1598168404Spjd * We compare against the *previous* checksum 1599168404Spjd * value, because the stored checksum is of 1600168404Spjd * everything before the DRR_END record. 1601168404Spjd */ 1602185029Spjd if (!ZIO_CHECKSUM_EQUAL(drre.drr_checksum, pcksum)) 1603249195Smm ra.err = SET_ERROR(ECKSUM); 1604168404Spjd goto out; 1605168404Spjd } 1606219089Spjd case DRR_SPILL: 1607219089Spjd { 1608219089Spjd struct drr_spill drrs = drr->drr_u.drr_spill; 1609219089Spjd ra.err = restore_spill(&ra, os, &drrs); 1610219089Spjd break; 1611219089Spjd } 1612168404Spjd default: 1613249195Smm ra.err = SET_ERROR(EINVAL); 1614168404Spjd goto out; 1615168404Spjd } 1616185029Spjd pcksum = ra.cksum; 1617168404Spjd } 1618185029Spjd ASSERT(ra.err != 0); 1619168404Spjd 1620168404Spjdout: 1621219089Spjd if ((featureflags & DMU_BACKUP_FEATURE_DEDUP) && (cleanup_fd != -1)) 1622219089Spjd zfs_onexit_fd_rele(cleanup_fd); 1623168404Spjd 1624185029Spjd if (ra.err != 0) { 1625168404Spjd /* 1626219089Spjd * destroy what we created, so we don't leave it in the 1627219089Spjd * inconsistent restoring state. 1628168404Spjd */ 1629248571Smm dmu_recv_cleanup_ds(drc); 1630168404Spjd } 1631168404Spjd 1632168404Spjd kmem_free(ra.buf, ra.bufsize); 1633185029Spjd *voffp = ra.voff; 1634168404Spjd return (ra.err); 1635168404Spjd} 1636185029Spjd 1637185029Spjdstatic int 1638248571Smmdmu_recv_end_check(void *arg, dmu_tx_t *tx) 1639185029Spjd{ 1640248571Smm dmu_recv_cookie_t *drc = arg; 1641248571Smm dsl_pool_t *dp = dmu_tx_pool(tx); 1642248571Smm int error; 1643185029Spjd 1644248571Smm ASSERT3P(drc->drc_ds->ds_owner, ==, dmu_recv_tag); 1645248571Smm 1646248571Smm if (!drc->drc_newfs) { 1647248571Smm dsl_dataset_t *origin_head; 1648248571Smm 1649248571Smm error = dsl_dataset_hold(dp, drc->drc_tofs, FTAG, &origin_head); 1650248571Smm if (error != 0) 1651248571Smm return (error); 1652253820Sdelphij if (drc->drc_force) { 1653253820Sdelphij /* 1654253820Sdelphij * We will destroy any snapshots in tofs (i.e. before 1655253820Sdelphij * origin_head) that are after the origin (which is 1656253820Sdelphij * the snap before drc_ds, because drc_ds can not 1657253820Sdelphij * have any snaps of its own). 1658253820Sdelphij */ 1659253820Sdelphij uint64_t obj = origin_head->ds_phys->ds_prev_snap_obj; 1660253820Sdelphij while (obj != drc->drc_ds->ds_phys->ds_prev_snap_obj) { 1661253820Sdelphij dsl_dataset_t *snap; 1662253820Sdelphij error = dsl_dataset_hold_obj(dp, obj, FTAG, 1663253820Sdelphij &snap); 1664253820Sdelphij if (error != 0) 1665253820Sdelphij return (error); 1666253820Sdelphij if (snap->ds_dir != origin_head->ds_dir) 1667253820Sdelphij error = SET_ERROR(EINVAL); 1668253820Sdelphij if (error == 0) { 1669253820Sdelphij error = dsl_destroy_snapshot_check_impl( 1670253820Sdelphij snap, B_FALSE); 1671253820Sdelphij } 1672253820Sdelphij obj = snap->ds_phys->ds_prev_snap_obj; 1673253820Sdelphij dsl_dataset_rele(snap, FTAG); 1674253820Sdelphij if (error != 0) 1675253820Sdelphij return (error); 1676253820Sdelphij } 1677253820Sdelphij } 1678248571Smm error = dsl_dataset_clone_swap_check_impl(drc->drc_ds, 1679253816Sdelphij origin_head, drc->drc_force, drc->drc_owner, tx); 1680248571Smm if (error != 0) { 1681248571Smm dsl_dataset_rele(origin_head, FTAG); 1682248571Smm return (error); 1683248571Smm } 1684248571Smm error = dsl_dataset_snapshot_check_impl(origin_head, 1685253819Sdelphij drc->drc_tosnap, tx, B_TRUE); 1686248571Smm dsl_dataset_rele(origin_head, FTAG); 1687248571Smm if (error != 0) 1688248571Smm return (error); 1689248571Smm 1690248571Smm error = dsl_destroy_head_check_impl(drc->drc_ds, 1); 1691248571Smm } else { 1692248571Smm error = dsl_dataset_snapshot_check_impl(drc->drc_ds, 1693253819Sdelphij drc->drc_tosnap, tx, B_TRUE); 1694248571Smm } 1695248571Smm return (error); 1696185029Spjd} 1697185029Spjd 1698185029Spjdstatic void 1699248571Smmdmu_recv_end_sync(void *arg, dmu_tx_t *tx) 1700185029Spjd{ 1701248571Smm dmu_recv_cookie_t *drc = arg; 1702248571Smm dsl_pool_t *dp = dmu_tx_pool(tx); 1703185029Spjd 1704248571Smm spa_history_log_internal_ds(drc->drc_ds, "finish receiving", 1705248571Smm tx, "snap=%s", drc->drc_tosnap); 1706185029Spjd 1707248571Smm if (!drc->drc_newfs) { 1708248571Smm dsl_dataset_t *origin_head; 1709185029Spjd 1710248571Smm VERIFY0(dsl_dataset_hold(dp, drc->drc_tofs, FTAG, 1711248571Smm &origin_head)); 1712253820Sdelphij 1713253820Sdelphij if (drc->drc_force) { 1714253820Sdelphij /* 1715253820Sdelphij * Destroy any snapshots of drc_tofs (origin_head) 1716253820Sdelphij * after the origin (the snap before drc_ds). 1717253820Sdelphij */ 1718253820Sdelphij uint64_t obj = origin_head->ds_phys->ds_prev_snap_obj; 1719253820Sdelphij while (obj != drc->drc_ds->ds_phys->ds_prev_snap_obj) { 1720253820Sdelphij dsl_dataset_t *snap; 1721253820Sdelphij VERIFY0(dsl_dataset_hold_obj(dp, obj, FTAG, 1722253820Sdelphij &snap)); 1723253820Sdelphij ASSERT3P(snap->ds_dir, ==, origin_head->ds_dir); 1724253820Sdelphij obj = snap->ds_phys->ds_prev_snap_obj; 1725253820Sdelphij dsl_destroy_snapshot_sync_impl(snap, 1726253820Sdelphij B_FALSE, tx); 1727253820Sdelphij dsl_dataset_rele(snap, FTAG); 1728253820Sdelphij } 1729253820Sdelphij } 1730253820Sdelphij VERIFY3P(drc->drc_ds->ds_prev, ==, 1731253820Sdelphij origin_head->ds_prev); 1732253820Sdelphij 1733248571Smm dsl_dataset_clone_swap_sync_impl(drc->drc_ds, 1734248571Smm origin_head, tx); 1735248571Smm dsl_dataset_snapshot_sync_impl(origin_head, 1736248571Smm drc->drc_tosnap, tx); 1737248571Smm 1738248571Smm /* set snapshot's creation time and guid */ 1739248571Smm dmu_buf_will_dirty(origin_head->ds_prev->ds_dbuf, tx); 1740248571Smm origin_head->ds_prev->ds_phys->ds_creation_time = 1741248571Smm drc->drc_drrb->drr_creation_time; 1742248571Smm origin_head->ds_prev->ds_phys->ds_guid = 1743248571Smm drc->drc_drrb->drr_toguid; 1744248571Smm origin_head->ds_prev->ds_phys->ds_flags &= 1745248571Smm ~DS_FLAG_INCONSISTENT; 1746248571Smm 1747248571Smm dmu_buf_will_dirty(origin_head->ds_dbuf, tx); 1748248571Smm origin_head->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT; 1749248571Smm 1750248571Smm dsl_dataset_rele(origin_head, FTAG); 1751248571Smm dsl_destroy_head_sync_impl(drc->drc_ds, tx); 1752253816Sdelphij 1753253816Sdelphij if (drc->drc_owner != NULL) 1754253816Sdelphij VERIFY3P(origin_head->ds_owner, ==, drc->drc_owner); 1755248571Smm } else { 1756248571Smm dsl_dataset_t *ds = drc->drc_ds; 1757248571Smm 1758248571Smm dsl_dataset_snapshot_sync_impl(ds, drc->drc_tosnap, tx); 1759248571Smm 1760248571Smm /* set snapshot's creation time and guid */ 1761248571Smm dmu_buf_will_dirty(ds->ds_prev->ds_dbuf, tx); 1762248571Smm ds->ds_prev->ds_phys->ds_creation_time = 1763248571Smm drc->drc_drrb->drr_creation_time; 1764248571Smm ds->ds_prev->ds_phys->ds_guid = drc->drc_drrb->drr_toguid; 1765248571Smm ds->ds_prev->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT; 1766248571Smm 1767248571Smm dmu_buf_will_dirty(ds->ds_dbuf, tx); 1768248571Smm ds->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT; 1769248571Smm } 1770248571Smm drc->drc_newsnapobj = drc->drc_ds->ds_phys->ds_prev_snap_obj; 1771248571Smm /* 1772248571Smm * Release the hold from dmu_recv_begin. This must be done before 1773248571Smm * we return to open context, so that when we free the dataset's dnode, 1774248571Smm * we can evict its bonus buffer. 1775248571Smm */ 1776248571Smm dsl_dataset_disown(drc->drc_ds, dmu_recv_tag); 1777248571Smm drc->drc_ds = NULL; 1778185029Spjd} 1779185029Spjd 1780219089Spjdstatic int 1781248571Smmadd_ds_to_guidmap(const char *name, avl_tree_t *guid_map, uint64_t snapobj) 1782221263Smm{ 1783248571Smm dsl_pool_t *dp; 1784221263Smm dsl_dataset_t *snapds; 1785221263Smm guid_map_entry_t *gmep; 1786221263Smm int err; 1787221263Smm 1788221263Smm ASSERT(guid_map != NULL); 1789221263Smm 1790248571Smm err = dsl_pool_hold(name, FTAG, &dp); 1791248571Smm if (err != 0) 1792248571Smm return (err); 1793249356Smm gmep = kmem_alloc(sizeof (*gmep), KM_SLEEP); 1794249196Smm err = dsl_dataset_hold_obj(dp, snapobj, gmep, &snapds); 1795221263Smm if (err == 0) { 1796221263Smm gmep->guid = snapds->ds_phys->ds_guid; 1797221263Smm gmep->gme_ds = snapds; 1798221263Smm avl_add(guid_map, gmep); 1799248571Smm dsl_dataset_long_hold(snapds, gmep); 1800249196Smm } else 1801249356Smm kmem_free(gmep, sizeof (*gmep)); 1802221263Smm 1803248571Smm dsl_pool_rele(dp, FTAG); 1804221263Smm return (err); 1805221263Smm} 1806221263Smm 1807248571Smmstatic int dmu_recv_end_modified_blocks = 3; 1808248571Smm 1809221263Smmstatic int 1810219089Spjddmu_recv_existing_end(dmu_recv_cookie_t *drc) 1811185029Spjd{ 1812248571Smm int error; 1813248571Smm char name[MAXNAMELEN]; 1814185029Spjd 1815248571Smm#ifdef _KERNEL 1816248571Smm /* 1817248571Smm * We will be destroying the ds; make sure its origin is unmounted if 1818248571Smm * necessary. 1819248571Smm */ 1820248571Smm dsl_dataset_name(drc->drc_ds, name); 1821248571Smm zfs_destroy_unmount_origin(name); 1822248571Smm#endif 1823185029Spjd 1824248571Smm error = dsl_sync_task(drc->drc_tofs, 1825248571Smm dmu_recv_end_check, dmu_recv_end_sync, drc, 1826248571Smm dmu_recv_end_modified_blocks); 1827185029Spjd 1828248571Smm if (error != 0) 1829248571Smm dmu_recv_cleanup_ds(drc); 1830248571Smm return (error); 1831185029Spjd} 1832219089Spjd 1833219089Spjdstatic int 1834219089Spjddmu_recv_new_end(dmu_recv_cookie_t *drc) 1835219089Spjd{ 1836248571Smm int error; 1837219089Spjd 1838248571Smm error = dsl_sync_task(drc->drc_tofs, 1839248571Smm dmu_recv_end_check, dmu_recv_end_sync, drc, 1840248571Smm dmu_recv_end_modified_blocks); 1841219089Spjd 1842248571Smm if (error != 0) { 1843248571Smm dmu_recv_cleanup_ds(drc); 1844248571Smm } else if (drc->drc_guid_to_ds_map != NULL) { 1845248571Smm (void) add_ds_to_guidmap(drc->drc_tofs, 1846248571Smm drc->drc_guid_to_ds_map, 1847248571Smm drc->drc_newsnapobj); 1848219089Spjd } 1849248571Smm return (error); 1850219089Spjd} 1851219089Spjd 1852219089Spjdint 1853253816Sdelphijdmu_recv_end(dmu_recv_cookie_t *drc, void *owner) 1854219089Spjd{ 1855253816Sdelphij drc->drc_owner = owner; 1856253816Sdelphij 1857248571Smm if (drc->drc_newfs) 1858248571Smm return (dmu_recv_new_end(drc)); 1859248571Smm else 1860219089Spjd return (dmu_recv_existing_end(drc)); 1861219089Spjd} 1862253821Sdelphij 1863253821Sdelphij/* 1864253821Sdelphij * Return TRUE if this objset is currently being received into. 1865253821Sdelphij */ 1866253821Sdelphijboolean_t 1867253821Sdelphijdmu_objset_is_receiving(objset_t *os) 1868253821Sdelphij{ 1869253821Sdelphij return (os->os_dsl_dataset != NULL && 1870253821Sdelphij os->os_dsl_dataset->ds_owner == dmu_recv_tag); 1871253821Sdelphij} 1872