dsl_dataset.c (5094:71a3e95fb9e2) dsl_dataset.c (5326:6752aa2bd5bc)
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

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

1530 uint64_t *usedobjsp, uint64_t *availobjsp)
1531{
1532 *refdbytesp = ds->ds_phys->ds_used_bytes;
1533 *availbytesp = dsl_dir_space_available(ds->ds_dir, NULL, 0, TRUE);
1534 *usedobjsp = ds->ds_phys->ds_bp.blk_fill;
1535 *availobjsp = DN_MAX_OBJECT - *usedobjsp;
1536}
1537
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

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

1530 uint64_t *usedobjsp, uint64_t *availobjsp)
1531{
1532 *refdbytesp = ds->ds_phys->ds_used_bytes;
1533 *availbytesp = dsl_dir_space_available(ds->ds_dir, NULL, 0, TRUE);
1534 *usedobjsp = ds->ds_phys->ds_bp.blk_fill;
1535 *availobjsp = DN_MAX_OBJECT - *usedobjsp;
1536}
1537
1538boolean_t
1539dsl_dataset_modified_since_lastsnap(dsl_dataset_t *ds)
1540{
1541 dsl_pool_t *dp = ds->ds_dir->dd_pool;
1542
1543 ASSERT(RW_LOCK_HELD(&dp->dp_config_rwlock) ||
1544 dsl_pool_sync_context(dp));
1545 if (ds->ds_prev == NULL)
1546 return (B_FALSE);
1547 if (ds->ds_phys->ds_bp.blk_birth >
1548 ds->ds_prev->ds_phys->ds_creation_txg)
1549 return (B_TRUE);
1550 return (B_FALSE);
1551}
1552
1538/* ARGSUSED */
1539static int
1540dsl_dataset_snapshot_rename_check(void *arg1, void *arg2, dmu_tx_t *tx)
1541{
1542 dsl_dataset_t *ds = arg1;
1543 char *newsnapname = arg2;
1544 dsl_dir_t *dd = ds->ds_dir;
1545 objset_t *mos = dd->dd_pool->dp_meta_objset;

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

1596 ds->ds_snapname, 8, 1, &ds->ds_object, tx);
1597 ASSERT3U(err, ==, 0);
1598
1599 spa_history_internal_log(LOG_DS_RENAME, dd->dd_pool->dp_spa, tx,
1600 cr, "dataset = %llu", ds->ds_object);
1601 dsl_dataset_close(hds, DS_MODE_NONE, FTAG);
1602}
1603
1553/* ARGSUSED */
1554static int
1555dsl_dataset_snapshot_rename_check(void *arg1, void *arg2, dmu_tx_t *tx)
1556{
1557 dsl_dataset_t *ds = arg1;
1558 char *newsnapname = arg2;
1559 dsl_dir_t *dd = ds->ds_dir;
1560 objset_t *mos = dd->dd_pool->dp_meta_objset;

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

1611 ds->ds_snapname, 8, 1, &ds->ds_object, tx);
1612 ASSERT3U(err, ==, 0);
1613
1614 spa_history_internal_log(LOG_DS_RENAME, dd->dd_pool->dp_spa, tx,
1615 cr, "dataset = %llu", ds->ds_object);
1616 dsl_dataset_close(hds, DS_MODE_NONE, FTAG);
1617}
1618
1604struct renamearg {
1619struct renamesnaparg {
1605 dsl_sync_task_group_t *dstg;
1606 char failed[MAXPATHLEN];
1607 char *oldsnap;
1608 char *newsnap;
1609};
1610
1611static int
1612dsl_snapshot_rename_one(char *name, void *arg)
1613{
1620 dsl_sync_task_group_t *dstg;
1621 char failed[MAXPATHLEN];
1622 char *oldsnap;
1623 char *newsnap;
1624};
1625
1626static int
1627dsl_snapshot_rename_one(char *name, void *arg)
1628{
1614 struct renamearg *ra = arg;
1629 struct renamesnaparg *ra = arg;
1615 dsl_dataset_t *ds = NULL;
1616 char *cp;
1617 int err;
1618
1619 cp = name + strlen(name);
1620 *cp = '@';
1621 (void) strcpy(cp + 1, ra->oldsnap);
1622

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

1654
1655 return (0);
1656}
1657
1658static int
1659dsl_recursive_rename(char *oldname, const char *newname)
1660{
1661 int err;
1630 dsl_dataset_t *ds = NULL;
1631 char *cp;
1632 int err;
1633
1634 cp = name + strlen(name);
1635 *cp = '@';
1636 (void) strcpy(cp + 1, ra->oldsnap);
1637

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

1669
1670 return (0);
1671}
1672
1673static int
1674dsl_recursive_rename(char *oldname, const char *newname)
1675{
1676 int err;
1662 struct renamearg *ra;
1677 struct renamesnaparg *ra;
1663 dsl_sync_task_t *dst;
1664 spa_t *spa;
1665 char *cp, *fsname = spa_strdup(oldname);
1666 int len = strlen(oldname);
1667
1668 /* truncate the snapshot name to get the fsname */
1669 cp = strchr(fsname, '@');
1670 *cp = '\0';
1671
1672 err = spa_open(fsname, &spa, FTAG);
1673 if (err) {
1674 kmem_free(fsname, len + 1);
1675 return (err);
1676 }
1678 dsl_sync_task_t *dst;
1679 spa_t *spa;
1680 char *cp, *fsname = spa_strdup(oldname);
1681 int len = strlen(oldname);
1682
1683 /* truncate the snapshot name to get the fsname */
1684 cp = strchr(fsname, '@');
1685 *cp = '\0';
1686
1687 err = spa_open(fsname, &spa, FTAG);
1688 if (err) {
1689 kmem_free(fsname, len + 1);
1690 return (err);
1691 }
1677 ra = kmem_alloc(sizeof (struct renamearg), KM_SLEEP);
1692 ra = kmem_alloc(sizeof (struct renamesnaparg), KM_SLEEP);
1678 ra->dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
1679
1680 ra->oldsnap = strchr(oldname, '@') + 1;
1681 ra->newsnap = strchr(newname, '@') + 1;
1682 *ra->failed = '\0';
1683
1684 err = dmu_objset_find(fsname, dsl_snapshot_rename_one, ra,
1685 DS_FIND_CHILDREN);

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

1699 }
1700 dsl_dataset_close(ds, DS_MODE_STANDARD, ra->dstg);
1701 }
1702
1703 if (err)
1704 (void) strcpy(oldname, ra->failed);
1705
1706 dsl_sync_task_group_destroy(ra->dstg);
1693 ra->dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
1694
1695 ra->oldsnap = strchr(oldname, '@') + 1;
1696 ra->newsnap = strchr(newname, '@') + 1;
1697 *ra->failed = '\0';
1698
1699 err = dmu_objset_find(fsname, dsl_snapshot_rename_one, ra,
1700 DS_FIND_CHILDREN);

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

