83 dsl_dataset_block_born(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx)
84 {
85 int used = bp_get_dsize_sync(tx->tx_pool->dp_spa, bp);
86 int compressed = BP_GET_PSIZE(bp);
87 int uncompressed = BP_GET_UCSIZE(bp);
88 int64_t delta;
89
90 dprintf_bp(bp, "ds=%p", ds);
91
92 ASSERT(dmu_tx_is_syncing(tx));
93 /* It could have been compressed away to nothing */
94 if (BP_IS_HOLE(bp))
95 return;
96 ASSERT(BP_GET_TYPE(bp) != DMU_OT_NONE);
97 ASSERT(DMU_OT_IS_VALID(BP_GET_TYPE(bp)));
98 if (ds == NULL) {
99 dsl_pool_mos_diduse_space(tx->tx_pool,
100 used, compressed, uncompressed);
101 return;
102 }
103 dmu_buf_will_dirty(ds->ds_dbuf, tx);
104
105 mutex_enter(&ds->ds_dir->dd_lock);
106 mutex_enter(&ds->ds_lock);
107 delta = parent_delta(ds, used);
108 ds->ds_phys->ds_referenced_bytes += used;
109 ds->ds_phys->ds_compressed_bytes += compressed;
110 ds->ds_phys->ds_uncompressed_bytes += uncompressed;
111 ds->ds_phys->ds_unique_bytes += used;
112 mutex_exit(&ds->ds_lock);
113 dsl_dir_diduse_space(ds->ds_dir, DD_USED_HEAD, delta,
114 compressed, uncompressed, tx);
115 dsl_dir_transfer_space(ds->ds_dir, used - delta,
116 DD_USED_REFRSRV, DD_USED_HEAD, tx);
117 mutex_exit(&ds->ds_dir->dd_lock);
118 }
119
120 int
121 dsl_dataset_block_kill(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx,
122 boolean_t async)
123 {
124 if (BP_IS_HOLE(bp))
125 return (0);
126
127 ASSERT(dmu_tx_is_syncing(tx));
128 ASSERT(bp->blk_birth <= tx->tx_txg);
129
130 int used = bp_get_dsize_sync(tx->tx_pool->dp_spa, bp);
131 int compressed = BP_GET_PSIZE(bp);
132 int uncompressed = BP_GET_UCSIZE(bp);
133
134 ASSERT(used > 0);
135 if (ds == NULL) {
136 dsl_free(tx->tx_pool, tx->tx_txg, bp);
137 dsl_pool_mos_diduse_space(tx->tx_pool,
138 -used, -compressed, -uncompressed);
139 return (used);
140 }
141 ASSERT3P(tx->tx_pool, ==, ds->ds_dir->dd_pool);
142
143 ASSERT(!dsl_dataset_is_snapshot(ds));
144 dmu_buf_will_dirty(ds->ds_dbuf, tx);
145
146 if (bp->blk_birth > ds->ds_phys->ds_prev_snap_txg) {
147 int64_t delta;
148
149 dprintf_bp(bp, "freeing ds=%llu", ds->ds_object);
150 dsl_free(tx->tx_pool, tx->tx_txg, bp);
151
152 mutex_enter(&ds->ds_dir->dd_lock);
153 mutex_enter(&ds->ds_lock);
154 ASSERT(ds->ds_phys->ds_unique_bytes >= used ||
155 !DS_UNIQUE_IS_ACCURATE(ds));
156 delta = parent_delta(ds, -used);
157 ds->ds_phys->ds_unique_bytes -= used;
158 mutex_exit(&ds->ds_lock);
159 dsl_dir_diduse_space(ds->ds_dir, DD_USED_HEAD,
160 delta, -compressed, -uncompressed, tx);
161 dsl_dir_transfer_space(ds->ds_dir, -used - delta,
162 DD_USED_REFRSRV, DD_USED_HEAD, tx);
163 mutex_exit(&ds->ds_dir->dd_lock);
164 } else {
165 dprintf_bp(bp, "putting on dead list: %s", "");
166 if (async) {
167 /*
168 * We are here as part of zio's write done callback,
169 * which means we're a zio interrupt thread. We can't
170 * call dsl_deadlist_insert() now because it may block
171 * waiting for I/O. Instead, put bp on the deferred
172 * queue and let dsl_pool_sync() finish the job.
173 */
174 bplist_append(&ds->ds_pending_deadlist, bp);
175 } else {
176 dsl_deadlist_insert(&ds->ds_deadlist, bp, tx);
177 }
178 ASSERT3U(ds->ds_prev->ds_object, ==,
179 ds->ds_phys->ds_prev_snap_obj);
180 ASSERT(ds->ds_prev->ds_phys->ds_num_children > 0);
181 /* if (bp->blk_birth > prev prev snap txg) prev unique += bs */
182 if (ds->ds_prev->ds_phys->ds_next_snap_obj ==
183 ds->ds_object && bp->blk_birth >
574 } else {
575 dsl_dir_name(ds->ds_dir, name);
576 VERIFY0(dsl_dataset_get_snapname(ds));
577 if (ds->ds_snapname[0]) {
578 (void) strcat(name, "@");
579 /*
580 * We use a "recursive" mutex so that we
581 * can call dprintf_ds() with ds_lock held.
582 */
583 if (!MUTEX_HELD(&ds->ds_lock)) {
584 mutex_enter(&ds->ds_lock);
585 (void) strcat(name, ds->ds_snapname);
586 mutex_exit(&ds->ds_lock);
587 } else {
588 (void) strcat(name, ds->ds_snapname);
589 }
590 }
591 }
592 }
593
594 static int
595 dsl_dataset_namelen(dsl_dataset_t *ds)
596 {
597 int result;
598
599 if (ds == NULL) {
600 result = 3; /* "mos" */
601 } else {
602 result = dsl_dir_namelen(ds->ds_dir);
603 VERIFY0(dsl_dataset_get_snapname(ds));
604 if (ds->ds_snapname[0]) {
605 ++result; /* adding one for the @-sign */
606 if (!MUTEX_HELD(&ds->ds_lock)) {
607 mutex_enter(&ds->ds_lock);
608 result += strlen(ds->ds_snapname);
609 mutex_exit(&ds->ds_lock);
610 } else {
611 result += strlen(ds->ds_snapname);
612 }
613 }
614 }
615
616 return (result);
617 }
618
619 void
620 dsl_dataset_rele(dsl_dataset_t *ds, void *tag)
621 {
622 dmu_buf_rele(ds->ds_dbuf, tag);
623 }
624
625 void
626 dsl_dataset_disown(dsl_dataset_t *ds, void *tag)
627 {
628 ASSERT(ds->ds_owner == tag && ds->ds_dbuf != NULL);
629
630 mutex_enter(&ds->ds_lock);
631 ds->ds_owner = NULL;
632 mutex_exit(&ds->ds_lock);
633 dsl_dataset_long_rele(ds, tag);
634 if (ds->ds_dbuf != NULL)
635 dsl_dataset_rele(ds, tag);
636 else
637 dsl_dataset_evict(NULL, ds);
638 }
|
83 dsl_dataset_block_born(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx)
84 {
85 int used = bp_get_dsize_sync(tx->tx_pool->dp_spa, bp);
86 int compressed = BP_GET_PSIZE(bp);
87 int uncompressed = BP_GET_UCSIZE(bp);
88 int64_t delta;
89
90 dprintf_bp(bp, "ds=%p", ds);
91
92 ASSERT(dmu_tx_is_syncing(tx));
93 /* It could have been compressed away to nothing */
94 if (BP_IS_HOLE(bp))
95 return;
96 ASSERT(BP_GET_TYPE(bp) != DMU_OT_NONE);
97 ASSERT(DMU_OT_IS_VALID(BP_GET_TYPE(bp)));
98 if (ds == NULL) {
99 dsl_pool_mos_diduse_space(tx->tx_pool,
100 used, compressed, uncompressed);
101 return;
102 }
103
104 dmu_buf_will_dirty(ds->ds_dbuf, tx);
105 mutex_enter(&ds->ds_lock);
106 delta = parent_delta(ds, used);
107 ds->ds_phys->ds_referenced_bytes += used;
108 ds->ds_phys->ds_compressed_bytes += compressed;
109 ds->ds_phys->ds_uncompressed_bytes += uncompressed;
110 ds->ds_phys->ds_unique_bytes += used;
111 mutex_exit(&ds->ds_lock);
112 dsl_dir_diduse_space(ds->ds_dir, DD_USED_HEAD, delta,
113 compressed, uncompressed, tx);
114 dsl_dir_transfer_space(ds->ds_dir, used - delta,
115 DD_USED_REFRSRV, DD_USED_HEAD, tx);
116 }
117
118 int
119 dsl_dataset_block_kill(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx,
120 boolean_t async)
121 {
122 if (BP_IS_HOLE(bp))
123 return (0);
124
125 ASSERT(dmu_tx_is_syncing(tx));
126 ASSERT(bp->blk_birth <= tx->tx_txg);
127
128 int used = bp_get_dsize_sync(tx->tx_pool->dp_spa, bp);
129 int compressed = BP_GET_PSIZE(bp);
130 int uncompressed = BP_GET_UCSIZE(bp);
131
132 ASSERT(used > 0);
133 if (ds == NULL) {
134 dsl_free(tx->tx_pool, tx->tx_txg, bp);
135 dsl_pool_mos_diduse_space(tx->tx_pool,
136 -used, -compressed, -uncompressed);
137 return (used);
138 }
139 ASSERT3P(tx->tx_pool, ==, ds->ds_dir->dd_pool);
140
141 ASSERT(!dsl_dataset_is_snapshot(ds));
142 dmu_buf_will_dirty(ds->ds_dbuf, tx);
143
144 if (bp->blk_birth > ds->ds_phys->ds_prev_snap_txg) {
145 int64_t delta;
146
147 dprintf_bp(bp, "freeing ds=%llu", ds->ds_object);
148 dsl_free(tx->tx_pool, tx->tx_txg, bp);
149
150 mutex_enter(&ds->ds_lock);
151 ASSERT(ds->ds_phys->ds_unique_bytes >= used ||
152 !DS_UNIQUE_IS_ACCURATE(ds));
153 delta = parent_delta(ds, -used);
154 ds->ds_phys->ds_unique_bytes -= used;
155 mutex_exit(&ds->ds_lock);
156 dsl_dir_diduse_space(ds->ds_dir, DD_USED_HEAD,
157 delta, -compressed, -uncompressed, tx);
158 dsl_dir_transfer_space(ds->ds_dir, -used - delta,
159 DD_USED_REFRSRV, DD_USED_HEAD, tx);
160 } else {
161 dprintf_bp(bp, "putting on dead list: %s", "");
162 if (async) {
163 /*
164 * We are here as part of zio's write done callback,
165 * which means we're a zio interrupt thread. We can't
166 * call dsl_deadlist_insert() now because it may block
167 * waiting for I/O. Instead, put bp on the deferred
168 * queue and let dsl_pool_sync() finish the job.
169 */
170 bplist_append(&ds->ds_pending_deadlist, bp);
171 } else {
172 dsl_deadlist_insert(&ds->ds_deadlist, bp, tx);
173 }
174 ASSERT3U(ds->ds_prev->ds_object, ==,
175 ds->ds_phys->ds_prev_snap_obj);
176 ASSERT(ds->ds_prev->ds_phys->ds_num_children > 0);
177 /* if (bp->blk_birth > prev prev snap txg) prev unique += bs */
178 if (ds->ds_prev->ds_phys->ds_next_snap_obj ==
179 ds->ds_object && bp->blk_birth >
570 } else {
571 dsl_dir_name(ds->ds_dir, name);
572 VERIFY0(dsl_dataset_get_snapname(ds));
573 if (ds->ds_snapname[0]) {
574 (void) strcat(name, "@");
575 /*
576 * We use a "recursive" mutex so that we
577 * can call dprintf_ds() with ds_lock held.
578 */
579 if (!MUTEX_HELD(&ds->ds_lock)) {
580 mutex_enter(&ds->ds_lock);
581 (void) strcat(name, ds->ds_snapname);
582 mutex_exit(&ds->ds_lock);
583 } else {
584 (void) strcat(name, ds->ds_snapname);
585 }
586 }
587 }
588 }
589
590 void
591 dsl_dataset_rele(dsl_dataset_t *ds, void *tag)
592 {
593 dmu_buf_rele(ds->ds_dbuf, tag);
594 }
595
596 void
597 dsl_dataset_disown(dsl_dataset_t *ds, void *tag)
598 {
599 ASSERT(ds->ds_owner == tag && ds->ds_dbuf != NULL);
600
601 mutex_enter(&ds->ds_lock);
602 ds->ds_owner = NULL;
603 mutex_exit(&ds->ds_lock);
604 dsl_dataset_long_rele(ds, tag);
605 if (ds->ds_dbuf != NULL)
606 dsl_dataset_rele(ds, tag);
607 else
608 dsl_dataset_evict(NULL, ds);
609 }
|