1 2743 ahrens /* 2 2743 ahrens * CDDL HEADER START 3 2743 ahrens * 4 2743 ahrens * The contents of this file are subject to the terms of the 5 2743 ahrens * Common Development and Distribution License (the "License"). 6 2743 ahrens * You may not use this file except in compliance with the License. 7 2743 ahrens * 8 2743 ahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 2743 ahrens * or http://www.opensolaris.org/os/licensing. 10 2743 ahrens * See the License for the specific language governing permissions 11 2743 ahrens * and limitations under the License. 12 2743 ahrens * 13 2743 ahrens * When distributing Covered Code, include this CDDL HEADER in each 14 2743 ahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 2743 ahrens * If applicable, add the following below this CDDL HEADER, with the 16 2743 ahrens * fields enclosed by brackets "[]" replaced with your own identifying 17 2743 ahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18 2743 ahrens * 19 2743 ahrens * CDDL HEADER END 20 2743 ahrens */ 21 2743 ahrens /* 22 8644 Mark * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 2743 ahrens * Use is subject to license terms. 24 2743 ahrens */ 25 2743 ahrens 26 2743 ahrens #include <sys/dmu.h> 27 2743 ahrens #include <sys/dmu_impl.h> 28 2743 ahrens #include <sys/dmu_tx.h> 29 2743 ahrens #include <sys/dbuf.h> 30 2743 ahrens #include <sys/dnode.h> 31 2743 ahrens #include <sys/zfs_context.h> 32 2743 ahrens #include <sys/dmu_objset.h> 33 2743 ahrens #include <sys/dmu_traverse.h> 34 2743 ahrens #include <sys/dsl_dataset.h> 35 2743 ahrens #include <sys/dsl_dir.h> 36 11022 Tom #include <sys/dsl_prop.h> 37 2743 ahrens #include <sys/dsl_pool.h> 38 2743 ahrens #include <sys/dsl_synctask.h> 39 2743 ahrens #include <sys/zfs_ioctl.h> 40 2743 ahrens #include <sys/zap.h> 41 2743 ahrens #include <sys/zio_checksum.h> 42 11007 Lori #include <sys/avl.h> 43 2743 ahrens 44 5367 ahrens static char *dmu_recv_tag = "dmu_recv_tag"; 45 11007 Lori 46 11007 Lori /* 47 11007 Lori * The list of data whose inclusion in a send stream can be pending from 48 11007 Lori * one call to backup_cb to another. Multiple calls to dump_free() and 49 11007 Lori * dump_freeobjects() can be aggregated into a single DRR_FREE or 50 11007 Lori * DRR_FREEOBJECTS replay record. 51 11007 Lori */ 52 11007 Lori typedef enum { 53 11007 Lori PENDING_NONE, 54 11007 Lori PENDING_FREE, 55 11007 Lori PENDING_FREEOBJECTS 56 11007 Lori } pendop_t; 57 5367 ahrens 58 2743 ahrens struct backuparg { 59 2743 ahrens dmu_replay_record_t *drr; 60 2743 ahrens vnode_t *vp; 61 5367 ahrens offset_t *off; 62 2743 ahrens objset_t *os; 63 2743 ahrens zio_cksum_t zc; 64 11007 Lori uint64_t toguid; 65 2743 ahrens int err; 66 11007 Lori pendop_t pending_op; 67 2743 ahrens }; 68 2743 ahrens 69 2743 ahrens static int 70 2743 ahrens dump_bytes(struct backuparg *ba, void *buf, int len) 71 2743 ahrens { 72 2743 ahrens ssize_t resid; /* have to get resid to get detailed errno */ 73 2743 ahrens ASSERT3U(len % 8, ==, 0); 74 2743 ahrens 75 2743 ahrens fletcher_4_incremental_native(buf, len, &ba->zc); 76 2743 ahrens ba->err = vn_rdwr(UIO_WRITE, ba->vp, 77 2743 ahrens (caddr_t)buf, len, 78 2743 ahrens 0, UIO_SYSSPACE, FAPPEND, RLIM64_INFINITY, CRED(), &resid); 79 5367 ahrens *ba->off += len; 80 2743 ahrens return (ba->err); 81 2743 ahrens } 82 2743 ahrens 83 2743 ahrens static int 84 2743 ahrens dump_free(struct backuparg *ba, uint64_t object, uint64_t offset, 85 2743 ahrens uint64_t length) 86 2743 ahrens { 87 11007 Lori struct drr_free *drrf = &(ba->drr->drr_u.drr_free); 88 11007 Lori 89 11007 Lori /* 90 11007 Lori * If there is a pending op, but it's not PENDING_FREE, push it out, 91 11007 Lori * since free block aggregation can only be done for blocks of the 92 11007 Lori * same type (i.e., DRR_FREE records can only be aggregated with 93 11007 Lori * other DRR_FREE records. DRR_FREEOBJECTS records can only be 94 11007 Lori * aggregated with other DRR_FREEOBJECTS records. 95 11007 Lori */ 96 11007 Lori if (ba->pending_op != PENDING_NONE && ba->pending_op != PENDING_FREE) { 97 11007 Lori if (dump_bytes(ba, ba->drr, sizeof (dmu_replay_record_t)) != 0) 98 11007 Lori return (EINTR); 99 11007 Lori ba->pending_op = PENDING_NONE; 100 11007 Lori } 101 11007 Lori 102 11007 Lori if (ba->pending_op == PENDING_FREE) { 103 11007 Lori /* 104 11007 Lori * There should never be a PENDING_FREE if length is -1 105 11007 Lori * (because dump_dnode is the only place where this 106 11007 Lori * function is called with a -1, and only after flushing 107 11007 Lori * any pending record). 108 11007 Lori */ 109 11007 Lori ASSERT(length != -1ULL); 110 11007 Lori /* 111 11007 Lori * Check to see whether this free block can be aggregated 112 11007 Lori * with pending one. 113 11007 Lori */ 114 11007 Lori if (drrf->drr_object == object && drrf->drr_offset + 115 11007 Lori drrf->drr_length == offset) { 116 11007 Lori drrf->drr_length += length; 117 11007 Lori return (0); 118 11007 Lori } else { 119 11007 Lori /* not a continuation. Push out pending record */ 120 11007 Lori if (dump_bytes(ba, ba->drr, 121 11007 Lori sizeof (dmu_replay_record_t)) != 0) 122 11007 Lori return (EINTR); 123 11007 Lori ba->pending_op = PENDING_NONE; 124 11007 Lori } 125 11007 Lori } 126 11007 Lori /* create a FREE record and make it pending */ 127 2743 ahrens bzero(ba->drr, sizeof (dmu_replay_record_t)); 128 2743 ahrens ba->drr->drr_type = DRR_FREE; 129 11007 Lori drrf->drr_object = object; 130 11007 Lori drrf->drr_offset = offset; 131 11007 Lori drrf->drr_length = length; 132 11007 Lori drrf->drr_toguid = ba->toguid; 133 11007 Lori if (length == -1ULL) { 134 11007 Lori if (dump_bytes(ba, ba->drr, sizeof (dmu_replay_record_t)) != 0) 135 11007 Lori return (EINTR); 136 11007 Lori } else { 137 11007 Lori ba->pending_op = PENDING_FREE; 138 11007 Lori } 139 2743 ahrens 140 2743 ahrens return (0); 141 2743 ahrens } 142 2743 ahrens 143 2743 ahrens static int 144 2743 ahrens dump_data(struct backuparg *ba, dmu_object_type_t type, 145 2743 ahrens uint64_t object, uint64_t offset, int blksz, void *data) 146 2743 ahrens { 147 11007 Lori struct drr_write *drrw = &(ba->drr->drr_u.drr_write); 148 11007 Lori 149 11007 Lori /* 150 11007 Lori * If there is any kind of pending aggregation (currently either 151 11007 Lori * a grouping of free objects or free blocks), push it out to 152 11007 Lori * the stream, since aggregation can't be done across operations 153 11007 Lori * of different types. 154 11007 Lori */ 155 11007 Lori if (ba->pending_op != PENDING_NONE) { 156 11007 Lori if (dump_bytes(ba, ba->drr, sizeof (dmu_replay_record_t)) != 0) 157 11007 Lori return (EINTR); 158 11007 Lori ba->pending_op = PENDING_NONE; 159 11007 Lori } 160 2743 ahrens /* write a DATA record */ 161 2743 ahrens bzero(ba->drr, sizeof (dmu_replay_record_t)); 162 2743 ahrens ba->drr->drr_type = DRR_WRITE; 163 11007 Lori drrw->drr_object = object; 164 11007 Lori drrw->drr_type = type; 165 11007 Lori drrw->drr_offset = offset; 166 11007 Lori drrw->drr_length = blksz; 167 11007 Lori drrw->drr_toguid = ba->toguid; 168 2743 ahrens 169 11007 Lori if (dump_bytes(ba, ba->drr, sizeof (dmu_replay_record_t)) != 0) 170 2743 ahrens return (EINTR); 171 11007 Lori if (dump_bytes(ba, data, blksz) != 0) 172 2743 ahrens return (EINTR); 173 2743 ahrens return (0); 174 2743 ahrens } 175 2743 ahrens 176 2743 ahrens static int 177 2743 ahrens dump_freeobjects(struct backuparg *ba, uint64_t firstobj, uint64_t numobjs) 178 2743 ahrens { 179 11007 Lori struct drr_freeobjects *drrfo = &(ba->drr->drr_u.drr_freeobjects); 180 11007 Lori 181 11007 Lori /* 182 11007 Lori * If there is a pending op, but it's not PENDING_FREEOBJECTS, 183 11007 Lori * push it out, since free block aggregation can only be done for 184 11007 Lori * blocks of the same type (i.e., DRR_FREE records can only be 185 11007 Lori * aggregated with other DRR_FREE records. DRR_FREEOBJECTS records 186 11007 Lori * can only be aggregated with other DRR_FREEOBJECTS records. 187 11007 Lori */ 188 11007 Lori if (ba->pending_op != PENDING_NONE && 189 11007 Lori ba->pending_op != PENDING_FREEOBJECTS) { 190 11007 Lori if (dump_bytes(ba, ba->drr, sizeof (dmu_replay_record_t)) != 0) 191 11007 Lori return (EINTR); 192 11007 Lori ba->pending_op = PENDING_NONE; 193 11007 Lori } 194 11007 Lori if (ba->pending_op == PENDING_FREEOBJECTS) { 195 11007 Lori /* 196 11007 Lori * See whether this free object array can be aggregated 197 11007 Lori * with pending one 198 11007 Lori */ 199 11007 Lori if (drrfo->drr_firstobj + drrfo->drr_numobjs == firstobj) { 200 11007 Lori drrfo->drr_numobjs += numobjs; 201 11007 Lori return (0); 202 11007 Lori } else { 203 11007 Lori /* can't be aggregated. Push out pending record */ 204 11007 Lori if (dump_bytes(ba, ba->drr, 205 11007 Lori sizeof (dmu_replay_record_t)) != 0) 206 11007 Lori return (EINTR); 207 11007 Lori ba->pending_op = PENDING_NONE; 208 11007 Lori } 209 11007 Lori } 210 11007 Lori 211 2743 ahrens /* write a FREEOBJECTS record */ 212 2743 ahrens bzero(ba->drr, sizeof (dmu_replay_record_t)); 213 2743 ahrens ba->drr->drr_type = DRR_FREEOBJECTS; 214 11007 Lori drrfo->drr_firstobj = firstobj; 215 11007 Lori drrfo->drr_numobjs = numobjs; 216 11007 Lori drrfo->drr_toguid = ba->toguid; 217 2743 ahrens 218 11007 Lori ba->pending_op = PENDING_FREEOBJECTS; 219 11007 Lori 220 2743 ahrens return (0); 221 2743 ahrens } 222 2743 ahrens 223 2743 ahrens static int 224 2743 ahrens dump_dnode(struct backuparg *ba, uint64_t object, dnode_phys_t *dnp) 225 2743 ahrens { 226 11007 Lori struct drr_object *drro = &(ba->drr->drr_u.drr_object); 227 11007 Lori 228 2743 ahrens if (dnp == NULL || dnp->dn_type == DMU_OT_NONE) 229 2743 ahrens return (dump_freeobjects(ba, object, 1)); 230 11007 Lori 231 11007 Lori if (ba->pending_op != PENDING_NONE) { 232 11007 Lori if (dump_bytes(ba, ba->drr, sizeof (dmu_replay_record_t)) != 0) 233 11007 Lori return (EINTR); 234 11007 Lori ba->pending_op = PENDING_NONE; 235 11007 Lori } 236 2743 ahrens 237 2743 ahrens /* write an OBJECT record */ 238 2743 ahrens bzero(ba->drr, sizeof (dmu_replay_record_t)); 239 2743 ahrens ba->drr->drr_type = DRR_OBJECT; 240 11007 Lori drro->drr_object = object; 241 11007 Lori drro->drr_type = dnp->dn_type; 242 11007 Lori drro->drr_bonustype = dnp->dn_bonustype; 243 11007 Lori drro->drr_blksz = dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT; 244 11007 Lori drro->drr_bonuslen = dnp->dn_bonuslen; 245 11007 Lori drro->drr_checksumtype = dnp->dn_checksum; 246 11007 Lori drro->drr_compress = dnp->dn_compress; 247 11007 Lori drro->drr_toguid = ba->toguid; 248 2743 ahrens 249 11007 Lori if (dump_bytes(ba, ba->drr, sizeof (dmu_replay_record_t)) != 0) 250 2743 ahrens return (EINTR); 251 2743 ahrens 252 11007 Lori if (dump_bytes(ba, DN_BONUS(dnp), P2ROUNDUP(dnp->dn_bonuslen, 8)) != 0) 253 2743 ahrens return (EINTR); 254 2743 ahrens 255 2743 ahrens /* free anything past the end of the file */ 256 2743 ahrens if (dump_free(ba, object, (dnp->dn_maxblkid + 1) * 257 2743 ahrens (dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT), -1ULL)) 258 2743 ahrens return (EINTR); 259 2743 ahrens if (ba->err) 260 2743 ahrens return (EINTR); 261 2743 ahrens return (0); 262 2743 ahrens } 263 2743 ahrens 264 2743 ahrens #define BP_SPAN(dnp, level) \ 265 2743 ahrens (((uint64_t)dnp->dn_datablkszsec) << (SPA_MINBLOCKSHIFT + \ 266 2743 ahrens (level) * (dnp->dn_indblkshift - SPA_BLKPTRSHIFT))) 267 2743 ahrens 268 10922 Jeff /* ARGSUSED */ 269 2743 ahrens static int 270 10922 Jeff backup_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, 271 10922 Jeff const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg) 272 2743 ahrens { 273 2743 ahrens struct backuparg *ba = arg; 274 2743 ahrens dmu_object_type_t type = bp ? BP_GET_TYPE(bp) : DMU_OT_NONE; 275 2743 ahrens int err = 0; 276 2743 ahrens 277 2743 ahrens if (issig(JUSTLOOKING) && issig(FORREAL)) 278 2743 ahrens return (EINTR); 279 2743 ahrens 280 10922 Jeff if (zb->zb_object != DMU_META_DNODE_OBJECT && 281 10922 Jeff DMU_OBJECT_IS_SPECIAL(zb->zb_object)) { 282 9396 Matthew return (0); 283 10922 Jeff } else if (bp == NULL && zb->zb_object == DMU_META_DNODE_OBJECT) { 284 7837 Matthew uint64_t span = BP_SPAN(dnp, zb->zb_level); 285 7837 Matthew uint64_t dnobj = (zb->zb_blkid * span) >> DNODE_SHIFT; 286 2743 ahrens err = dump_freeobjects(ba, dnobj, span >> DNODE_SHIFT); 287 2743 ahrens } else if (bp == NULL) { 288 7837 Matthew uint64_t span = BP_SPAN(dnp, zb->zb_level); 289 7837 Matthew err = dump_free(ba, zb->zb_object, zb->zb_blkid * span, span); 290 7837 Matthew } else if (zb->zb_level > 0 || type == DMU_OT_OBJSET) { 291 7837 Matthew return (0); 292 7837 Matthew } else if (type == DMU_OT_DNODE) { 293 7837 Matthew dnode_phys_t *blk; 294 2743 ahrens int i; 295 2743 ahrens int blksz = BP_GET_LSIZE(bp); 296 7837 Matthew uint32_t aflags = ARC_WAIT; 297 7837 Matthew arc_buf_t *abuf; 298 2743 ahrens 299 7837 Matthew if (arc_read_nolock(NULL, spa, bp, 300 7837 Matthew arc_getbuf_func, &abuf, ZIO_PRIORITY_ASYNC_READ, 301 7837 Matthew ZIO_FLAG_CANFAIL, &aflags, zb) != 0) 302 7837 Matthew return (EIO); 303 7837 Matthew 304 7837 Matthew blk = abuf->b_data; 305 2743 ahrens for (i = 0; i < blksz >> DNODE_SHIFT; i++) { 306 7837 Matthew uint64_t dnobj = (zb->zb_blkid << 307 7837 Matthew (DNODE_BLOCK_SHIFT - DNODE_SHIFT)) + i; 308 2743 ahrens err = dump_dnode(ba, dnobj, blk+i); 309 2743 ahrens if (err) 310 2743 ahrens break; 311 2743 ahrens } 312 7837 Matthew (void) arc_buf_remove_ref(abuf, &abuf); 313 7837 Matthew } else { /* it's a level-0 block of a regular object */ 314 7837 Matthew uint32_t aflags = ARC_WAIT; 315 7837 Matthew arc_buf_t *abuf; 316 2743 ahrens int blksz = BP_GET_LSIZE(bp); 317 2743 ahrens 318 7837 Matthew if (arc_read_nolock(NULL, spa, bp, 319 7837 Matthew arc_getbuf_func, &abuf, ZIO_PRIORITY_ASYNC_READ, 320 7837 Matthew ZIO_FLAG_CANFAIL, &aflags, zb) != 0) 321 7837 Matthew return (EIO); 322 2743 ahrens 323 7837 Matthew err = dump_data(ba, type, zb->zb_object, zb->zb_blkid * blksz, 324 7837 Matthew blksz, abuf->b_data); 325 7837 Matthew (void) arc_buf_remove_ref(abuf, &abuf); 326 2743 ahrens } 327 2743 ahrens 328 2743 ahrens ASSERT(err == 0 || err == EINTR); 329 2743 ahrens return (err); 330 2743 ahrens } 331 2743 ahrens 332 2743 ahrens int 333 5367 ahrens dmu_sendbackup(objset_t *tosnap, objset_t *fromsnap, boolean_t fromorigin, 334 5367 ahrens vnode_t *vp, offset_t *off) 335 2743 ahrens { 336 10298 Matthew dsl_dataset_t *ds = tosnap->os_dsl_dataset; 337 10298 Matthew dsl_dataset_t *fromds = fromsnap ? fromsnap->os_dsl_dataset : NULL; 338 2743 ahrens dmu_replay_record_t *drr; 339 2743 ahrens struct backuparg ba; 340 2743 ahrens int err; 341 5367 ahrens uint64_t fromtxg = 0; 342 2743 ahrens 343 2743 ahrens /* tosnap must be a snapshot */ 344 2743 ahrens if (ds->ds_phys->ds_next_snap_obj == 0) 345 2743 ahrens return (EINVAL); 346 2743 ahrens 347 2743 ahrens /* fromsnap must be an earlier snapshot from the same fs as tosnap */ 348 2743 ahrens if (fromds && (ds->ds_dir != fromds->ds_dir || 349 5367 ahrens fromds->ds_phys->ds_creation_txg >= ds->ds_phys->ds_creation_txg)) 350 2743 ahrens return (EXDEV); 351 5367 ahrens 352 5367 ahrens if (fromorigin) { 353 7046 ahrens dsl_pool_t *dp = ds->ds_dir->dd_pool; 354 7046 ahrens 355 5367 ahrens if (fromsnap) 356 5367 ahrens return (EINVAL); 357 5367 ahrens 358 7046 ahrens if (dsl_dir_is_clone(ds->ds_dir)) { 359 5367 ahrens rw_enter(&dp->dp_config_rwlock, RW_READER); 360 6689 maybee err = dsl_dataset_hold_obj(dp, 361 6689 maybee ds->ds_dir->dd_phys->dd_origin_obj, FTAG, &fromds); 362 5367 ahrens rw_exit(&dp->dp_config_rwlock); 363 5367 ahrens if (err) 364 5367 ahrens return (err); 365 5367 ahrens } else { 366 5367 ahrens fromorigin = B_FALSE; 367 5367 ahrens } 368 5367 ahrens } 369 5367 ahrens 370 2743 ahrens 371 2743 ahrens drr = kmem_zalloc(sizeof (dmu_replay_record_t), KM_SLEEP); 372 2743 ahrens drr->drr_type = DRR_BEGIN; 373 2743 ahrens drr->drr_u.drr_begin.drr_magic = DMU_BACKUP_MAGIC; 374 11007 Lori DMU_SET_STREAM_HDRTYPE(drr->drr_u.drr_begin.drr_versioninfo, 375 11007 Lori DMU_SUBSTREAM); 376 2743 ahrens drr->drr_u.drr_begin.drr_creation_time = 377 2743 ahrens ds->ds_phys->ds_creation_time; 378 10298 Matthew drr->drr_u.drr_begin.drr_type = tosnap->os_phys->os_type; 379 5367 ahrens if (fromorigin) 380 5367 ahrens drr->drr_u.drr_begin.drr_flags |= DRR_FLAG_CLONE; 381 2743 ahrens drr->drr_u.drr_begin.drr_toguid = ds->ds_phys->ds_guid; 382 6492 timh if (ds->ds_phys->ds_flags & DS_FLAG_CI_DATASET) 383 6492 timh drr->drr_u.drr_begin.drr_flags |= DRR_FLAG_CI_DATA; 384 6492 timh 385 2743 ahrens if (fromds) 386 2743 ahrens drr->drr_u.drr_begin.drr_fromguid = fromds->ds_phys->ds_guid; 387 2743 ahrens dsl_dataset_name(ds, drr->drr_u.drr_begin.drr_toname); 388 2743 ahrens 389 5367 ahrens if (fromds) 390 5367 ahrens fromtxg = fromds->ds_phys->ds_creation_txg; 391 5367 ahrens if (fromorigin) 392 6689 maybee dsl_dataset_rele(fromds, FTAG); 393 5367 ahrens 394 2743 ahrens ba.drr = drr; 395 2743 ahrens ba.vp = vp; 396 2743 ahrens ba.os = tosnap; 397 5367 ahrens ba.off = off; 398 11007 Lori ba.toguid = ds->ds_phys->ds_guid; 399 2743 ahrens ZIO_SET_CHECKSUM(&ba.zc, 0, 0, 0, 0); 400 11007 Lori ba.pending_op = PENDING_NONE; 401 2743 ahrens 402 11007 Lori if (dump_bytes(&ba, drr, sizeof (dmu_replay_record_t)) != 0) { 403 2743 ahrens kmem_free(drr, sizeof (dmu_replay_record_t)); 404 2743 ahrens return (ba.err); 405 2743 ahrens } 406 2743 ahrens 407 7837 Matthew err = traverse_dataset(ds, fromtxg, TRAVERSE_PRE | TRAVERSE_PREFETCH, 408 2743 ahrens backup_cb, &ba); 409 11007 Lori 410 11007 Lori if (ba.pending_op != PENDING_NONE) 411 11007 Lori if (dump_bytes(&ba, drr, sizeof (dmu_replay_record_t)) != 0) 412 11007 Lori err = EINTR; 413 2743 ahrens 414 2743 ahrens if (err) { 415 2743 ahrens if (err == EINTR && ba.err) 416 2743 ahrens err = ba.err; 417 3655 gw25295 kmem_free(drr, sizeof (dmu_replay_record_t)); 418 2743 ahrens return (err); 419 2743 ahrens } 420 2743 ahrens 421 2743 ahrens bzero(drr, sizeof (dmu_replay_record_t)); 422 2743 ahrens drr->drr_type = DRR_END; 423 2743 ahrens drr->drr_u.drr_end.drr_checksum = ba.zc; 424 11007 Lori drr->drr_u.drr_end.drr_toguid = ba.toguid; 425 2743 ahrens 426 11007 Lori if (dump_bytes(&ba, drr, sizeof (dmu_replay_record_t)) != 0) { 427 3655 gw25295 kmem_free(drr, sizeof (dmu_replay_record_t)); 428 2743 ahrens return (ba.err); 429 3655 gw25295 } 430 2743 ahrens 431 2743 ahrens kmem_free(drr, sizeof (dmu_replay_record_t)); 432 2743 ahrens 433 2743 ahrens return (0); 434 2743 ahrens } 435 2743 ahrens 436 5367 ahrens struct recvbeginsyncarg { 437 5367 ahrens const char *tofs; 438 5367 ahrens const char *tosnap; 439 5367 ahrens dsl_dataset_t *origin; 440 5367 ahrens uint64_t fromguid; 441 5367 ahrens dmu_objset_type_t type; 442 5367 ahrens void *tag; 443 5367 ahrens boolean_t force; 444 6492 timh uint64_t dsflags; 445 5367 ahrens char clonelastname[MAXNAMELEN]; 446 5367 ahrens dsl_dataset_t *ds; /* the ds to recv into; returned from the syncfunc */ 447 2743 ahrens }; 448 2743 ahrens 449 5367 ahrens /* ARGSUSED */ 450 2743 ahrens static int 451 10272 Matthew recv_new_check(void *arg1, void *arg2, dmu_tx_t *tx) 452 2743 ahrens { 453 5367 ahrens dsl_dir_t *dd = arg1; 454 5367 ahrens struct recvbeginsyncarg *rbsa = arg2; 455 5367 ahrens objset_t *mos = dd->dd_pool->dp_meta_objset; 456 5367 ahrens uint64_t val; 457 5367 ahrens int err; 458 5367 ahrens 459 5367 ahrens err = zap_lookup(mos, dd->dd_phys->dd_child_dir_zapobj, 460 5367 ahrens strrchr(rbsa->tofs, '/') + 1, sizeof (uint64_t), 1, &val); 461 5367 ahrens 462 5367 ahrens if (err != ENOENT) 463 5367 ahrens return (err ? err : EEXIST); 464 5367 ahrens 465 5367 ahrens if (rbsa->origin) { 466 5367 ahrens /* make sure it's a snap in the same pool */ 467 5367 ahrens if (rbsa->origin->ds_dir->dd_pool != dd->dd_pool) 468 5367 ahrens return (EXDEV); 469 10272 Matthew if (!dsl_dataset_is_snapshot(rbsa->origin)) 470 5367 ahrens return (EINVAL); 471 5367 ahrens if (rbsa->origin->ds_phys->ds_guid != rbsa->fromguid) 472 5367 ahrens return (ENODEV); 473 5367 ahrens } 474 5367 ahrens 475 5367 ahrens return (0); 476 5367 ahrens } 477 5367 ahrens 478 5367 ahrens static void 479 10272 Matthew recv_new_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx) 480 5367 ahrens { 481 5367 ahrens dsl_dir_t *dd = arg1; 482 5367 ahrens struct recvbeginsyncarg *rbsa = arg2; 483 6689 maybee uint64_t flags = DS_FLAG_INCONSISTENT | rbsa->dsflags; 484 5367 ahrens uint64_t dsobj; 485 5367 ahrens 486 10272 Matthew /* Create and open new dataset. */ 487 5367 ahrens dsobj = dsl_dataset_create_sync(dd, strrchr(rbsa->tofs, '/') + 1, 488 6492 timh rbsa->origin, flags, cr, tx); 489 10272 Matthew VERIFY(0 == dsl_dataset_own_obj(dd->dd_pool, dsobj, 490 10298 Matthew B_TRUE, dmu_recv_tag, &rbsa->ds)); 491 5367 ahrens 492 10272 Matthew if (rbsa->origin == NULL) { 493 10272 Matthew (void) dmu_objset_create_impl(dd->dd_pool->dp_spa, 494 10272 Matthew rbsa->ds, &rbsa->ds->ds_phys->ds_bp, rbsa->type, tx); 495 5367 ahrens } 496 5367 ahrens 497 10272 Matthew spa_history_internal_log(LOG_DS_REPLAY_FULL_SYNC, 498 10272 Matthew dd->dd_pool->dp_spa, tx, cr, "dataset = %lld", dsobj); 499 5367 ahrens } 500 5367 ahrens 501 5367 ahrens /* ARGSUSED */ 502 5367 ahrens static int 503 10272 Matthew recv_existing_check(void *arg1, void *arg2, dmu_tx_t *tx) 504 5367 ahrens { 505 5367 ahrens dsl_dataset_t *ds = arg1; 506 5367 ahrens struct recvbeginsyncarg *rbsa = arg2; 507 2743 ahrens int err; 508 2743 ahrens uint64_t val; 509 5367 ahrens 510 5367 ahrens /* must not have any changes since most recent snapshot */ 511 5367 ahrens if (!rbsa->force && dsl_dataset_modified_since_lastsnap(ds)) 512 5367 ahrens return (ETXTBSY); 513 2743 ahrens 514 10272 Matthew if (rbsa->fromguid) { 515 10272 Matthew /* if incremental, most recent snapshot must match fromguid */ 516 10272 Matthew if (ds->ds_prev == NULL) 517 10272 Matthew return (ENODEV); 518 11022 Tom 519 11022 Tom /* 520 11022 Tom * most recent snapshot must match fromguid, or there are no 521 11022 Tom * changes since the fromguid one 522 11022 Tom */ 523 11022 Tom if (ds->ds_prev->ds_phys->ds_guid != rbsa->fromguid) { 524 11022 Tom uint64_t birth = ds->ds_prev->ds_phys->ds_bp.blk_birth; 525 11022 Tom uint64_t obj = ds->ds_prev->ds_phys->ds_prev_snap_obj; 526 11022 Tom while (obj != 0) { 527 11022 Tom dsl_dataset_t *snap; 528 11022 Tom err = dsl_dataset_hold_obj(ds->ds_dir->dd_pool, 529 11022 Tom obj, FTAG, &snap); 530 11022 Tom if (err) 531 11022 Tom return (ENODEV); 532 11022 Tom if (snap->ds_phys->ds_creation_txg < birth) { 533 11022 Tom dsl_dataset_rele(snap, FTAG); 534 11022 Tom return (ENODEV); 535 11022 Tom } 536 11022 Tom if (snap->ds_phys->ds_guid == rbsa->fromguid) { 537 11022 Tom dsl_dataset_rele(snap, FTAG); 538 11022 Tom break; /* it's ok */ 539 11022 Tom } 540 11022 Tom obj = snap->ds_phys->ds_prev_snap_obj; 541 11022 Tom dsl_dataset_rele(snap, FTAG); 542 11022 Tom } 543 11022 Tom if (obj == 0) 544 11022 Tom return (ENODEV); 545 11022 Tom } 546 10272 Matthew } else { 547 10272 Matthew /* if full, most recent snapshot must be $ORIGIN */ 548 10272 Matthew if (ds->ds_phys->ds_prev_snap_txg >= TXG_INITIAL) 549 10272 Matthew return (ENODEV); 550 10272 Matthew } 551 6083 ek110237 552 6083 ek110237 /* temporary clone name must not exist */ 553 6083 ek110237 err = zap_lookup(ds->ds_dir->dd_pool->dp_meta_objset, 554 6083 ek110237 ds->ds_dir->dd_phys->dd_child_dir_zapobj, 555 6083 ek110237 rbsa->clonelastname, 8, 1, &val); 556 6083 ek110237 if (err == 0) 557 6083 ek110237 return (EEXIST); 558 6083 ek110237 if (err != ENOENT) 559 6083 ek110237 return (err); 560 2743 ahrens 561 2743 ahrens /* new snapshot name must not exist */ 562 5367 ahrens err = zap_lookup(ds->ds_dir->dd_pool->dp_meta_objset, 563 5367 ahrens ds->ds_phys->ds_snapnames_zapobj, rbsa->tosnap, 8, 1, &val); 564 5367 ahrens if (err == 0) 565 2743 ahrens return (EEXIST); 566 2743 ahrens if (err != ENOENT) 567 5367 ahrens return (err); 568 2743 ahrens return (0); 569 2743 ahrens } 570 2743 ahrens 571 2743 ahrens /* ARGSUSED */ 572 5367 ahrens static void 573 10272 Matthew recv_existing_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx) 574 5326 ek110237 { 575 5367 ahrens dsl_dataset_t *ohds = arg1; 576 5367 ahrens struct recvbeginsyncarg *rbsa = arg2; 577 5367 ahrens dsl_pool_t *dp = ohds->ds_dir->dd_pool; 578 10272 Matthew dsl_dataset_t *cds; 579 6689 maybee uint64_t flags = DS_FLAG_INCONSISTENT | rbsa->dsflags; 580 5367 ahrens uint64_t dsobj; 581 5326 ek110237 582 10272 Matthew /* create and open the temporary clone */ 583 10272 Matthew dsobj = dsl_dataset_create_sync(ohds->ds_dir, rbsa->clonelastname, 584 10272 Matthew ohds->ds_prev, flags, cr, tx); 585 10298 Matthew VERIFY(0 == dsl_dataset_own_obj(dp, dsobj, B_TRUE, dmu_recv_tag, &cds)); 586 10272 Matthew 587 10272 Matthew /* 588 10272 Matthew * If we actually created a non-clone, we need to create the 589 10272 Matthew * objset in our new dataset. 590 10272 Matthew */ 591 10272 Matthew if (BP_IS_HOLE(dsl_dataset_get_blkptr(cds))) { 592 10272 Matthew (void) dmu_objset_create_impl(dp->dp_spa, 593 10272 Matthew cds, dsl_dataset_get_blkptr(cds), rbsa->type, tx); 594 10272 Matthew } 595 5367 ahrens 596 5367 ahrens rbsa->ds = cds; 597 5367 ahrens 598 5367 ahrens spa_history_internal_log(LOG_DS_REPLAY_INC_SYNC, 599 6689 maybee dp->dp_spa, tx, cr, "dataset = %lld", dsobj); 600 5326 ek110237 } 601 5326 ek110237 602 5367 ahrens /* 603 5367 ahrens * NB: callers *MUST* call dmu_recv_stream() if dmu_recv_begin() 604 5367 ahrens * succeeds; otherwise we will leak the holds on the datasets. 605 5367 ahrens */ 606 5367 ahrens int 607 11007 Lori dmu_recv_begin(char *tofs, char *tosnap, char *top_ds, struct drr_begin *drrb, 608 10204 Matthew boolean_t force, objset_t *origin, dmu_recv_cookie_t *drc) 609 2743 ahrens { 610 5367 ahrens int err = 0; 611 5367 ahrens boolean_t byteswap; 612 10272 Matthew struct recvbeginsyncarg rbsa = { 0 }; 613 11007 Lori uint64_t versioninfo; 614 5367 ahrens int flags; 615 5367 ahrens dsl_dataset_t *ds; 616 2743 ahrens 617 5367 ahrens if (drrb->drr_magic == DMU_BACKUP_MAGIC) 618 5367 ahrens byteswap = FALSE; 619 5367 ahrens else if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC)) 620 5367 ahrens byteswap = TRUE; 621 5367 ahrens else 622 5367 ahrens return (EINVAL); 623 2743 ahrens 624 5367 ahrens rbsa.tofs = tofs; 625 5367 ahrens rbsa.tosnap = tosnap; 626 10298 Matthew rbsa.origin = origin ? origin->os_dsl_dataset : NULL; 627 5367 ahrens rbsa.fromguid = drrb->drr_fromguid; 628 5367 ahrens rbsa.type = drrb->drr_type; 629 5367 ahrens rbsa.tag = FTAG; 630 6492 timh rbsa.dsflags = 0; 631 11007 Lori versioninfo = drrb->drr_versioninfo; 632 5367 ahrens flags = drrb->drr_flags; 633 5367 ahrens 634 5367 ahrens if (byteswap) { 635 5367 ahrens rbsa.type = BSWAP_32(rbsa.type); 636 5367 ahrens rbsa.fromguid = BSWAP_64(rbsa.fromguid); 637 11007 Lori versioninfo = BSWAP_64(versioninfo); 638 5367 ahrens flags = BSWAP_32(flags); 639 5367 ahrens } 640 5367 ahrens 641 11007 Lori if (DMU_GET_STREAM_HDRTYPE(versioninfo) == DMU_COMPOUNDSTREAM || 642 5367 ahrens rbsa.type >= DMU_OST_NUMTYPES || 643 5367 ahrens ((flags & DRR_FLAG_CLONE) && origin == NULL)) 644 5367 ahrens return (EINVAL); 645 6492 timh 646 6492 timh if (flags & DRR_FLAG_CI_DATA) 647 6492 timh rbsa.dsflags = DS_FLAG_CI_DATASET; 648 5367 ahrens 649 5367 ahrens bzero(drc, sizeof (dmu_recv_cookie_t)); 650 5367 ahrens drc->drc_drrb = drrb; 651 5367 ahrens drc->drc_tosnap = tosnap; 652 11007 Lori drc->drc_top_ds = top_ds; 653 5367 ahrens drc->drc_force = force; 654 5367 ahrens 655 5367 ahrens /* 656 5367 ahrens * Process the begin in syncing context. 657 5367 ahrens */ 658 5367 ahrens 659 10272 Matthew /* open the dataset we are logically receiving into */ 660 10272 Matthew err = dsl_dataset_hold(tofs, dmu_recv_tag, &ds); 661 10272 Matthew if (err == 0) { 662 10272 Matthew /* target fs already exists; recv into temp clone */ 663 5367 ahrens 664 10272 Matthew /* Can't recv a clone into an existing fs */ 665 10272 Matthew if (flags & DRR_FLAG_CLONE) { 666 10272 Matthew dsl_dataset_rele(ds, dmu_recv_tag); 667 10272 Matthew return (EINVAL); 668 10272 Matthew } 669 5367 ahrens 670 10204 Matthew /* must not have an incremental recv already in progress */ 671 10204 Matthew if (!mutex_tryenter(&ds->ds_recvlock)) { 672 10204 Matthew dsl_dataset_rele(ds, dmu_recv_tag); 673 10204 Matthew return (EBUSY); 674 10204 Matthew } 675 10204 Matthew 676 10272 Matthew /* tmp clone name is: tofs/%tosnap" */ 677 10272 Matthew (void) snprintf(rbsa.clonelastname, sizeof (rbsa.clonelastname), 678 10272 Matthew "%%%s", tosnap); 679 5367 ahrens rbsa.force = force; 680 5367 ahrens err = dsl_sync_task_do(ds->ds_dir->dd_pool, 681 10272 Matthew recv_existing_check, recv_existing_sync, ds, &rbsa, 5); 682 5367 ahrens if (err) { 683 10204 Matthew mutex_exit(&ds->ds_recvlock); 684 6689 maybee dsl_dataset_rele(ds, dmu_recv_tag); 685 5367 ahrens return (err); 686 5367 ahrens } 687 5367 ahrens drc->drc_logical_ds = ds; 688 5367 ahrens drc->drc_real_ds = rbsa.ds; 689 10272 Matthew } else if (err == ENOENT) { 690 10272 Matthew /* target fs does not exist; must be a full backup or clone */ 691 10272 Matthew char *cp; 692 5367 ahrens 693 10272 Matthew /* 694 10272 Matthew * If it's a non-clone incremental, we are missing the 695 10272 Matthew * target fs, so fail the recv. 696 10272 Matthew */ 697 10272 Matthew if (rbsa.fromguid && !(flags & DRR_FLAG_CLONE)) 698 10272 Matthew return (ENOENT); 699 10272 Matthew 700 10272 Matthew /* Open the parent of tofs */ 701 10272 Matthew cp = strrchr(tofs, '/'); 702 10272 Matthew *cp = '\0'; 703 10819 Chris err = dsl_dataset_hold(tofs, FTAG, &ds); 704 10272 Matthew *cp = '/'; 705 5367 ahrens if (err) 706 5367 ahrens return (err); 707 5367 ahrens 708 10272 Matthew err = dsl_sync_task_do(ds->ds_dir->dd_pool, 709 10272 Matthew recv_new_check, recv_new_sync, ds->ds_dir, &rbsa, 5); 710 10819 Chris dsl_dataset_rele(ds, FTAG); 711 5367 ahrens if (err) 712 5367 ahrens return (err); 713 5367 ahrens drc->drc_logical_ds = drc->drc_real_ds = rbsa.ds; 714 5367 ahrens drc->drc_newfs = B_TRUE; 715 5367 ahrens } 716 2743 ahrens 717 10272 Matthew return (err); 718 2743 ahrens } 719 2743 ahrens 720 5367 ahrens struct restorearg { 721 5367 ahrens int err; 722 5367 ahrens int byteswap; 723 5367 ahrens vnode_t *vp; 724 5367 ahrens char *buf; 725 5367 ahrens uint64_t voff; 726 5367 ahrens int bufsize; /* amount of memory allocated for buf */ 727 5367 ahrens zio_cksum_t cksum; 728 11007 Lori avl_tree_t guid_to_ds_map; 729 5326 ek110237 }; 730 11007 Lori 731 11007 Lori typedef struct guid_map_entry { 732 11007 Lori uint64_t guid; 733 11007 Lori dsl_dataset_t *gme_ds; 734 11007 Lori avl_node_t avlnode; 735 11007 Lori } guid_map_entry_t; 736 11007 Lori 737 11007 Lori static int 738 11007 Lori guid_compare(const void *arg1, const void *arg2) 739 11007 Lori { 740 11007 Lori const guid_map_entry_t *gmep1 = arg1; 741 11007 Lori const guid_map_entry_t *gmep2 = arg2; 742 11007 Lori 743 11007 Lori if (gmep1->guid < gmep2->guid) 744 11007 Lori return (-1); 745 11007 Lori else if (gmep1->guid > gmep2->guid) 746 11007 Lori return (1); 747 11007 Lori return (0); 748 11007 Lori } 749 11007 Lori 750 11007 Lori /* 751 11007 Lori * This function is a callback used by dmu_objset_find() (which 752 11007 Lori * enumerates the object sets) to build an avl tree that maps guids 753 11007 Lori * to datasets. The resulting table is used when processing DRR_WRITE_BYREF 754 11007 Lori * send stream records. These records, which are used in dedup'ed 755 11007 Lori * streams, do not contain data themselves, but refer to a copy 756 11007 Lori * of the data block that has already been written because it was 757 11007 Lori * earlier in the stream. That previous copy is identified by the 758 11007 Lori * guid of the dataset with the referenced data. 759 11007 Lori */ 760 11007 Lori int 761 11007 Lori find_ds_by_guid(char *name, void *arg) 762 11007 Lori { 763 11007 Lori dsl_dataset_t *ds, *snapds; 764 11007 Lori avl_tree_t *guid_map = arg; 765 11007 Lori guid_map_entry_t *gmep; 766 11007 Lori dsl_pool_t *dp; 767 11007 Lori int err; 768 11007 Lori uint64_t lastobj, firstobj; 769 11007 Lori 770 11007 Lori if (dsl_dataset_hold(name, FTAG, &ds) != 0) 771 11007 Lori return (0); 772 11007 Lori 773 11007 Lori dp = ds->ds_dir->dd_pool; 774 11007 Lori rw_enter(&dp->dp_config_rwlock, RW_READER); 775 11007 Lori firstobj = ds->ds_dir->dd_phys->dd_origin_obj; 776 11007 Lori lastobj = ds->ds_phys->ds_prev_snap_obj; 777 11007 Lori 778 11007 Lori while (lastobj != firstobj) { 779 11007 Lori err = dsl_dataset_hold_obj(dp, lastobj, guid_map, &snapds); 780 11007 Lori if (err) { 781 11007 Lori /* 782 11007 Lori * Skip this snapshot and move on. It's not 783 11007 Lori * clear why this would ever happen, but the 784 11007 Lori * remainder of the snapshot streadm can be 785 11007 Lori * processed. 786 11007 Lori */ 787 11007 Lori rw_exit(&dp->dp_config_rwlock); 788 11007 Lori dsl_dataset_rele(ds, FTAG); 789 11007 Lori return (0); 790 11007 Lori } 791 11007 Lori 792 11007 Lori gmep = kmem_alloc(sizeof (guid_map_entry_t), KM_SLEEP); 793 11007 Lori gmep->guid = snapds->ds_phys->ds_guid; 794 11007 Lori gmep->gme_ds = snapds; 795 11007 Lori avl_add(guid_map, gmep); 796 11007 Lori lastobj = snapds->ds_phys->ds_prev_snap_obj; 797 11007 Lori } 798 11007 Lori 799 11007 Lori rw_exit(&dp->dp_config_rwlock); 800 11007 Lori dsl_dataset_rele(ds, FTAG); 801 11007 Lori 802 11007 Lori return (0); 803 11007 Lori } 804 2743 ahrens 805 2743 ahrens static void * 806 2743 ahrens restore_read(struct restorearg *ra, int len) 807 2743 ahrens { 808 2743 ahrens void *rv; 809 5367 ahrens int done = 0; 810 2743 ahrens 811 2743 ahrens /* some things will require 8-byte alignment, so everything must */ 812 2743 ahrens ASSERT3U(len % 8, ==, 0); 813 2743 ahrens 814 5367 ahrens while (done < len) { 815 2743 ahrens ssize_t resid; 816 2743 ahrens 817 2743 ahrens ra->err = vn_rdwr(UIO_READ, ra->vp, 818 5367 ahrens (caddr_t)ra->buf + done, len - done, 819 2743 ahrens ra->voff, UIO_SYSSPACE, FAPPEND, 820 2743 ahrens RLIM64_INFINITY, CRED(), &resid); 821 2743 ahrens 822 5367 ahrens if (resid == len - done) 823 2743 ahrens ra->err = EINVAL; 824 5367 ahrens ra->voff += len - done - resid; 825 5367 ahrens done = len - resid; 826 2743 ahrens if (ra->err) 827 2743 ahrens return (NULL); 828 2743 ahrens } 829 2743 ahrens 830 5367 ahrens ASSERT3U(done, ==, len); 831 5367 ahrens rv = ra->buf; 832 2743 ahrens if (ra->byteswap) 833 5367 ahrens fletcher_4_incremental_byteswap(rv, len, &ra->cksum); 834 2743 ahrens else 835 5367 ahrens fletcher_4_incremental_native(rv, len, &ra->cksum); 836 2743 ahrens return (rv); 837 2743 ahrens } 838 2743 ahrens 839 2743 ahrens static void 840 2743 ahrens backup_byteswap(dmu_replay_record_t *drr) 841 2743 ahrens { 842 2743 ahrens #define DO64(X) (drr->drr_u.X = BSWAP_64(drr->drr_u.X)) 843 2743 ahrens #define DO32(X) (drr->drr_u.X = BSWAP_32(drr->drr_u.X)) 844 2743 ahrens drr->drr_type = BSWAP_32(drr->drr_type); 845 5367 ahrens drr->drr_payloadlen = BSWAP_32(drr->drr_payloadlen); 846 2743 ahrens switch (drr->drr_type) { 847 2743 ahrens case DRR_BEGIN: 848 2743 ahrens DO64(drr_begin.drr_magic); 849 11007 Lori DO64(drr_begin.drr_versioninfo); 850 2743 ahrens DO64(drr_begin.drr_creation_time); 851 2743 ahrens DO32(drr_begin.drr_type); 852 5367 ahrens DO32(drr_begin.drr_flags); 853 2743 ahrens DO64(drr_begin.drr_toguid); 854 2743 ahrens DO64(drr_begin.drr_fromguid); 855 2743 ahrens break; 856 2743 ahrens case DRR_OBJECT: 857 2743 ahrens DO64(drr_object.drr_object); 858 2743 ahrens /* DO64(drr_object.drr_allocation_txg); */ 859 2743 ahrens DO32(drr_object.drr_type); 860 2743 ahrens DO32(drr_object.drr_bonustype); 861 2743 ahrens DO32(drr_object.drr_blksz); 862 2743 ahrens DO32(drr_object.drr_bonuslen); 863 11007 Lori DO64(drr_object.drr_toguid); 864 2743 ahrens break; 865 2743 ahrens case DRR_FREEOBJECTS: 866 2743 ahrens DO64(drr_freeobjects.drr_firstobj); 867 2743 ahrens DO64(drr_freeobjects.drr_numobjs); 868 11007 Lori DO64(drr_freeobjects.drr_toguid); 869 2743 ahrens break; 870 2743 ahrens case DRR_WRITE: 871 2743 ahrens DO64(drr_write.drr_object); 872 2743 ahrens DO32(drr_write.drr_type); 873 2743 ahrens DO64(drr_write.drr_offset); 874 2743 ahrens DO64(drr_write.drr_length); 875 11007 Lori DO64(drr_write.drr_toguid); 876 11007 Lori DO64(drr_write.drr_blkcksum.zc_word[0]); 877 11007 Lori DO64(drr_write.drr_blkcksum.zc_word[1]); 878 11007 Lori DO64(drr_write.drr_blkcksum.zc_word[2]); 879 11007 Lori DO64(drr_write.drr_blkcksum.zc_word[3]); 880 11007 Lori break; 881 11007 Lori case DRR_WRITE_BYREF: 882 11007 Lori DO64(drr_write_byref.drr_object); 883 11007 Lori DO64(drr_write_byref.drr_offset); 884 11007 Lori DO64(drr_write_byref.drr_length); 885 11007 Lori DO64(drr_write_byref.drr_toguid); 886 11007 Lori DO64(drr_write_byref.drr_refguid); 887 11007 Lori DO64(drr_write_byref.drr_refobject); 888 11007 Lori DO64(drr_write_byref.drr_refoffset); 889 11007 Lori DO64(drr_write_byref.drr_blkcksum.zc_word[0]); 890 11007 Lori DO64(drr_write_byref.drr_blkcksum.zc_word[1]); 891 11007 Lori DO64(drr_write_byref.drr_blkcksum.zc_word[2]); 892 11007 Lori DO64(drr_write_byref.drr_blkcksum.zc_word[3]); 893 2743 ahrens break; 894 2743 ahrens case DRR_FREE: 895 2743 ahrens DO64(drr_free.drr_object); 896 2743 ahrens DO64(drr_free.drr_offset); 897 2743 ahrens DO64(drr_free.drr_length); 898 11007 Lori DO64(drr_free.drr_toguid); 899 2743 ahrens break; 900 2743 ahrens case DRR_END: 901 2743 ahrens DO64(drr_end.drr_checksum.zc_word[0]); 902 2743 ahrens DO64(drr_end.drr_checksum.zc_word[1]); 903 2743 ahrens DO64(drr_end.drr_checksum.zc_word[2]); 904 2743 ahrens DO64(drr_end.drr_checksum.zc_word[3]); 905 11007 Lori DO64(drr_end.drr_toguid); 906 2743 ahrens break; 907 2743 ahrens } 908 2743 ahrens #undef DO64 909 2743 ahrens #undef DO32 910 2743 ahrens } 911 2743 ahrens 912 2743 ahrens static int 913 2743 ahrens restore_object(struct restorearg *ra, objset_t *os, struct drr_object *drro) 914 2743 ahrens { 915 2743 ahrens int err; 916 2743 ahrens dmu_tx_t *tx; 917 7994 Tim void *data = NULL; 918 2743 ahrens 919 2743 ahrens if (drro->drr_type == DMU_OT_NONE || 920 2743 ahrens drro->drr_type >= DMU_OT_NUMTYPES || 921 2743 ahrens drro->drr_bonustype >= DMU_OT_NUMTYPES || 922 11007 Lori drro->drr_checksumtype >= ZIO_CHECKSUM_FUNCTIONS || 923 2743 ahrens drro->drr_compress >= ZIO_COMPRESS_FUNCTIONS || 924 2743 ahrens P2PHASE(drro->drr_blksz, SPA_MINBLOCKSIZE) || 925 2743 ahrens drro->drr_blksz < SPA_MINBLOCKSIZE || 926 2743 ahrens drro->drr_blksz > SPA_MAXBLOCKSIZE || 927 2743 ahrens drro->drr_bonuslen > DN_MAX_BONUSLEN) { 928 2743 ahrens return (EINVAL); 929 7994 Tim } 930 7994 Tim 931 8986 Mark err = dmu_object_info(os, drro->drr_object, NULL); 932 8986 Mark 933 8986 Mark if (err != 0 && err != ENOENT) 934 8986 Mark return (EINVAL); 935 8986 Mark 936 7994 Tim if (drro->drr_bonuslen) { 937 7994 Tim data = restore_read(ra, P2ROUNDUP(drro->drr_bonuslen, 8)); 938 7994 Tim if (ra->err) 939 7994 Tim return (ra->err); 940 2743 ahrens } 941 2743 ahrens 942 2743 ahrens if (err == ENOENT) { 943 2743 ahrens /* currently free, want to be allocated */ 944 8986 Mark tx = dmu_tx_create(os); 945 2743 ahrens dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT); 946 2743 ahrens err = dmu_tx_assign(tx, TXG_WAIT); 947 2743 ahrens if (err) { 948 2743 ahrens dmu_tx_abort(tx); 949 2743 ahrens return (err); 950 2743 ahrens } 951 2743 ahrens err = dmu_object_claim(os, drro->drr_object, 952 2743 ahrens drro->drr_type, drro->drr_blksz, 953 2743 ahrens drro->drr_bonustype, drro->drr_bonuslen, tx); 954 8986 Mark dmu_tx_commit(tx); 955 2743 ahrens } else { 956 2743 ahrens /* currently allocated, want to be allocated */ 957 2743 ahrens err = dmu_object_reclaim(os, drro->drr_object, 958 2743 ahrens drro->drr_type, drro->drr_blksz, 959 8986 Mark drro->drr_bonustype, drro->drr_bonuslen); 960 2743 ahrens } 961 8986 Mark if (err) 962 8986 Mark return (EINVAL); 963 8986 Mark 964 8986 Mark tx = dmu_tx_create(os); 965 8986 Mark dmu_tx_hold_bonus(tx, drro->drr_object); 966 8986 Mark err = dmu_tx_assign(tx, TXG_WAIT); 967 2743 ahrens if (err) { 968 8986 Mark dmu_tx_abort(tx); 969 8986 Mark return (err); 970 2743 ahrens } 971 2743 ahrens 972 11007 Lori dmu_object_set_checksum(os, drro->drr_object, drro->drr_checksumtype, 973 11007 Lori tx); 974 2743 ahrens dmu_object_set_compress(os, drro->drr_object, drro->drr_compress, tx); 975 2743 ahrens 976 7994 Tim if (data != NULL) { 977 2743 ahrens dmu_buf_t *db; 978 7994 Tim 979 2743 ahrens VERIFY(0 == dmu_bonus_hold(os, drro->drr_object, FTAG, &db)); 980 2743 ahrens dmu_buf_will_dirty(db, tx); 981 2743 ahrens 982 4944 maybee ASSERT3U(db->db_size, >=, drro->drr_bonuslen); 983 4944 maybee bcopy(data, db->db_data, drro->drr_bonuslen); 984 2743 ahrens if (ra->byteswap) { 985 2743 ahrens dmu_ot[drro->drr_bonustype].ot_byteswap(db->db_data, 986 2743 ahrens drro->drr_bonuslen); 987 2743 ahrens } 988 2743 ahrens dmu_buf_rele(db, FTAG); 989 2743 ahrens } 990 2743 ahrens dmu_tx_commit(tx); 991 2743 ahrens return (0); 992 2743 ahrens } 993 2743 ahrens 994 2743 ahrens /* ARGSUSED */ 995 2743 ahrens static int 996 2743 ahrens restore_freeobjects(struct restorearg *ra, objset_t *os, 997 2743 ahrens struct drr_freeobjects *drrfo) 998 2743 ahrens { 999 2743 ahrens uint64_t obj; 1000 2743 ahrens 1001 2743 ahrens if (drrfo->drr_firstobj + drrfo->drr_numobjs < drrfo->drr_firstobj) 1002 2743 ahrens return (EINVAL); 1003 2743 ahrens 1004 2743 ahrens for (obj = drrfo->drr_firstobj; 1005 3087 ahrens obj < drrfo->drr_firstobj + drrfo->drr_numobjs; 1006 3087 ahrens (void) dmu_object_next(os, &obj, FALSE, 0)) { 1007 2743 ahrens int err; 1008 2743 ahrens 1009 2743 ahrens if (dmu_object_info(os, obj, NULL) != 0) 1010 2743 ahrens continue; 1011 2743 ahrens 1012 6992 maybee err = dmu_free_object(os, obj); 1013 6992 maybee if (err) 1014 2743 ahrens return (err); 1015 2743 ahrens } 1016 2743 ahrens return (0); 1017 2743 ahrens } 1018 2743 ahrens 1019 2743 ahrens static int 1020 2743 ahrens restore_write(struct restorearg *ra, objset_t *os, 1021 2743 ahrens struct drr_write *drrw) 1022 2743 ahrens { 1023 2743 ahrens dmu_tx_t *tx; 1024 2743 ahrens void *data; 1025 2743 ahrens int err; 1026 2743 ahrens 1027 2743 ahrens if (drrw->drr_offset + drrw->drr_length < drrw->drr_offset || 1028 2743 ahrens drrw->drr_type >= DMU_OT_NUMTYPES) 1029 2743 ahrens return (EINVAL); 1030 2743 ahrens 1031 2743 ahrens data = restore_read(ra, drrw->drr_length); 1032 2743 ahrens if (data == NULL) 1033 2743 ahrens return (ra->err); 1034 2743 ahrens 1035 2743 ahrens if (dmu_object_info(os, drrw->drr_object, NULL) != 0) 1036 2743 ahrens return (EINVAL); 1037 2743 ahrens 1038 2743 ahrens tx = dmu_tx_create(os); 1039 2743 ahrens 1040 2743 ahrens dmu_tx_hold_write(tx, drrw->drr_object, 1041 2743 ahrens drrw->drr_offset, drrw->drr_length); 1042 2743 ahrens err = dmu_tx_assign(tx, TXG_WAIT); 1043 2743 ahrens if (err) { 1044 2743 ahrens dmu_tx_abort(tx); 1045 2743 ahrens return (err); 1046 2743 ahrens } 1047 2743 ahrens if (ra->byteswap) 1048 2743 ahrens dmu_ot[drrw->drr_type].ot_byteswap(data, drrw->drr_length); 1049 2743 ahrens dmu_write(os, drrw->drr_object, 1050 2743 ahrens drrw->drr_offset, drrw->drr_length, data, tx); 1051 2743 ahrens dmu_tx_commit(tx); 1052 2743 ahrens return (0); 1053 2743 ahrens } 1054 2743 ahrens 1055 11007 Lori /* 1056 11007 Lori * Handle a DRR_WRITE_BYREF record. This record is used in dedup'ed 1057 11007 Lori * streams to refer to a copy of the data that is already on the 1058 11007 Lori * system because it came in earlier in the stream. This function 1059 11007 Lori * finds the earlier copy of the data, and uses that copy instead of 1060 11007 Lori * data from the stream to fulfill this write. 1061 11007 Lori */ 1062 11007 Lori static int 1063 11007 Lori restore_write_byref(struct restorearg *ra, objset_t *os, 1064 11007 Lori struct drr_write_byref *drrwbr) 1065 11007 Lori { 1066 11007 Lori dmu_tx_t *tx; 1067 11007 Lori int err; 1068 11007 Lori guid_map_entry_t gmesrch; 1069 11007 Lori guid_map_entry_t *gmep; 1070 11007 Lori avl_index_t where; 1071 11007 Lori objset_t *ref_os = NULL; 1072 11007 Lori dmu_buf_t *dbp; 1073 11007 Lori 1074 11007 Lori if (drrwbr->drr_offset + drrwbr->drr_length < drrwbr->drr_offset) 1075 11007 Lori return (EINVAL); 1076 11007 Lori 1077 11007 Lori /* 1078 11007 Lori * If the GUID of the referenced dataset is different from the 1079 11007 Lori * GUID of the target dataset, find the referenced dataset. 1080 11007 Lori */ 1081 11007 Lori if (drrwbr->drr_toguid != drrwbr->drr_refguid) { 1082 11007 Lori gmesrch.guid = drrwbr->drr_refguid; 1083 11007 Lori if ((gmep = avl_find(&ra->guid_to_ds_map, &gmesrch, 1084 11007 Lori &where)) == NULL) { 1085 11007 Lori return (EINVAL); 1086 11007 Lori } 1087 11007 Lori if (dmu_objset_from_ds(gmep->gme_ds, &ref_os)) 1088 11007 Lori return (EINVAL); 1089 11007 Lori } else { 1090 11007 Lori ref_os = os; 1091 11007 Lori } 1092 11007 Lori 1093 11007 Lori if (err = dmu_buf_hold(ref_os, drrwbr->drr_refobject, 1094 11007 Lori drrwbr->drr_refoffset, FTAG, &dbp)) 1095 11007 Lori return (err); 1096 11007 Lori 1097 11007 Lori tx = dmu_tx_create(os); 1098 11007 Lori 1099 11007 Lori dmu_tx_hold_write(tx, drrwbr->drr_object, 1100 11007 Lori drrwbr->drr_offset, drrwbr->drr_length); 1101 11007 Lori err = dmu_tx_assign(tx, TXG_WAIT); 1102 11007 Lori if (err) { 1103 11007 Lori dmu_tx_abort(tx); 1104 11007 Lori return (err); 1105 11007 Lori } 1106 11007 Lori dmu_write(os, drrwbr->drr_object, 1107 11007 Lori drrwbr->drr_offset, drrwbr->drr_length, dbp->db_data, tx); 1108 11007 Lori dmu_buf_rele(dbp, FTAG); 1109 11007 Lori dmu_tx_commit(tx); 1110 11007 Lori return (0); 1111 11007 Lori } 1112 11007 Lori 1113 2743 ahrens /* ARGSUSED */ 1114 2743 ahrens static int 1115 2743 ahrens restore_free(struct restorearg *ra, objset_t *os, 1116 2743 ahrens struct drr_free *drrf) 1117 2743 ahrens { 1118 2743 ahrens int err; 1119 2743 ahrens 1120 2743 ahrens if (drrf->drr_length != -1ULL && 1121 2743 ahrens drrf->drr_offset + drrf->drr_length < drrf->drr_offset) 1122 2743 ahrens return (EINVAL); 1123 2743 ahrens 1124 2743 ahrens if (dmu_object_info(os, drrf->drr_object, NULL) != 0) 1125 2743 ahrens return (EINVAL); 1126 2743 ahrens 1127 6992 maybee err = dmu_free_long_range(os, drrf->drr_object, 1128 2743 ahrens drrf->drr_offset, drrf->drr_length); 1129 2743 ahrens return (err); 1130 2743 ahrens } 1131 2743 ahrens 1132 5367 ahrens /* 1133 5367 ahrens * NB: callers *must* call dmu_recv_end() if this succeeds. 1134 5367 ahrens */ 1135 2743 ahrens int 1136 5367 ahrens dmu_recv_stream(dmu_recv_cookie_t *drc, vnode_t *vp, offset_t *voffp) 1137 2743 ahrens { 1138 5367 ahrens struct restorearg ra = { 0 }; 1139 2743 ahrens dmu_replay_record_t *drr; 1140 5367 ahrens objset_t *os; 1141 5367 ahrens zio_cksum_t pcksum; 1142 11007 Lori guid_map_entry_t *gmep; 1143 11007 Lori int featureflags; 1144 2743 ahrens 1145 5367 ahrens if (drc->drc_drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC)) 1146 5367 ahrens ra.byteswap = TRUE; 1147 2743 ahrens 1148 5367 ahrens { 1149 5367 ahrens /* compute checksum of drr_begin record */ 1150 5367 ahrens dmu_replay_record_t *drr; 1151 5367 ahrens drr = kmem_zalloc(sizeof (dmu_replay_record_t), KM_SLEEP); 1152 5367 ahrens 1153 5367 ahrens drr->drr_type = DRR_BEGIN; 1154 5367 ahrens drr->drr_u.drr_begin = *drc->drc_drrb; 1155 5367 ahrens if (ra.byteswap) { 1156 5367 ahrens fletcher_4_incremental_byteswap(drr, 1157 5367 ahrens sizeof (dmu_replay_record_t), &ra.cksum); 1158 5367 ahrens } else { 1159 5367 ahrens fletcher_4_incremental_native(drr, 1160 5367 ahrens sizeof (dmu_replay_record_t), &ra.cksum); 1161 5367 ahrens } 1162 5367 ahrens kmem_free(drr, sizeof (dmu_replay_record_t)); 1163 2743 ahrens } 1164 2743 ahrens 1165 2743 ahrens if (ra.byteswap) { 1166 5367 ahrens struct drr_begin *drrb = drc->drc_drrb; 1167 2743 ahrens drrb->drr_magic = BSWAP_64(drrb->drr_magic); 1168 11007 Lori drrb->drr_versioninfo = BSWAP_64(drrb->drr_versioninfo); 1169 2743 ahrens drrb->drr_creation_time = BSWAP_64(drrb->drr_creation_time); 1170 2743 ahrens drrb->drr_type = BSWAP_32(drrb->drr_type); 1171 2743 ahrens drrb->drr_toguid = BSWAP_64(drrb->drr_toguid); 1172 2743 ahrens drrb->drr_fromguid = BSWAP_64(drrb->drr_fromguid); 1173 2743 ahrens } 1174 2743 ahrens 1175 5367 ahrens ra.vp = vp; 1176 5367 ahrens ra.voff = *voffp; 1177 5367 ahrens ra.bufsize = 1<<20; 1178 5367 ahrens ra.buf = kmem_alloc(ra.bufsize, KM_SLEEP); 1179 2743 ahrens 1180 5367 ahrens /* these were verified in dmu_recv_begin */ 1181 11007 Lori ASSERT(DMU_GET_STREAM_HDRTYPE(drc->drc_drrb->drr_versioninfo) == 1182 11007 Lori DMU_SUBSTREAM); 1183 5367 ahrens ASSERT(drc->drc_drrb->drr_type < DMU_OST_NUMTYPES); 1184 2743 ahrens 1185 2743 ahrens /* 1186 2743 ahrens * Open the objset we are modifying. 1187 2743 ahrens */ 1188 10298 Matthew VERIFY(dmu_objset_from_ds(drc->drc_real_ds, &os) == 0); 1189 2743 ahrens 1190 5367 ahrens ASSERT(drc->drc_real_ds->ds_phys->ds_flags & DS_FLAG_INCONSISTENT); 1191 11007 Lori 1192 11007 Lori featureflags = DMU_GET_FEATUREFLAGS(drc->drc_drrb->drr_versioninfo); 1193 11007 Lori 1194 11007 Lori /* if this stream is dedup'ed, set up the avl tree for guid mapping */ 1195 11007 Lori if (featureflags & DMU_BACKUP_FEATURE_DEDUP) { 1196 11007 Lori avl_create(&ra.guid_to_ds_map, guid_compare, 1197 11007 Lori sizeof (guid_map_entry_t), 1198 11007 Lori offsetof(guid_map_entry_t, avlnode)); 1199 11007 Lori (void) dmu_objset_find(drc->drc_top_ds, find_ds_by_guid, 1200 11007 Lori (void *)&ra.guid_to_ds_map, 1201 11007 Lori DS_FIND_CHILDREN); 1202 11007 Lori } 1203 2743 ahrens 1204 2743 ahrens /* 1205 2743 ahrens * Read records and process them. 1206 2743 ahrens */ 1207 5367 ahrens pcksum = ra.cksum; 1208 2743 ahrens while (ra.err == 0 && 1209 2743 ahrens NULL != (drr = restore_read(&ra, sizeof (*drr)))) { 1210 2743 ahrens if (issig(JUSTLOOKING) && issig(FORREAL)) { 1211 2743 ahrens ra.err = EINTR; 1212 2743 ahrens goto out; 1213 2743 ahrens } 1214 2743 ahrens 1215 2743 ahrens if (ra.byteswap) 1216 2743 ahrens backup_byteswap(drr); 1217 2743 ahrens 1218 2743 ahrens switch (drr->drr_type) { 1219 2743 ahrens case DRR_OBJECT: 1220 2743 ahrens { 1221 2743 ahrens /* 1222 2743 ahrens * We need to make a copy of the record header, 1223 2743 ahrens * because restore_{object,write} may need to 1224 2743 ahrens * restore_read(), which will invalidate drr. 1225 2743 ahrens */ 1226 2743 ahrens struct drr_object drro = drr->drr_u.drr_object; 1227 2743 ahrens ra.err = restore_object(&ra, os, &drro); 1228 2743 ahrens break; 1229 2743 ahrens } 1230 2743 ahrens case DRR_FREEOBJECTS: 1231 2743 ahrens { 1232 2743 ahrens struct drr_freeobjects drrfo = 1233 2743 ahrens drr->drr_u.drr_freeobjects; 1234 2743 ahrens ra.err = restore_freeobjects(&ra, os, &drrfo); 1235 2743 ahrens break; 1236 2743 ahrens } 1237 2743 ahrens case DRR_WRITE: 1238 2743 ahrens { 1239 2743 ahrens struct drr_write drrw = drr->drr_u.drr_write; 1240 2743 ahrens ra.err = restore_write(&ra, os, &drrw); 1241 11007 Lori break; 1242 11007 Lori } 1243 11007 Lori case DRR_WRITE_BYREF: 1244 11007 Lori { 1245 11007 Lori struct drr_write_byref drrwbr = 1246 11007 Lori drr->drr_u.drr_write_byref; 1247 11007 Lori ra.err = restore_write_byref(&ra, os, &drrwbr); 1248 2743 ahrens break; 1249 2743 ahrens } 1250 2743 ahrens case DRR_FREE: 1251 2743 ahrens { 1252 2743 ahrens struct drr_free drrf = drr->drr_u.drr_free; 1253 2743 ahrens ra.err = restore_free(&ra, os, &drrf); 1254 2743 ahrens break; 1255 2743 ahrens } 1256 2743 ahrens case DRR_END: 1257 2743 ahrens { 1258 2743 ahrens struct drr_end drre = drr->drr_u.drr_end; 1259 2743 ahrens /* 1260 2743 ahrens * We compare against the *previous* checksum 1261 2743 ahrens * value, because the stored checksum is of 1262 2743 ahrens * everything before the DRR_END record. 1263 2743 ahrens */ 1264 6479 ahrens if (!ZIO_CHECKSUM_EQUAL(drre.drr_checksum, pcksum)) 1265 2743 ahrens ra.err = ECKSUM; 1266 2743 ahrens goto out; 1267 2743 ahrens } 1268 2743 ahrens default: 1269 2743 ahrens ra.err = EINVAL; 1270 2743 ahrens goto out; 1271 2743 ahrens } 1272 5367 ahrens pcksum = ra.cksum; 1273 2743 ahrens } 1274 6479 ahrens ASSERT(ra.err != 0); 1275 2743 ahrens 1276 2743 ahrens out: 1277 5367 ahrens if (ra.err != 0) { 1278 2743 ahrens /* 1279 10204 Matthew * destroy what we created, so we don't leave it in the 1280 10204 Matthew * inconsistent restoring state. 1281 2743 ahrens */ 1282 5367 ahrens txg_wait_synced(drc->drc_real_ds->ds_dir->dd_pool, 0); 1283 10204 Matthew 1284 10242 chris (void) dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag, 1285 10242 chris B_FALSE); 1286 10204 Matthew if (drc->drc_real_ds != drc->drc_logical_ds) { 1287 10204 Matthew mutex_exit(&drc->drc_logical_ds->ds_recvlock); 1288 10204 Matthew dsl_dataset_rele(drc->drc_logical_ds, dmu_recv_tag); 1289 10204 Matthew } 1290 11007 Lori } 1291 11007 Lori 1292 11007 Lori if (featureflags & DMU_BACKUP_FEATURE_DEDUP) { 1293 11007 Lori void *cookie = NULL; 1294 11007 Lori 1295 11007 Lori while (gmep = avl_destroy_nodes(&ra.guid_to_ds_map, &cookie)) { 1296 11007 Lori dsl_dataset_rele(gmep->gme_ds, &ra.guid_to_ds_map); 1297 11007 Lori kmem_free(gmep, sizeof (guid_map_entry_t)); 1298 11007 Lori } 1299 11007 Lori avl_destroy(&ra.guid_to_ds_map); 1300 2743 ahrens } 1301 2743 ahrens 1302 2743 ahrens kmem_free(ra.buf, ra.bufsize); 1303 5367 ahrens *voffp = ra.voff; 1304 2743 ahrens return (ra.err); 1305 2743 ahrens } 1306 5326 ek110237 1307 5367 ahrens struct recvendsyncarg { 1308 5367 ahrens char *tosnap; 1309 5367 ahrens uint64_t creation_time; 1310 5367 ahrens uint64_t toguid; 1311 5367 ahrens }; 1312 5367 ahrens 1313 5367 ahrens static int 1314 5367 ahrens recv_end_check(void *arg1, void *arg2, dmu_tx_t *tx) 1315 5367 ahrens { 1316 5367 ahrens dsl_dataset_t *ds = arg1; 1317 5367 ahrens struct recvendsyncarg *resa = arg2; 1318 5367 ahrens 1319 5367 ahrens return (dsl_dataset_snapshot_check(ds, resa->tosnap, tx)); 1320 5367 ahrens } 1321 5367 ahrens 1322 5367 ahrens static void 1323 5367 ahrens recv_end_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx) 1324 5367 ahrens { 1325 5367 ahrens dsl_dataset_t *ds = arg1; 1326 5367 ahrens struct recvendsyncarg *resa = arg2; 1327 5367 ahrens 1328 5367 ahrens dsl_dataset_snapshot_sync(ds, resa->tosnap, cr, tx); 1329 5367 ahrens 1330 5367 ahrens /* set snapshot's creation time and guid */ 1331 5367 ahrens dmu_buf_will_dirty(ds->ds_prev->ds_dbuf, tx); 1332 5367 ahrens ds->ds_prev->ds_phys->ds_creation_time = resa->creation_time; 1333 5367 ahrens ds->ds_prev->ds_phys->ds_guid = resa->toguid; 1334 5367 ahrens ds->ds_prev->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT; 1335 5367 ahrens 1336 5367 ahrens dmu_buf_will_dirty(ds->ds_dbuf, tx); 1337 5367 ahrens ds->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT; 1338 5367 ahrens } 1339 5367 ahrens 1340 10272 Matthew static int 1341 10272 Matthew dmu_recv_existing_end(dmu_recv_cookie_t *drc) 1342 5326 ek110237 { 1343 6689 maybee struct recvendsyncarg resa; 1344 6689 maybee dsl_dataset_t *ds = drc->drc_logical_ds; 1345 6689 maybee int err; 1346 5326 ek110237 1347 5367 ahrens /* 1348 10272 Matthew * XXX hack; seems the ds is still dirty and dsl_pool_zil_clean() 1349 10272 Matthew * expects it to have a ds_user_ptr (and zil), but clone_swap() 1350 10272 Matthew * can close it. 1351 5367 ahrens */ 1352 6689 maybee txg_wait_synced(ds->ds_dir->dd_pool, 0); 1353 5326 ek110237 1354 10272 Matthew if (dsl_dataset_tryown(ds, FALSE, dmu_recv_tag)) { 1355 10272 Matthew err = dsl_dataset_clone_swap(drc->drc_real_ds, ds, 1356 10272 Matthew drc->drc_force); 1357 10272 Matthew if (err) 1358 10272 Matthew goto out; 1359 10272 Matthew } else { 1360 10272 Matthew mutex_exit(&ds->ds_recvlock); 1361 10272 Matthew dsl_dataset_rele(ds, dmu_recv_tag); 1362 10242 chris (void) dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag, 1363 10242 chris B_FALSE); 1364 10272 Matthew return (EBUSY); 1365 5367 ahrens } 1366 5367 ahrens 1367 6689 maybee resa.creation_time = drc->drc_drrb->drr_creation_time; 1368 6689 maybee resa.toguid = drc->drc_drrb->drr_toguid; 1369 6689 maybee resa.tosnap = drc->drc_tosnap; 1370 6689 maybee 1371 6689 maybee err = dsl_sync_task_do(ds->ds_dir->dd_pool, 1372 6689 maybee recv_end_check, recv_end_sync, ds, &resa, 3); 1373 6689 maybee if (err) { 1374 10272 Matthew /* swap back */ 1375 10272 Matthew (void) dsl_dataset_clone_swap(drc->drc_real_ds, ds, B_TRUE); 1376 5367 ahrens } 1377 5367 ahrens 1378 10272 Matthew out: 1379 10272 Matthew mutex_exit(&ds->ds_recvlock); 1380 6689 maybee dsl_dataset_disown(ds, dmu_recv_tag); 1381 10272 Matthew (void) dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag, B_FALSE); 1382 5326 ek110237 return (err); 1383 5326 ek110237 } 1384 10272 Matthew 1385 10272 Matthew static int 1386 10272 Matthew dmu_recv_new_end(dmu_recv_cookie_t *drc) 1387 10272 Matthew { 1388 10272 Matthew struct recvendsyncarg resa; 1389 10272 Matthew dsl_dataset_t *ds = drc->drc_logical_ds; 1390 10272 Matthew int err; 1391 10272 Matthew 1392 10272 Matthew /* 1393 10272 Matthew * XXX hack; seems the ds is still dirty and dsl_pool_zil_clean() 1394 10272 Matthew * expects it to have a ds_user_ptr (and zil), but clone_swap() 1395 10272 Matthew * can close it. 1396 10272 Matthew */ 1397 10272 Matthew txg_wait_synced(ds->ds_dir->dd_pool, 0); 1398 10272 Matthew 1399 10272 Matthew resa.creation_time = drc->drc_drrb->drr_creation_time; 1400 10272 Matthew resa.toguid = drc->drc_drrb->drr_toguid; 1401 10272 Matthew resa.tosnap = drc->drc_tosnap; 1402 10272 Matthew 1403 10272 Matthew err = dsl_sync_task_do(ds->ds_dir->dd_pool, 1404 10272 Matthew recv_end_check, recv_end_sync, ds, &resa, 3); 1405 10272 Matthew if (err) { 1406 10272 Matthew /* clean up the fs we just recv'd into */ 1407 10272 Matthew (void) dsl_dataset_destroy(ds, dmu_recv_tag, B_FALSE); 1408 10272 Matthew } else { 1409 10272 Matthew /* release the hold from dmu_recv_begin */ 1410 10272 Matthew dsl_dataset_disown(ds, dmu_recv_tag); 1411 10272 Matthew } 1412 10272 Matthew return (err); 1413 10272 Matthew } 1414 10272 Matthew 1415 10272 Matthew int 1416 10272 Matthew dmu_recv_end(dmu_recv_cookie_t *drc) 1417 10272 Matthew { 1418 10272 Matthew if (drc->drc_logical_ds != drc->drc_real_ds) 1419 10272 Matthew return (dmu_recv_existing_end(drc)); 1420 10272 Matthew else 1421 10272 Matthew return (dmu_recv_new_end(drc)); 1422 10272 Matthew } 1423