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