Print this page
*** NO COMMENTS ***

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/zfs/dmu_send.c
          +++ new/usr/src/uts/common/fs/zfs/dmu_send.c
↓ open down ↓ 842 lines elided ↑ open up ↑
 843  843                          return (ENOTSUP);
 844  844                  }
 845  845                  /* target fs already exists; recv into temp clone */
 846  846  
 847  847                  /* Can't recv a clone into an existing fs */
 848  848                  if (flags & DRR_FLAG_CLONE) {
 849  849                          dsl_dataset_rele(ds, dmu_recv_tag);
 850  850                          return (EINVAL);
 851  851                  }
 852  852  
 853      -                /* must not have an incremental recv already in progress */
 854      -                if (!mutex_tryenter(&ds->ds_recvlock)) {
 855      -                        dsl_dataset_rele(ds, dmu_recv_tag);
 856      -                        return (EBUSY);
 857      -                }
 858      -
 859  853                  /* tmp clone name is: tofs/%tosnap" */
 860  854                  (void) snprintf(rbsa.clonelastname, sizeof (rbsa.clonelastname),
 861  855                      "%%%s", tosnap);
 862  856                  rbsa.force = force;
 863  857                  err = dsl_sync_task_do(ds->ds_dir->dd_pool,
 864  858                      recv_existing_check, recv_existing_sync, ds, &rbsa, 5);
 865  859                  if (err) {
 866      -                        mutex_exit(&ds->ds_recvlock);
 867  860                          dsl_dataset_rele(ds, dmu_recv_tag);
 868  861                          return (err);
 869  862                  }
 870      -                drc->drc_logical_ds = ds;
      863 +                drc->drc_logical_dsobj = ds->ds_object;
 871  864                  drc->drc_real_ds = rbsa.ds;
      865 +                dsl_dataset_rele(ds, dmu_recv_tag);
 872  866          } else if (err == ENOENT) {
 873  867                  /* target fs does not exist; must be a full backup or clone */
 874  868                  char *cp;
 875  869  
 876  870                  /*
 877  871                   * If it's a non-clone incremental, we are missing the
 878  872                   * target fs, so fail the recv.
 879  873                   */
 880  874                  if (rbsa.fromguid && !(flags & DRR_FLAG_CLONE))
 881  875                          return (ENOENT);
↓ open down ↓ 9 lines elided ↑ open up ↑
 891  885                  if (dmu_recv_verify_features(ds, drrb)) {
 892  886                          dsl_dataset_rele(ds, FTAG);
 893  887                          return (ENOTSUP);
 894  888                  }
 895  889  
 896  890                  err = dsl_sync_task_do(ds->ds_dir->dd_pool,
 897  891                      recv_new_check, recv_new_sync, ds->ds_dir, &rbsa, 5);
 898  892                  dsl_dataset_rele(ds, FTAG);
 899  893                  if (err)
 900  894                          return (err);
 901      -                drc->drc_logical_ds = drc->drc_real_ds = rbsa.ds;
      895 +                drc->drc_real_ds = rbsa.ds;
 902  896                  drc->drc_newfs = B_TRUE;
 903  897          }
 904  898  
 905  899          return (err);
 906  900  }
 907  901  
 908  902  struct restorearg {
 909  903          int err;
 910  904          int byteswap;
 911  905          vnode_t *vp;
↓ open down ↓ 609 lines elided ↑ open up ↑
1521 1515  
1522 1516          if (ra.err != 0) {
1523 1517                  /*
1524 1518                   * destroy what we created, so we don't leave it in the
1525 1519                   * inconsistent restoring state.
1526 1520                   */
1527 1521                  txg_wait_synced(drc->drc_real_ds->ds_dir->dd_pool, 0);
1528 1522  
1529 1523                  (void) dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag,
1530 1524                      B_FALSE);
1531      -                if (drc->drc_real_ds != drc->drc_logical_ds) {
1532      -                        mutex_exit(&drc->drc_logical_ds->ds_recvlock);
1533      -                        dsl_dataset_rele(drc->drc_logical_ds, dmu_recv_tag);
1534      -                }
1535 1525          }
1536 1526  
1537 1527          kmem_free(ra.buf, ra.bufsize);
1538 1528          *voffp = ra.voff;
1539 1529          return (ra.err);
1540 1530  }
1541 1531  
1542 1532  struct recvendsyncarg {
1543 1533          char *tosnap;
1544 1534          uint64_t creation_time;
↓ open down ↓ 48 lines elided ↑ open up ↑
1593 1583          }
1594 1584  
1595 1585          rw_exit(&dp->dp_config_rwlock);
1596 1586          return (err);
1597 1587  }
1598 1588  
1599 1589  static int
1600 1590  dmu_recv_existing_end(dmu_recv_cookie_t *drc)
1601 1591  {
1602 1592          struct recvendsyncarg resa;
1603      -        dsl_dataset_t *ds = drc->drc_logical_ds;
     1593 +        dsl_dataset_t *ds;
1604 1594          int err, myerr;
     1595 +        dsl_pool_t *dp = drc->drc_real_ds->ds_dir->dd_pool;
     1596 +
     1597 +        rw_enter(&dp->dp_config_rwlock, RW_READER);
     1598 +        err = dsl_dataset_own_obj(dp, drc->drc_logical_dsobj, FALSE,
     1599 +            dmu_recv_tag, &ds);
     1600 +        rw_exit(&dp->dp_config_rwlock);
     1601 +
     1602 +        if (err) {
     1603 +                (void) dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag,
     1604 +                    B_FALSE);
     1605 +                return (EBUSY);
     1606 +        }
