Deleted Added
full compact
dmu_send.c (219089) dmu_send.c (221263)
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

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

16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
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

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

16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24/*
25 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
26 */
24
25#include <sys/dmu.h>
26#include <sys/dmu_impl.h>
27#include <sys/dmu_tx.h>
28#include <sys/dbuf.h>
29#include <sys/dnode.h>
30#include <sys/zfs_context.h>
31#include <sys/dmu_objset.h>

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

846
847 if (gmep1->guid < gmep2->guid)
848 return (-1);
849 else if (gmep1->guid > gmep2->guid)
850 return (1);
851 return (0);
852}
853
27
28#include <sys/dmu.h>
29#include <sys/dmu_impl.h>
30#include <sys/dmu_tx.h>
31#include <sys/dbuf.h>
32#include <sys/dnode.h>
33#include <sys/zfs_context.h>
34#include <sys/dmu_objset.h>

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

849
850 if (gmep1->guid < gmep2->guid)
851 return (-1);
852 else if (gmep1->guid > gmep2->guid)
853 return (1);
854 return (0);
855}
856
854/*
855 * This function is a callback used by dmu_objset_find() (which
856 * enumerates the object sets) to build an avl tree that maps guids
857 * to datasets. The resulting table is used when processing DRR_WRITE_BYREF
858 * send stream records. These records, which are used in dedup'ed
859 * streams, do not contain data themselves, but refer to a copy
860 * of the data block that has already been written because it was
861 * earlier in the stream. That previous copy is identified by the
862 * guid of the dataset with the referenced data.
863 */
864int
865find_ds_by_guid(const char *name, void *arg)
866{
867 avl_tree_t *guid_map = arg;
868 dsl_dataset_t *ds, *snapds;
869 guid_map_entry_t *gmep;
870 dsl_pool_t *dp;
871 int err;
872 uint64_t lastobj, firstobj;
873
874 if (dsl_dataset_hold(name, FTAG, &ds) != 0)
875 return (0);
876
877 dp = ds->ds_dir->dd_pool;
878 rw_enter(&dp->dp_config_rwlock, RW_READER);
879 firstobj = ds->ds_dir->dd_phys->dd_origin_obj;
880 lastobj = ds->ds_phys->ds_prev_snap_obj;
881
882 while (lastobj != firstobj) {
883 err = dsl_dataset_hold_obj(dp, lastobj, guid_map, &snapds);
884 if (err) {
885 /*
886 * Skip this snapshot and move on. It's not
887 * clear why this would ever happen, but the
888 * remainder of the snapshot streadm can be
889 * processed.
890 */
891 rw_exit(&dp->dp_config_rwlock);
892 dsl_dataset_rele(ds, FTAG);
893 return (0);
894 }
895
896 gmep = kmem_alloc(sizeof (guid_map_entry_t), KM_SLEEP);
897 gmep->guid = snapds->ds_phys->ds_guid;
898 gmep->gme_ds = snapds;
899 avl_add(guid_map, gmep);
900 lastobj = snapds->ds_phys->ds_prev_snap_obj;
901 }
902
903 rw_exit(&dp->dp_config_rwlock);
904 dsl_dataset_rele(ds, FTAG);
905
906 return (0);
907}
908
909static void
910free_guid_map_onexit(void *arg)
911{
912 avl_tree_t *ca = arg;
913 void *cookie = NULL;
914 guid_map_entry_t *gmep;
915
916 while ((gmep = avl_destroy_nodes(ca, &cookie)) != NULL) {

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

1408 }
1409
1410 if (*action_handlep == 0) {
1411 ra.guid_to_ds_map =
1412 kmem_alloc(sizeof (avl_tree_t), KM_SLEEP);
1413 avl_create(ra.guid_to_ds_map, guid_compare,
1414 sizeof (guid_map_entry_t),
1415 offsetof(guid_map_entry_t, avlnode));
857static void
858free_guid_map_onexit(void *arg)
859{
860 avl_tree_t *ca = arg;
861 void *cookie = NULL;
862 guid_map_entry_t *gmep;
863
864 while ((gmep = avl_destroy_nodes(ca, &cookie)) != NULL) {

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

1356 }
1357
1358 if (*action_handlep == 0) {
1359 ra.guid_to_ds_map =
1360 kmem_alloc(sizeof (avl_tree_t), KM_SLEEP);
1361 avl_create(ra.guid_to_ds_map, guid_compare,
1362 sizeof (guid_map_entry_t),
1363 offsetof(guid_map_entry_t, avlnode));
1416 (void) dmu_objset_find(drc->drc_top_ds, find_ds_by_guid,
1417 (void *)ra.guid_to_ds_map,
1418 DS_FIND_CHILDREN);
1419 ra.err = zfs_onexit_add_cb(minor,
1420 free_guid_map_onexit, ra.guid_to_ds_map,
1421 action_handlep);
1422 if (ra.err)
1423 goto out;
1424 } else {
1425 ra.err = zfs_onexit_cb_data(minor, *action_handlep,
1426 (void **)&ra.guid_to_ds_map);
1427 if (ra.err)
1428 goto out;
1429 }
1364 ra.err = zfs_onexit_add_cb(minor,
1365 free_guid_map_onexit, ra.guid_to_ds_map,
1366 action_handlep);
1367 if (ra.err)
1368 goto out;
1369 } else {
1370 ra.err = zfs_onexit_cb_data(minor, *action_handlep,
1371 (void **)&ra.guid_to_ds_map);
1372 if (ra.err)
1373 goto out;
1374 }
1375
1376 drc->drc_guid_to_ds_map = ra.guid_to_ds_map;
1430 }
1431
1432 /*
1433 * Read records and process them.
1434 */
1435 pcksum = ra.cksum;
1436 while (ra.err == 0 &&
1437 NULL != (drr = restore_read(&ra, sizeof (*drr)))) {

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

1560 ds->ds_prev->ds_phys->ds_guid = resa->toguid;
1561 ds->ds_prev->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT;
1562
1563 dmu_buf_will_dirty(ds->ds_dbuf, tx);
1564 ds->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT;
1565}
1566
1567static int
1377 }
1378
1379 /*
1380 * Read records and process them.
1381 */
1382 pcksum = ra.cksum;
1383 while (ra.err == 0 &&
1384 NULL != (drr = restore_read(&ra, sizeof (*drr)))) {

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

1507 ds->ds_prev->ds_phys->ds_guid = resa->toguid;
1508 ds->ds_prev->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT;
1509
1510 dmu_buf_will_dirty(ds->ds_dbuf, tx);
1511 ds->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT;
1512}
1513
1514static int
1515add_ds_to_guidmap(avl_tree_t *guid_map, dsl_dataset_t *ds)
1516{
1517 dsl_pool_t *dp = ds->ds_dir->dd_pool;
1518 uint64_t snapobj = ds->ds_phys->ds_prev_snap_obj;
1519 dsl_dataset_t *snapds;
1520 guid_map_entry_t *gmep;
1521 int err;
1522
1523 ASSERT(guid_map != NULL);
1524
1525 rw_enter(&dp->dp_config_rwlock, RW_READER);
1526 err = dsl_dataset_hold_obj(dp, snapobj, guid_map, &snapds);
1527 if (err == 0) {
1528 gmep = kmem_alloc(sizeof (guid_map_entry_t), KM_SLEEP);
1529 gmep->guid = snapds->ds_phys->ds_guid;
1530 gmep->gme_ds = snapds;
1531 avl_add(guid_map, gmep);
1532 }
1533
1534 rw_exit(&dp->dp_config_rwlock);
1535 return (err);
1536}
1537
1538static int
1568dmu_recv_existing_end(dmu_recv_cookie_t *drc)
1569{
1570 struct recvendsyncarg resa;
1571 dsl_dataset_t *ds = drc->drc_logical_ds;
1572 int err;
1573
1574 /*
1575 * XXX hack; seems the ds is still dirty and dsl_pool_zil_clean()

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

1599 recv_end_check, recv_end_sync, ds, &resa, 3);
1600 if (err) {
1601 /* swap back */
1602 (void) dsl_dataset_clone_swap(drc->drc_real_ds, ds, B_TRUE);
1603 }
1604
1605out:
1606 mutex_exit(&ds->ds_recvlock);
1539dmu_recv_existing_end(dmu_recv_cookie_t *drc)
1540{
1541 struct recvendsyncarg resa;
1542 dsl_dataset_t *ds = drc->drc_logical_ds;
1543 int err;
1544
1545 /*
1546 * XXX hack; seems the ds is still dirty and dsl_pool_zil_clean()

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

1570 recv_end_check, recv_end_sync, ds, &resa, 3);
1571 if (err) {
1572 /* swap back */
1573 (void) dsl_dataset_clone_swap(drc->drc_real_ds, ds, B_TRUE);
1574 }
1575
1576out:
1577 mutex_exit(&ds->ds_recvlock);
1578 if (err == 0 && drc->drc_guid_to_ds_map != NULL)
1579 (void) add_ds_to_guidmap(drc->drc_guid_to_ds_map, ds);
1607 dsl_dataset_disown(ds, dmu_recv_tag);
1608 (void) dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag, B_FALSE);
1609 return (err);
1610}
1611
1612static int
1613dmu_recv_new_end(dmu_recv_cookie_t *drc)
1614{

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

1628 resa.tosnap = drc->drc_tosnap;
1629
1630 err = dsl_sync_task_do(ds->ds_dir->dd_pool,
1631 recv_end_check, recv_end_sync, ds, &resa, 3);
1632 if (err) {
1633 /* clean up the fs we just recv'd into */
1634 (void) dsl_dataset_destroy(ds, dmu_recv_tag, B_FALSE);
1635 } else {
1580 dsl_dataset_disown(ds, dmu_recv_tag);
1581 (void) dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag, B_FALSE);
1582 return (err);
1583}
1584
1585static int
1586dmu_recv_new_end(dmu_recv_cookie_t *drc)
1587{

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

1601 resa.tosnap = drc->drc_tosnap;
1602
1603 err = dsl_sync_task_do(ds->ds_dir->dd_pool,
1604 recv_end_check, recv_end_sync, ds, &resa, 3);
1605 if (err) {
1606 /* clean up the fs we just recv'd into */
1607 (void) dsl_dataset_destroy(ds, dmu_recv_tag, B_FALSE);
1608 } else {
1609 if (drc->drc_guid_to_ds_map != NULL)
1610 (void) add_ds_to_guidmap(drc->drc_guid_to_ds_map, ds);
1636 /* release the hold from dmu_recv_begin */
1637 dsl_dataset_disown(ds, dmu_recv_tag);
1638 }
1639 return (err);
1640}
1641
1642int
1643dmu_recv_end(dmu_recv_cookie_t *drc)
1644{
1645 if (drc->drc_logical_ds != drc->drc_real_ds)
1646 return (dmu_recv_existing_end(drc));
1647 else
1648 return (dmu_recv_new_end(drc));
1649}
1611 /* release the hold from dmu_recv_begin */
1612 dsl_dataset_disown(ds, dmu_recv_tag);
1613 }
1614 return (err);
1615}
1616
1617int
1618dmu_recv_end(dmu_recv_cookie_t *drc)
1619{
1620 if (drc->drc_logical_ds != drc->drc_real_ds)
1621 return (dmu_recv_existing_end(drc));
1622 else
1623 return (dmu_recv_new_end(drc));
1624}