usr/src/uts/common/fs/zfs/dmu_send.c
changeset 13512 060607df0c9d
parent 13509 04570f5cbeca
child 13524 f0e12b33f77c
equal deleted inserted replaced
13511:0e6c45a1423b 13512:060607df0c9d
    21 /*
    21 /*
    22  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
    22  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
    23  */
    23  */
    24 /*
    24 /*
    25  * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
    25  * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
    26  * Copyright (c) 2011 by Delphix. All rights reserved.
       
    27  */
    26  */
    28 
    27 
    29 #include <sys/dmu.h>
    28 #include <sys/dmu.h>
    30 #include <sys/dmu_impl.h>
    29 #include <sys/dmu_impl.h>
    31 #include <sys/dmu_tx.h>
    30 #include <sys/dmu_tx.h>
    45 #include <sys/zfs_znode.h>
    44 #include <sys/zfs_znode.h>
    46 #include <zfs_fletcher.h>
    45 #include <zfs_fletcher.h>
    47 #include <sys/avl.h>
    46 #include <sys/avl.h>
    48 #include <sys/ddt.h>
    47 #include <sys/ddt.h>
    49 #include <sys/zfs_onexit.h>
    48 #include <sys/zfs_onexit.h>
    50 
       
    51 /* Set this tunable to TRUE to replace corrupt data with 0x2f5baddb10c */
       
    52 int zfs_send_corrupt_data = B_FALSE;
       
    53 
    49 
    54 static char *dmu_recv_tag = "dmu_recv_tag";
    50 static char *dmu_recv_tag = "dmu_recv_tag";
    55 
    51 
    56 /*
    52 /*
    57  * The list of data whose inclusion in a send stream can be pending from
    53  * The list of data whose inclusion in a send stream can be pending from
   370 		arc_buf_t *abuf;
   366 		arc_buf_t *abuf;
   371 		int blksz = BP_GET_LSIZE(bp);
   367 		int blksz = BP_GET_LSIZE(bp);
   372 
   368 
   373 		if (dsl_read(NULL, spa, bp, pbuf,
   369 		if (dsl_read(NULL, spa, bp, pbuf,
   374 		    arc_getbuf_func, &abuf, ZIO_PRIORITY_ASYNC_READ,
   370 		    arc_getbuf_func, &abuf, ZIO_PRIORITY_ASYNC_READ,
   375 		    ZIO_FLAG_CANFAIL, &aflags, zb) != 0) {
   371 		    ZIO_FLAG_CANFAIL, &aflags, zb) != 0)
   376 			if (zfs_send_corrupt_data) {
   372 			return (EIO);
   377 				/* Send a block filled with 0x"zfs badd bloc" */
       
   378 				abuf = arc_buf_alloc(spa, blksz, &abuf,
       
   379 				    ARC_BUFC_DATA);
       
   380 				uint64_t *ptr;
       
   381 				for (ptr = abuf->b_data;
       
   382 				    (char *)ptr < (char *)abuf->b_data + blksz;
       
   383 				    ptr++)
       
   384 					*ptr = 0x2f5baddb10c;
       
   385 			} else {
       
   386 				return (EIO);
       
   387 			}
       
   388 		}
       
   389 
   373 
   390 		err = dump_data(ba, type, zb->zb_object, zb->zb_blkid * blksz,
   374 		err = dump_data(ba, type, zb->zb_object, zb->zb_blkid * blksz,
   391 		    blksz, bp, abuf->b_data);
   375 		    blksz, bp, abuf->b_data);
   392 		(void) arc_buf_remove_ref(abuf, &abuf);
   376 		(void) arc_buf_remove_ref(abuf, &abuf);
   393 	}
   377 	}
   508 		kmem_free(drr, sizeof (dmu_replay_record_t));
   492 		kmem_free(drr, sizeof (dmu_replay_record_t));
   509 		return (ba.err);
   493 		return (ba.err);
   510 	}
   494 	}
   511 
   495 
   512 	kmem_free(drr, sizeof (dmu_replay_record_t));
   496 	kmem_free(drr, sizeof (dmu_replay_record_t));
   513 
       
   514 	return (0);
       
   515 }
       
   516 
       
   517 int
       
   518 dmu_send_estimate(objset_t *tosnap, objset_t *fromsnap, boolean_t fromorigin,
       
   519     uint64_t *sizep)
       
   520 {
       
   521 	dsl_dataset_t *ds = tosnap->os_dsl_dataset;
       
   522 	dsl_dataset_t *fromds = fromsnap ? fromsnap->os_dsl_dataset : NULL;
       
   523 	dsl_pool_t *dp = ds->ds_dir->dd_pool;
       
   524 	int err;
       
   525 	uint64_t size;
       
   526 
       
   527 	/* tosnap must be a snapshot */
       
   528 	if (ds->ds_phys->ds_next_snap_obj == 0)
       
   529 		return (EINVAL);
       
   530 
       
   531 	/* fromsnap must be an earlier snapshot from the same fs as tosnap */
       
   532 	if (fromds && (ds->ds_dir != fromds->ds_dir ||
       
   533 	    fromds->ds_phys->ds_creation_txg >= ds->ds_phys->ds_creation_txg))
       
   534 		return (EXDEV);
       
   535 
       
   536 	if (fromorigin) {
       
   537 		if (fromsnap)
       
   538 			return (EINVAL);
       
   539 
       
   540 		if (dsl_dir_is_clone(ds->ds_dir)) {
       
   541 			rw_enter(&dp->dp_config_rwlock, RW_READER);
       
   542 			err = dsl_dataset_hold_obj(dp,
       
   543 			    ds->ds_dir->dd_phys->dd_origin_obj, FTAG, &fromds);
       
   544 			rw_exit(&dp->dp_config_rwlock);
       
   545 			if (err)
       
   546 				return (err);
       
   547 		} else {
       
   548 			fromorigin = B_FALSE;
       
   549 		}
       
   550 	}
       
   551 
       
   552 	/* Get uncompressed size estimate of changed data. */
       
   553 	if (fromds == NULL) {
       
   554 		size = ds->ds_phys->ds_uncompressed_bytes;
       
   555 	} else {
       
   556 		uint64_t used, comp;
       
   557 		err = dsl_dataset_space_written(fromds, ds,
       
   558 		    &used, &comp, &size);
       
   559 		if (fromorigin)
       
   560 			dsl_dataset_rele(fromds, FTAG);
       
   561 		if (err)
       
   562 			return (err);
       
   563 	}
       
   564 
       
   565 	/*
       
   566 	 * Assume that space (both on-disk and in-stream) is dominated by
       
   567 	 * data.  We will adjust for indirect blocks and the copies property,
       
   568 	 * but ignore per-object space used (eg, dnodes and DRR_OBJECT records).
       
   569 	 */
       
   570 
       
   571 	/*
       
   572 	 * Subtract out approximate space used by indirect blocks.
       
   573 	 * Assume most space is used by data blocks (non-indirect, non-dnode).
       
   574 	 * Assume all blocks are recordsize.  Assume ditto blocks and
       
   575 	 * internal fragmentation counter out compression.
       
   576 	 *
       
   577 	 * Therefore, space used by indirect blocks is sizeof(blkptr_t) per
       
   578 	 * block, which we observe in practice.
       
   579 	 */
       
   580 	uint64_t recordsize;
       
   581 	rw_enter(&dp->dp_config_rwlock, RW_READER);
       
   582 	err = dsl_prop_get_ds(ds, "recordsize",
       
   583 	    sizeof (recordsize), 1, &recordsize, NULL);
       
   584 	rw_exit(&dp->dp_config_rwlock);
       
   585 	if (err)
       
   586 		return (err);
       
   587 	size -= size / recordsize * sizeof (blkptr_t);
       
   588 
       
   589 	/* Add in the space for the record associated with each block. */
       
   590 	size += size / recordsize * sizeof (dmu_replay_record_t);
       
   591 
       
   592 	*sizep = size;
       
   593 
   497 
   594 	return (0);
   498 	return (0);
   595 }
   499 }
   596 
   500 
   597 struct recvbeginsyncarg {
   501 struct recvbeginsyncarg {