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 { |