Deleted Added
full compact
libzfs_sendrecv.c (251417) libzfs_sendrecv.c (252764)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE

--- 11 unchanged lines hidden (view full) ---

20 */
21
22/*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2012 by Delphix. All rights reserved.
25 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
26 * Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
27 * All rights reserved.
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE

--- 11 unchanged lines hidden (view full) ---

20 */
21
22/*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2012 by Delphix. All rights reserved.
25 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
26 * Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
27 * All rights reserved.
28 * Copyright (c) 2013 Steven Hartland. All rights reserved.
28 */
29
30#include <assert.h>
31#include <ctype.h>
32#include <errno.h>
33#include <libintl.h>
34#include <stdio.h>
35#include <stdlib.h>

--- 761 unchanged lines hidden (view full) ---

797 const char *tosnap;
798 char prevsnap[ZFS_MAXNAMELEN];
799 uint64_t prevsnap_obj;
800 boolean_t seenfrom, seento, replicate, doall, fromorigin;
801 boolean_t verbose, dryrun, parsable, progress;
802 int outfd;
803 boolean_t err;
804 nvlist_t *fss;
29 */
30
31#include <assert.h>
32#include <ctype.h>
33#include <errno.h>
34#include <libintl.h>
35#include <stdio.h>
36#include <stdlib.h>

--- 761 unchanged lines hidden (view full) ---

798 const char *tosnap;
799 char prevsnap[ZFS_MAXNAMELEN];
800 uint64_t prevsnap_obj;
801 boolean_t seenfrom, seento, replicate, doall, fromorigin;
802 boolean_t verbose, dryrun, parsable, progress;
803 int outfd;
804 boolean_t err;
805 nvlist_t *fss;
806 nvlist_t *snapholds;
805 avl_tree_t *fsavl;
806 snapfilter_cb_t *filter_cb;
807 void *filter_cb_arg;
808 nvlist_t *debugnv;
809 char holdtag[ZFS_MAXNAMELEN];
810 int cleanup_fd;
811 uint64_t size;
812} send_dump_data_t;

--- 134 unchanged lines hidden (view full) ---

947
948 if (debugnv)
949 VERIFY(0 == nvlist_add_nvlist(debugnv, zhp->zfs_name, thisdbg));
950 nvlist_free(thisdbg);
951
952 return (0);
953}
954
807 avl_tree_t *fsavl;
808 snapfilter_cb_t *filter_cb;
809 void *filter_cb_arg;
810 nvlist_t *debugnv;
811 char holdtag[ZFS_MAXNAMELEN];
812 int cleanup_fd;
813 uint64_t size;
814} send_dump_data_t;

--- 134 unchanged lines hidden (view full) ---

949
950 if (debugnv)
951 VERIFY(0 == nvlist_add_nvlist(debugnv, zhp->zfs_name, thisdbg));
952 nvlist_free(thisdbg);
953
954 return (0);
955}
956
955static int
956hold_for_send(zfs_handle_t *zhp, send_dump_data_t *sdd)
957static void
958gather_holds(zfs_handle_t *zhp, send_dump_data_t *sdd)
957{
959{
958 zfs_handle_t *pzhp;
959 int error = 0;
960 char *thissnap;
961
962 assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
963
960 assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
961
964 if (sdd->dryrun)
965 return (0);
966
967 /*
962 /*
968 * zfs_send() only opens a cleanup_fd for sends that need it,
963 * zfs_send() only sets snapholds for sends that need them,
969 * e.g. replication and doall.
970 */
964 * e.g. replication and doall.
965 */
971 if (sdd->cleanup_fd == -1)
972 return (0);
966 if (sdd->snapholds == NULL)
967 return;
973
968
974 thissnap = strchr(zhp->zfs_name, '@') + 1;
975 *(thissnap - 1) = '\0';
976 pzhp = zfs_open(zhp->zfs_hdl, zhp->zfs_name, ZFS_TYPE_DATASET);
977 *(thissnap - 1) = '@';
978
979 /*
980 * It's OK if the parent no longer exists. The send code will
981 * handle that error.
982 */
983 if (pzhp) {
984 error = zfs_hold(pzhp, thissnap, sdd->holdtag,
985 B_FALSE, B_TRUE, sdd->cleanup_fd);
986 zfs_close(pzhp);
987 }
988
989 return (error);
969 fnvlist_add_string(sdd->snapholds, zhp->zfs_name, sdd->holdtag);
990}
991
992static void *
993send_progress_thread(void *arg)
994{
995 progress_arg_t *pa = arg;
996
997 zfs_cmd_t zc = { 0 };

--- 39 unchanged lines hidden (view full) ---

1037}
1038
1039static int
1040dump_snapshot(zfs_handle_t *zhp, void *arg)
1041{
1042 send_dump_data_t *sdd = arg;
1043 progress_arg_t pa = { 0 };
1044 pthread_t tid;
970}
971
972static void *
973send_progress_thread(void *arg)
974{
975 progress_arg_t *pa = arg;
976
977 zfs_cmd_t zc = { 0 };

--- 39 unchanged lines hidden (view full) ---

1017}
1018
1019static int
1020dump_snapshot(zfs_handle_t *zhp, void *arg)
1021{
1022 send_dump_data_t *sdd = arg;
1023 progress_arg_t pa = { 0 };
1024 pthread_t tid;
1045
1046 char *thissnap;
1047 int err;
1048 boolean_t isfromsnap, istosnap, fromorigin;
1049 boolean_t exclude = B_FALSE;
1050
1025 char *thissnap;
1026 int err;
1027 boolean_t isfromsnap, istosnap, fromorigin;
1028 boolean_t exclude = B_FALSE;
1029
1030 err = 0;
1051 thissnap = strchr(zhp->zfs_name, '@') + 1;
1052 isfromsnap = (sdd->fromsnap != NULL &&
1053 strcmp(sdd->fromsnap, thissnap) == 0);
1054
1055 if (!sdd->seenfrom && isfromsnap) {
1031 thissnap = strchr(zhp->zfs_name, '@') + 1;
1032 isfromsnap = (sdd->fromsnap != NULL &&
1033 strcmp(sdd->fromsnap, thissnap) == 0);
1034
1035 if (!sdd->seenfrom && isfromsnap) {
1056 err = hold_for_send(zhp, sdd);
1057 if (err == 0) {
1058 sdd->seenfrom = B_TRUE;
1059 (void) strcpy(sdd->prevsnap, thissnap);
1060 sdd->prevsnap_obj = zfs_prop_get_int(zhp,
1061 ZFS_PROP_OBJSETID);
1062 } else if (err == ENOENT) {
1063 err = 0;
1064 }
1036 gather_holds(zhp, sdd);
1037 sdd->seenfrom = B_TRUE;
1038 (void) strcpy(sdd->prevsnap, thissnap);
1039 sdd->prevsnap_obj = zfs_prop_get_int(zhp, ZFS_PROP_OBJSETID);
1065 zfs_close(zhp);
1040 zfs_close(zhp);
1066 return (err);
1041 return (0);
1067 }
1068
1069 if (sdd->seento || !sdd->seenfrom) {
1070 zfs_close(zhp);
1071 return (0);
1072 }
1073
1074 istosnap = (strcmp(sdd->tosnap, thissnap) == 0);

--- 34 unchanged lines hidden (view full) ---

1109 * an incremental from the last accepted one, or as the
1110 * first (and full) snapshot in the case of a replication,
1111 * non-incremental send.
1112 */
1113 zfs_close(zhp);
1114 return (0);
1115 }
1116
1042 }
1043
1044 if (sdd->seento || !sdd->seenfrom) {
1045 zfs_close(zhp);
1046 return (0);
1047 }
1048
1049 istosnap = (strcmp(sdd->tosnap, thissnap) == 0);

--- 34 unchanged lines hidden (view full) ---

1084 * an incremental from the last accepted one, or as the
1085 * first (and full) snapshot in the case of a replication,
1086 * non-incremental send.
1087 */
1088 zfs_close(zhp);
1089 return (0);
1090 }
1091
1117 err = hold_for_send(zhp, sdd);
1118 if (err) {
1119 if (err == ENOENT)
1120 err = 0;
1121 zfs_close(zhp);
1122 return (err);
1123 }
1124
1092 gather_holds(zhp, sdd);
1125 fromorigin = sdd->prevsnap[0] == '\0' &&
1126 (sdd->fromorigin || sdd->replicate);
1127
1128 if (sdd->verbose) {
1129 uint64_t size;
1130 err = estimate_ioctl(zhp, sdd->prevsnap_obj,
1131 fromorigin, &size);
1132

--- 251 unchanged lines hidden (view full) ---

1384{
1385 char errbuf[1024];
1386 send_dump_data_t sdd = { 0 };
1387 int err = 0;
1388 nvlist_t *fss = NULL;
1389 avl_tree_t *fsavl = NULL;
1390 static uint64_t holdseq;
1391 int spa_version;
1093 fromorigin = sdd->prevsnap[0] == '\0' &&
1094 (sdd->fromorigin || sdd->replicate);
1095
1096 if (sdd->verbose) {
1097 uint64_t size;
1098 err = estimate_ioctl(zhp, sdd->prevsnap_obj,
1099 fromorigin, &size);
1100

--- 251 unchanged lines hidden (view full) ---

1352{
1353 char errbuf[1024];
1354 send_dump_data_t sdd = { 0 };
1355 int err = 0;
1356 nvlist_t *fss = NULL;
1357 avl_tree_t *fsavl = NULL;
1358 static uint64_t holdseq;
1359 int spa_version;
1392 pthread_t tid;
1360 pthread_t tid = 0;
1393 int pipefd[2];
1394 dedup_arg_t dda = { 0 };
1395 int featureflags = 0;
1396
1397 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1398 "cannot send '%s'"), zhp->zfs_name);
1399
1400 if (fromsnap && fromsnap[0] == '\0') {

--- 56 unchanged lines hidden (view full) ---

1457 goto err_out;
1458 VERIFY(0 == nvlist_add_nvlist(hdrnv, "fss", fss));
1459 err = nvlist_pack(hdrnv, &packbuf, &buflen,
1460 NV_ENCODE_XDR, 0);
1461 if (debugnvp)
1462 *debugnvp = hdrnv;
1463 else
1464 nvlist_free(hdrnv);
1361 int pipefd[2];
1362 dedup_arg_t dda = { 0 };
1363 int featureflags = 0;
1364
1365 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1366 "cannot send '%s'"), zhp->zfs_name);
1367
1368 if (fromsnap && fromsnap[0] == '\0') {

--- 56 unchanged lines hidden (view full) ---

1425 goto err_out;
1426 VERIFY(0 == nvlist_add_nvlist(hdrnv, "fss", fss));
1427 err = nvlist_pack(hdrnv, &packbuf, &buflen,
1428 NV_ENCODE_XDR, 0);
1429 if (debugnvp)
1430 *debugnvp = hdrnv;
1431 else
1432 nvlist_free(hdrnv);
1465 if (err) {
1466 fsavl_destroy(fsavl);
1467 nvlist_free(fss);
1433 if (err)
1468 goto stderr_out;
1434 goto stderr_out;
1469 }
1470 }
1471
1472 if (!flags->dryrun) {
1473 /* write first begin record */
1474 drr.drr_type = DRR_BEGIN;
1475 drr.drr_u.drr_begin.drr_magic = DMU_BACKUP_MAGIC;
1476 DMU_SET_STREAM_HDRTYPE(drr.drr_u.drr_begin.
1477 drr_versioninfo, DMU_COMPOUNDSTREAM);

--- 7 unchanged lines hidden (view full) ---

1485
1486 /* write header nvlist */
1487 if (err != -1 && packbuf != NULL) {
1488 err = cksum_and_write(packbuf, buflen, &zc,
1489 outfd);
1490 }
1491 free(packbuf);
1492 if (err == -1) {
1435 }
1436
1437 if (!flags->dryrun) {
1438 /* write first begin record */
1439 drr.drr_type = DRR_BEGIN;
1440 drr.drr_u.drr_begin.drr_magic = DMU_BACKUP_MAGIC;
1441 DMU_SET_STREAM_HDRTYPE(drr.drr_u.drr_begin.
1442 drr_versioninfo, DMU_COMPOUNDSTREAM);

--- 7 unchanged lines hidden (view full) ---

1450
1451 /* write header nvlist */
1452 if (err != -1 && packbuf != NULL) {
1453 err = cksum_and_write(packbuf, buflen, &zc,
1454 outfd);
1455 }
1456 free(packbuf);
1457 if (err == -1) {
1493 fsavl_destroy(fsavl);
1494 nvlist_free(fss);
1495 err = errno;
1496 goto stderr_out;
1497 }
1498
1499 /* write end record */
1500 bzero(&drr, sizeof (drr));
1501 drr.drr_type = DRR_END;
1502 drr.drr_u.drr_end.drr_checksum = zc;
1503 err = write(outfd, &drr, sizeof (drr));
1504 if (err == -1) {
1458 err = errno;
1459 goto stderr_out;
1460 }
1461
1462 /* write end record */
1463 bzero(&drr, sizeof (drr));
1464 drr.drr_type = DRR_END;
1465 drr.drr_u.drr_end.drr_checksum = zc;
1466 err = write(outfd, &drr, sizeof (drr));
1467 if (err == -1) {
1505 fsavl_destroy(fsavl);
1506 nvlist_free(fss);
1507 err = errno;
1508 goto stderr_out;
1509 }
1510
1511 err = 0;
1512 }
1513 }
1514
1515 /* dump each stream */
1516 sdd.fromsnap = fromsnap;
1517 sdd.tosnap = tosnap;
1468 err = errno;
1469 goto stderr_out;
1470 }
1471
1472 err = 0;
1473 }
1474 }
1475
1476 /* dump each stream */
1477 sdd.fromsnap = fromsnap;
1478 sdd.tosnap = tosnap;
1518 if (flags->dedup)
1479 if (tid != 0)
1519 sdd.outfd = pipefd[0];
1520 else
1521 sdd.outfd = outfd;
1522 sdd.replicate = flags->replicate;
1523 sdd.doall = flags->doall;
1524 sdd.fromorigin = flags->fromorigin;
1525 sdd.fss = fss;
1526 sdd.fsavl = fsavl;

