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