1714 }
1715 dsl_dataset_close(ds, DS_MODE_STANDARD, ra->dstg);
1716 }
1717
1718 if (err)
1719 (void) strcpy(oldname, ra->failed);
1720
1721 dsl_sync_task_group_destroy(ra->dstg);
1707 kmem_free(ra, sizeof (struct renamearg));
1722 kmem_free(ra, sizeof (struct renamesnaparg));
1708 spa_close(spa, FTAG);
1709 return (err);
1710}
1711
1712static int
1713dsl_valid_rename(char *oldname, void *arg)
1714{
1715 int delta = *(int *)arg;

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

2046 */
2047 err = dsl_sync_task_do(ds->ds_dir->dd_pool,
2048 dsl_dataset_promote_check,
2049 dsl_dataset_promote_sync, ds, &pa, 2 + 2 * doi.doi_physical_blks);
2050 dsl_dataset_close(ds, DS_MODE_NONE, FTAG);
2051 return (err);
2052}
2053
1723 spa_close(spa, FTAG);
1724 return (err);
1725}
1726
1727static int
1728dsl_valid_rename(char *oldname, void *arg)
1729{
1730 int delta = *(int *)arg;

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

2061 */
2062 err = dsl_sync_task_do(ds->ds_dir->dd_pool,
2063 dsl_dataset_promote_check,
2064 dsl_dataset_promote_sync, ds, &pa, 2 + 2 * doi.doi_physical_blks);
2065 dsl_dataset_close(ds, DS_MODE_NONE, FTAG);
2066 return (err);
2067}
2068
2069#define SWITCH64(x, y) \
2070 { \
2071 uint64_t __tmp = (x); \
2072 (x) = (y); \
2073 (y) = __tmp; \
2074 }
2075
2076/* ARGSUSED */
2077static int
2078dsl_dataset_clone_swap_check(void *arg1, void *arg2, dmu_tx_t *tx)
2079{
2080 dsl_dataset_t *cds = arg1; /* clone to become new head */
2081 boolean_t *forcep = arg2;
2082 dsl_dir_t *cdd = cds->ds_dir;
2083 dsl_pool_t *dp = cds->ds_dir->dd_pool;
2084 dsl_dataset_t *ods; /* the snapshot cds is cloned off of */
2085 dsl_dataset_t *ohds = NULL;
2086 dsl_dir_t *odd;
2087 int err;
2088
2089 /* check that it is a clone */
2090 if (cdd->dd_phys->dd_clone_parent_obj == 0)
2091 return (EINVAL);
2092
2093 /* check that cds is not a snapshot */
2094 if (dsl_dataset_is_snapshot(cds))
2095 return (EINVAL);
2096
2097 /* open the origin */
2098 if (err = dsl_dataset_open_obj(dp, cdd->dd_phys->dd_clone_parent_obj,
2099 NULL, DS_MODE_STANDARD | DS_MODE_READONLY, FTAG, &ods))
2100 return (err);
2101 odd = ods->ds_dir;
2102
2103 /* make sure the clone is descendant of origin */
2104 if (cdd->dd_parent != odd) {
2105 err = EINVAL;
2106 goto out;
2107 }
2108
2109 /* check that there are no snapshots after the origin */
2110 if (cds->ds_phys->ds_prev_snap_obj != ods->ds_object ||
2111 ods->ds_phys->ds_next_snap_obj !=
2112 odd->dd_phys->dd_head_dataset_obj) {
2113 err = EINVAL;
2114 goto out;
2115 }
2116
2117 /*
2118 * Verify origin head dataset hasn't been modified or
2119 * 'force' has been passed down.
2120 */
2121 if (!(*forcep) &&
2122 (err = dsl_dataset_open_obj(cdd->dd_pool,
2123 odd->dd_phys->dd_head_dataset_obj, NULL, DS_MODE_EXCLUSIVE,
2124 FTAG, &ohds)) == 0) {
2125 if (dsl_dataset_modified_since_lastsnap(ohds))
2126 err = ETXTBSY;
2127 dsl_dataset_close(ohds, DS_MODE_EXCLUSIVE, FTAG);
2128 }
2129out:
2130 dsl_dataset_close(ods, DS_MODE_STANDARD, FTAG);
2131 return (err);
2132}
2133
2134/* ARGSUSED */
2135static void
2136dsl_dataset_clone_swap_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx)
2137{
2138 dsl_dataset_t *cds = arg1; /* clone to become new head */
2139 dsl_dir_t *cdd = cds->ds_dir;
2140 dsl_pool_t *dp = cds->ds_dir->dd_pool;
2141 dsl_dataset_t *ods, *ohds;
2142 dsl_dir_t *odd;
2143 uint64_t itor = 0;
2144 blkptr_t bp;
2145 uint64_t unique = 0;
2146 int err;
2147
2148 ASSERT(cdd->dd_phys->dd_clone_parent_obj != 0);
2149 ASSERT(dsl_dataset_is_snapshot(cds) == 0);
2150
2151 /* open the origin */
2152 VERIFY(0 == dsl_dataset_open_obj(dp, cdd->dd_phys->dd_clone_parent_obj,
2153 NULL, DS_MODE_STANDARD | DS_MODE_READONLY, FTAG, &ods));
2154 odd = ods->ds_dir;
2155 ASSERT(cds->ds_phys->ds_prev_snap_obj == ods->ds_object);
2156 ASSERT(ods->ds_phys->ds_next_snap_obj ==
2157 odd->dd_phys->dd_head_dataset_obj);
2158
2159 /* open the origin head */
2160 VERIFY(0 == dsl_dataset_open_obj(cdd->dd_pool,
2161 odd->dd_phys->dd_head_dataset_obj, NULL, DS_MODE_EXCLUSIVE,
2162 FTAG, &ohds));
2163 ASSERT(odd == ohds->ds_dir);
2164
2165 dmu_buf_will_dirty(cds->ds_dbuf, tx);
2166 dmu_buf_will_dirty(ohds->ds_dbuf, tx);
2167 dmu_buf_will_dirty(ods->ds_dbuf, tx);
2168
2169 /* compute unique space */
2170 while ((err = bplist_iterate(&cds->ds_deadlist, &itor, &bp)) == 0) {
2171 if (bp.blk_birth > ods->ds_phys->ds_prev_snap_txg)
2172 unique += bp_get_dasize(cdd->dd_pool->dp_spa, &bp);
2173 }
2174 VERIFY(err == ENOENT);
2175
2176 /* reset origin's unique bytes */
2177 ods->ds_phys->ds_unique_bytes = unique;
2178
2179 /* swap blkptrs */
2180 {
2181 blkptr_t tmp;
2182 tmp = ohds->ds_phys->ds_bp;
2183 ohds->ds_phys->ds_bp = cds->ds_phys->ds_bp;
2184 cds->ds_phys->ds_bp = tmp;
2185 }
2186
2187 /* set dd_*_bytes */
2188 {
2189 int64_t dused, dcomp, duncomp;
2190 uint64_t cdl_used, cdl_comp, cdl_uncomp;
2191 uint64_t odl_used, odl_comp, odl_uncomp;
2192
2193 VERIFY(0 == bplist_space(&cds->ds_deadlist, &cdl_used,
2194 &cdl_comp, &cdl_uncomp));
2195 VERIFY(0 == bplist_space(&ohds->ds_deadlist, &odl_used,
2196 &odl_comp, &odl_uncomp));
2197 dused = cds->ds_phys->ds_used_bytes + cdl_used -
2198 (ohds->ds_phys->ds_used_bytes + odl_used);
2199 dcomp = cds->ds_phys->ds_compressed_bytes + cdl_comp -
2200 (ohds->ds_phys->ds_compressed_bytes + odl_comp);
2201 duncomp = cds->ds_phys->ds_uncompressed_bytes + cdl_uncomp -
2202 (ohds->ds_phys->ds_uncompressed_bytes + odl_uncomp);
2203
2204 dsl_dir_diduse_space(odd, dused, dcomp, duncomp, tx);
2205 dsl_dir_diduse_space(cdd, -dused, -dcomp, -duncomp, tx);
2206 }
2207
2208 /* swap ds_*_bytes */
2209 SWITCH64(ohds->ds_phys->ds_used_bytes, cds->ds_phys->ds_used_bytes);
2210 SWITCH64(ohds->ds_phys->ds_compressed_bytes,
2211 cds->ds_phys->ds_compressed_bytes);
2212 SWITCH64(ohds->ds_phys->ds_uncompressed_bytes,
2213 cds->ds_phys->ds_uncompressed_bytes);
2214
2215 /* swap deadlists */
2216 bplist_close(&cds->ds_deadlist);
2217 bplist_close(&ohds->ds_deadlist);
2218 SWITCH64(ohds->ds_phys->ds_deadlist_obj, cds->ds_phys->ds_deadlist_obj);
2219 VERIFY(0 == bplist_open(&cds->ds_deadlist, dp->dp_meta_objset,
2220 cds->ds_phys->ds_deadlist_obj));
2221 VERIFY(0 == bplist_open(&ohds->ds_deadlist, dp->dp_meta_objset,
2222 ohds->ds_phys->ds_deadlist_obj));
2223
2224 dsl_dataset_close(ohds, DS_MODE_EXCLUSIVE, FTAG);
2225 dsl_dataset_close(ods, DS_MODE_STANDARD, FTAG);
2226}
2227
2054/*
2228/*
2229 * Swap the clone "cosname" with its origin head file system.
2230 */
2231int
2232dsl_dataset_clone_swap(const char *cosname, boolean_t force)
2233{
2234 dsl_dataset_t *ds;
2235 int err;
2236
2237 err = dsl_dataset_open(cosname,
2238 DS_MODE_EXCLUSIVE | DS_MODE_INCONSISTENT, FTAG, &ds);
2239 if (err)
2240 return (err);
2241
2242 err = dsl_sync_task_do(ds->ds_dir->dd_pool,
2243 dsl_dataset_clone_swap_check,
2244 dsl_dataset_clone_swap_sync, ds, &force, 9);
2245 dsl_dataset_close(ds, DS_MODE_EXCLUSIVE, FTAG);
2246 return (err);
2247}
2248
2249/*
2055 * Given a pool name and a dataset object number in that pool,
2056 * return the name of that dataset.
2057 */
2058int
2059dsl_dsobj_to_dsname(char *pname, uint64_t obj, char *buf)
2060{
2061 spa_t *spa;
2062 dsl_pool_t *dp;

--- 20 unchanged lines hidden ---
2250 * Given a pool name and a dataset object number in that pool,
2251 * return the name of that dataset.
2252 */
2253int
2254dsl_dsobj_to_dsname(char *pname, uint64_t obj, char *buf)
2255{
2256 spa_t *spa;
2257 dsl_pool_t *dp;

--- 20 unchanged lines hidden ---