--- 20 unchanged lines hidden (view full) ---

1547 ++holdseq;
1548 (void) snprintf(sdd.holdtag, sizeof (sdd.holdtag),
1549 ".send-%d-%llu", getpid(), (u_longlong_t)holdseq);
1550 sdd.cleanup_fd = open(ZFS_DEV, O_RDWR|O_EXCL);
1551 if (sdd.cleanup_fd < 0) {
1552 err = errno;
1553 goto stderr_out;
1554 }
1480 sdd.outfd = pipefd[0];
1481 else
1482 sdd.outfd = outfd;
1483 sdd.replicate = flags->replicate;
1484 sdd.doall = flags->doall;
1485 sdd.fromorigin = flags->fromorigin;
1486 sdd.fss = fss;
1487 sdd.fsavl = fsavl;

--- 20 unchanged lines hidden (view full) ---

1508 ++holdseq;
1509 (void) snprintf(sdd.holdtag, sizeof (sdd.holdtag),
1510 ".send-%d-%llu", getpid(), (u_longlong_t)holdseq);
1511 sdd.cleanup_fd = open(ZFS_DEV, O_RDWR|O_EXCL);
1512 if (sdd.cleanup_fd < 0) {
1513 err = errno;
1514 goto stderr_out;
1515 }
1516 sdd.snapholds = fnvlist_alloc();
1555 } else {
1556 sdd.cleanup_fd = -1;
1517 } else {
1518 sdd.cleanup_fd = -1;
1519 sdd.snapholds = NULL;
1557 }
1520 }
1558 if (flags->verbose) {
1521 if (flags->verbose || sdd.snapholds != NULL) {
1559 /*
1560 * Do a verbose no-op dry run to get all the verbose output
1522 /*
1523 * Do a verbose no-op dry run to get all the verbose output
1561 * before generating any data. Then do a non-verbose real
1562 * run to generate the streams.
1524 * or to gather snapshot hold's before generating any data,
1525 * then do a non-verbose real run to generate the streams.
1563 */
1564 sdd.dryrun = B_TRUE;
1565 err = dump_filesystems(zhp, &sdd);
1526 */
1527 sdd.dryrun = B_TRUE;
1528 err = dump_filesystems(zhp, &sdd);
1566 sdd.dryrun = flags->dryrun;
1567 sdd.verbose = B_FALSE;
1568 if (flags->parsable) {
1569 (void) fprintf(stderr, "size\t%llu\n",
1570 (longlong_t)sdd.size);
1571 } else {
1572 char buf[16];
1573 zfs_nicenum(sdd.size, buf, sizeof (buf));
1574 (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
1575 "total estimated size is %s\n"), buf);
1529
1530 if (err != 0)
1531 goto stderr_out;
1532
1533 if (flags->verbose) {
1534 if (flags->parsable) {
1535 (void) fprintf(stderr, "size\t%llu\n",
1536 (longlong_t)sdd.size);
1537 } else {
1538 char buf[16];
1539 zfs_nicenum(sdd.size, buf, sizeof (buf));
1540 (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
1541 "total estimated size is %s\n"), buf);
1542 }
1576 }
1543 }
1544
1545 /* Ensure no snaps found is treated as an error. */
1546 if (!sdd.seento) {
1547 err = ENOENT;
1548 goto err_out;
1549 }
1550
1551 /* Skip the second run if dryrun was requested. */
1552 if (flags->dryrun)
1553 goto err_out;
1554
1555 if (sdd.snapholds != NULL) {
1556 err = zfs_hold_nvl(zhp, sdd.cleanup_fd, sdd.snapholds);
1557 if (err != 0)
1558 goto stderr_out;
1559
1560 fnvlist_free(sdd.snapholds);
1561 sdd.snapholds = NULL;
1562 }
1563
1564 sdd.dryrun = B_FALSE;
1565 sdd.verbose = B_FALSE;
1577 }
1566 }
1567
1578 err = dump_filesystems(zhp, &sdd);
1579 fsavl_destroy(fsavl);
1580 nvlist_free(fss);
1581
1568 err = dump_filesystems(zhp, &sdd);
1569 fsavl_destroy(fsavl);
1570 nvlist_free(fss);
1571
1582 if (flags->dedup) {
1583 (void) close(pipefd[0]);
1572 /* Ensure no snaps found is treated as an error. */
1573 if (err == 0 && !sdd.seento)
1574 err = ENOENT;
1575
1576 if (tid != 0) {
1577 if (err != 0)
1578 (void) pthread_cancel(tid);
1584 (void) pthread_join(tid, NULL);
1579 (void) pthread_join(tid, NULL);
1580 (void) close(pipefd[0]);
1585 }
1586
1587 if (sdd.cleanup_fd != -1) {
1588 VERIFY(0 == close(sdd.cleanup_fd));
1589 sdd.cleanup_fd = -1;
1590 }
1591
1592 if (!flags->dryrun && (flags->replicate || flags->doall ||

--- 11 unchanged lines hidden (view full) ---

1604 }
1605 }
1606
1607 return (err || sdd.err);
1608
1609stderr_out:
1610 err = zfs_standard_error(zhp->zfs_hdl, err, errbuf);
1611err_out:
1581 }
1582
1583 if (sdd.cleanup_fd != -1) {
1584 VERIFY(0 == close(sdd.cleanup_fd));
1585 sdd.cleanup_fd = -1;
1586 }
1587
1588 if (!flags->dryrun && (flags->replicate || flags->doall ||

--- 11 unchanged lines hidden (view full) ---

1600 }
1601 }
1602
1603 return (err || sdd.err);
1604
1605stderr_out:
1606 err = zfs_standard_error(zhp->zfs_hdl, err, errbuf);
1607err_out:
1608 fsavl_destroy(fsavl);
1609 nvlist_free(fss);
1610 fnvlist_free(sdd.snapholds);
1611
1612 if (sdd.cleanup_fd != -1)
1613 VERIFY(0 == close(sdd.cleanup_fd));
1612 if (sdd.cleanup_fd != -1)
1613 VERIFY(0 == close(sdd.cleanup_fd));
1614 if (flags->dedup) {
1614 if (tid != 0) {
1615 (void) pthread_cancel(tid);
1616 (void) pthread_join(tid, NULL);
1617 (void) close(pipefd[0]);
1618 }
1619 return (err);
1620}
1621
1622/*

--- 1619 unchanged lines hidden ---
1615 (void) pthread_cancel(tid);
1616 (void) pthread_join(tid, NULL);
1617 (void) close(pipefd[0]);
1618 }
1619 return (err);
1620}
1621
1622/*

--- 1619 unchanged lines hidden ---