1605 1607  
1606 1608          /*
1607 1609           * XXX hack; seems the ds is still dirty and dsl_pool_zil_clean()
1608 1610           * expects it to have a ds_user_ptr (and zil), but clone_swap()
1609 1611           * can close it.
1610 1612           */
1611 1613          txg_wait_synced(ds->ds_dir->dd_pool, 0);
1612 1614  
1613      -        if (dsl_dataset_tryown(ds, FALSE, dmu_recv_tag)) {
1614      -                err = dsl_dataset_clone_swap(drc->drc_real_ds, ds,
1615      -                    drc->drc_force);
1616      -                if (err)
1617      -                        goto out;
1618      -        } else {
1619      -                mutex_exit(&ds->ds_recvlock);
1620      -                dsl_dataset_rele(ds, dmu_recv_tag);
1621      -                (void) dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag,
1622      -                    B_FALSE);
1623      -                return (EBUSY);
1624      -        }
     1615 +        err = dsl_dataset_clone_swap(drc->drc_real_ds, ds, drc->drc_force);
     1616 +        if (err)
     1617 +                goto out;
1625 1618  
1626 1619          resa.creation_time = drc->drc_drrb->drr_creation_time;
1627 1620          resa.toguid = drc->drc_drrb->drr_toguid;
1628 1621          resa.tosnap = drc->drc_tosnap;
1629 1622  
1630 1623          err = dsl_sync_task_do(ds->ds_dir->dd_pool,
1631 1624              recv_end_check, recv_end_sync, ds, &resa, 3);
1632 1625          if (err) {
1633 1626                  /* swap back */
1634 1627                  (void) dsl_dataset_clone_swap(drc->drc_real_ds, ds, B_TRUE);
1635 1628          }
1636 1629  
1637 1630  out:
1638      -        mutex_exit(&ds->ds_recvlock);
1639 1631          if (err == 0 && drc->drc_guid_to_ds_map != NULL)
1640 1632                  (void) add_ds_to_guidmap(drc->drc_guid_to_ds_map, ds);
1641 1633          dsl_dataset_disown(ds, dmu_recv_tag);
1642 1634          myerr = dsl_dataset_destroy(drc->drc_real_ds, dmu_recv_tag, B_FALSE);
1643 1635          ASSERT3U(myerr, ==, 0);
1644 1636          return (err);
1645 1637  }
1646 1638  
1647 1639  static int
1648 1640  dmu_recv_new_end(dmu_recv_cookie_t *drc)
1649 1641  {
1650 1642          struct recvendsyncarg resa;
1651      -        dsl_dataset_t *ds = drc->drc_logical_ds;
     1643 +        dsl_dataset_t *ds = drc->drc_real_ds;
1652 1644          int err;
1653 1645  
1654 1646          /*
1655 1647           * XXX hack; seems the ds is still dirty and dsl_pool_zil_clean()
1656 1648           * expects it to have a ds_user_ptr (and zil), but clone_swap()
1657 1649           * can close it.
1658 1650           */
1659 1651          txg_wait_synced(ds->ds_dir->dd_pool, 0);
1660 1652  
1661 1653          resa.creation_time = drc->drc_drrb->drr_creation_time;
↓ open down ↓ 10 lines elided ↑ open up ↑
1672 1664                          (void) add_ds_to_guidmap(drc->drc_guid_to_ds_map, ds);
1673 1665                  /* release the hold from dmu_recv_begin */
1674 1666                  dsl_dataset_disown(ds, dmu_recv_tag);
1675 1667          }
1676 1668          return (err);
1677 1669  }
1678 1670  
1679 1671  int
1680 1672  dmu_recv_end(dmu_recv_cookie_t *drc)
1681 1673  {
1682      -        if (drc->drc_logical_ds != drc->drc_real_ds)
     1674 +        if (!drc->drc_newfs)
1683 1675                  return (dmu_recv_existing_end(drc));
1684 1676          else
1685 1677                  return (dmu_recv_new_end(drc));
1686 1678  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX