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

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

20 */
21/*
22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2011 by Delphix. All rights reserved.
24 */
25/*
26 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
27 * Copyright (c) 2011 by Delphix. All rights reserved.
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

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

20 */
21/*
22 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2011 by Delphix. All rights reserved.
24 */
25/*
26 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
27 * Copyright (c) 2011 by Delphix. All rights reserved.
28 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
29 * Copyright (c) 2012, Martin Matuska <mm@FreeBSD.org>. All rights reserved.
28 */
29
30#include <sys/dmu.h>
31#include <sys/dmu_impl.h>
32#include <sys/dmu_tx.h>
33#include <sys/dbuf.h>
34#include <sys/dnode.h>
35#include <sys/zfs_context.h>

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

49#include <sys/ddt.h>
50#include <sys/zfs_onexit.h>
51
52/* Set this tunable to TRUE to replace corrupt data with 0x2f5baddb10c */
53int zfs_send_corrupt_data = B_FALSE;
54
55static char *dmu_recv_tag = "dmu_recv_tag";
56
30 */
31
32#include <sys/dmu.h>
33#include <sys/dmu_impl.h>
34#include <sys/dmu_tx.h>
35#include <sys/dbuf.h>
36#include <sys/dnode.h>
37#include <sys/zfs_context.h>

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

51#include <sys/ddt.h>
52#include <sys/zfs_onexit.h>
53
54/* Set this tunable to TRUE to replace corrupt data with 0x2f5baddb10c */
55int zfs_send_corrupt_data = B_FALSE;
56
57static char *dmu_recv_tag = "dmu_recv_tag";
58
57/*
58 * The list of data whose inclusion in a send stream can be pending from
59 * one call to backup_cb to another. Multiple calls to dump_free() and
60 * dump_freeobjects() can be aggregated into a single DRR_FREE or
61 * DRR_FREEOBJECTS replay record.
62 */
63typedef enum {
64 PENDING_NONE,
65 PENDING_FREE,
66 PENDING_FREEOBJECTS
67} pendop_t;
68
69struct backuparg {
70 dmu_replay_record_t *drr;
71 kthread_t *td;
72 struct file *fp;
73 offset_t *off;
74 objset_t *os;
75 zio_cksum_t zc;
76 uint64_t toguid;
77 int err;
78 pendop_t pending_op;
79};
80
81static int
59static int
82dump_bytes(struct backuparg *ba, void *buf, int len)
60dump_bytes(dmu_sendarg_t *dsp, void *buf, int len)
83{
61{
62 dsl_dataset_t *ds = dsp->dsa_os->os_dsl_dataset;
84 struct uio auio;
85 struct iovec aiov;
86 ASSERT3U(len % 8, ==, 0);
87
63 struct uio auio;
64 struct iovec aiov;
65 ASSERT3U(len % 8, ==, 0);
66
88 fletcher_4_incremental_native(buf, len, &ba->zc);
67 fletcher_4_incremental_native(buf, len, &dsp->dsa_zc);
89 aiov.iov_base = buf;
90 aiov.iov_len = len;
91 auio.uio_iov = &aiov;
92 auio.uio_iovcnt = 1;
93 auio.uio_resid = len;
94 auio.uio_segflg = UIO_SYSSPACE;
95 auio.uio_rw = UIO_WRITE;
96 auio.uio_offset = (off_t)-1;
68 aiov.iov_base = buf;
69 aiov.iov_len = len;
70 auio.uio_iov = &aiov;
71 auio.uio_iovcnt = 1;
72 auio.uio_resid = len;
73 auio.uio_segflg = UIO_SYSSPACE;
74 auio.uio_rw = UIO_WRITE;
75 auio.uio_offset = (off_t)-1;
97 auio.uio_td = ba->td;
76 auio.uio_td = dsp->dsa_td;
98#ifdef _KERNEL
77#ifdef _KERNEL
99 if (ba->fp->f_type == DTYPE_VNODE)
78 if (dsp->dsa_fp->f_type == DTYPE_VNODE)
100 bwillwrite();
79 bwillwrite();
101 ba->err = fo_write(ba->fp, &auio, ba->td->td_ucred, 0, ba->td);
80 dsp->dsa_err = fo_write(dsp->dsa_fp, &auio, dsp->dsa_td->td_ucred, 0,
81 dsp->dsa_td);
102#else
103 fprintf(stderr, "%s: returning EOPNOTSUPP\n", __func__);
82#else
83 fprintf(stderr, "%s: returning EOPNOTSUPP\n", __func__);
104 ba->err = EOPNOTSUPP;
84 dsp->dsa_err = EOPNOTSUPP;
105#endif
85#endif
106 *ba->off += len;
107 return (ba->err);
86 mutex_enter(&ds->ds_sendstream_lock);
87 *dsp->dsa_off += len;
88 mutex_exit(&ds->ds_sendstream_lock);
89
90 return (dsp->dsa_err);
108}
109
110static int
91}
92
93static int
111dump_free(struct backuparg *ba, uint64_t object, uint64_t offset,
94dump_free(dmu_sendarg_t *dsp, uint64_t object, uint64_t offset,
112 uint64_t length)
113{
95 uint64_t length)
96{
114 struct drr_free *drrf = &(ba->drr->drr_u.drr_free);
97 struct drr_free *drrf = &(dsp->dsa_drr->drr_u.drr_free);
115
116 /*
117 * If there is a pending op, but it's not PENDING_FREE, push it out,
118 * since free block aggregation can only be done for blocks of the
119 * same type (i.e., DRR_FREE records can only be aggregated with
120 * other DRR_FREE records. DRR_FREEOBJECTS records can only be
121 * aggregated with other DRR_FREEOBJECTS records.
122 */
98
99 /*
100 * If there is a pending op, but it's not PENDING_FREE, push it out,
101 * since free block aggregation can only be done for blocks of the
102 * same type (i.e., DRR_FREE records can only be aggregated with
103 * other DRR_FREE records. DRR_FREEOBJECTS records can only be
104 * aggregated with other DRR_FREEOBJECTS records.
105 */
123 if (ba->pending_op != PENDING_NONE && ba->pending_op != PENDING_FREE) {
124 if (dump_bytes(ba, ba->drr, sizeof (dmu_replay_record_t)) != 0)
106 if (dsp->dsa_pending_op != PENDING_NONE &&
107 dsp->dsa_pending_op != PENDING_FREE) {
108 if (dump_bytes(dsp, dsp->dsa_drr,
109 sizeof (dmu_replay_record_t)) != 0)
125 return (EINTR);
110 return (EINTR);
126 ba->pending_op = PENDING_NONE;
111 dsp->dsa_pending_op = PENDING_NONE;
127 }
128
112 }
113
129 if (ba->pending_op == PENDING_FREE) {
114 if (dsp->dsa_pending_op == PENDING_FREE) {
130 /*
131 * There should never be a PENDING_FREE if length is -1
132 * (because dump_dnode is the only place where this
133 * function is called with a -1, and only after flushing
134 * any pending record).
135 */
136 ASSERT(length != -1ULL);
137 /*
138 * Check to see whether this free block can be aggregated
139 * with pending one.
140 */
141 if (drrf->drr_object == object && drrf->drr_offset +
142 drrf->drr_length == offset) {
143 drrf->drr_length += length;
144 return (0);
145 } else {
146 /* not a continuation. Push out pending record */
115 /*
116 * There should never be a PENDING_FREE if length is -1
117 * (because dump_dnode is the only place where this
118 * function is called with a -1, and only after flushing
119 * any pending record).
120 */
121 ASSERT(length != -1ULL);
122 /*
123 * Check to see whether this free block can be aggregated
124 * with pending one.
125 */
126 if (drrf->drr_object == object && drrf->drr_offset +
127 drrf->drr_length == offset) {
128 drrf->drr_length += length;
129 return (0);
130 } else {
131 /* not a continuation. Push out pending record */
147 if (dump_bytes(ba, ba->drr,
132 if (dump_bytes(dsp, dsp->dsa_drr,
148 sizeof (dmu_replay_record_t)) != 0)
149 return (EINTR);
133 sizeof (dmu_replay_record_t)) != 0)
134 return (EINTR);
150 ba->pending_op = PENDING_NONE;
135 dsp->dsa_pending_op = PENDING_NONE;
151 }
152 }
153 /* create a FREE record and make it pending */
136 }
137 }
138 /* create a FREE record and make it pending */
154 bzero(ba->drr, sizeof (dmu_replay_record_t));
155 ba->drr->drr_type = DRR_FREE;
139 bzero(dsp->dsa_drr, sizeof (dmu_replay_record_t));
140 dsp->dsa_drr->drr_type = DRR_FREE;
156 drrf->drr_object = object;
157 drrf->drr_offset = offset;
158 drrf->drr_length = length;
141 drrf->drr_object = object;
142 drrf->drr_offset = offset;
143 drrf->drr_length = length;
159 drrf->drr_toguid = ba->toguid;
144 drrf->drr_toguid = dsp->dsa_toguid;
160 if (length == -1ULL) {
145 if (length == -1ULL) {
161 if (dump_bytes(ba, ba->drr, sizeof (dmu_replay_record_t)) != 0)
146 if (dump_bytes(dsp, dsp->dsa_drr,
147 sizeof (dmu_replay_record_t)) != 0)
162 return (EINTR);
163 } else {
148 return (EINTR);
149 } else {
164 ba->pending_op = PENDING_FREE;
150 dsp->dsa_pending_op = PENDING_FREE;
165 }
166
167 return (0);
168}
169
170static int
151 }
152
153 return (0);
154}
155
156static int
171dump_data(struct backuparg *ba, dmu_object_type_t type,
157dump_data(dmu_sendarg_t *dsp, dmu_object_type_t type,
172 uint64_t object, uint64_t offset, int blksz, const blkptr_t *bp, void *data)
173{
158 uint64_t object, uint64_t offset, int blksz, const blkptr_t *bp, void *data)
159{
174 struct drr_write *drrw = &(ba->drr->drr_u.drr_write);
160 struct drr_write *drrw = &(dsp->dsa_drr->drr_u.drr_write);
175
176
177 /*
178 * If there is any kind of pending aggregation (currently either
179 * a grouping of free objects or free blocks), push it out to
180 * the stream, since aggregation can't be done across operations
181 * of different types.
182 */
161
162
163 /*
164 * If there is any kind of pending aggregation (currently either
165 * a grouping of free objects or free blocks), push it out to
166 * the stream, since aggregation can't be done across operations
167 * of different types.
168 */
183 if (ba->pending_op != PENDING_NONE) {
184 if (dump_bytes(ba, ba->drr, sizeof (dmu_replay_record_t)) != 0)
169 if (dsp->dsa_pending_op != PENDING_NONE) {
170 if (dump_bytes(dsp, dsp->dsa_drr,
171 sizeof (dmu_replay_record_t)) != 0)
185 return (EINTR);
172 return (EINTR);
186 ba->pending_op = PENDING_NONE;
173 dsp->dsa_pending_op = PENDING_NONE;
187 }
188 /* write a DATA record */
174 }
175 /* write a DATA record */
189 bzero(ba->drr, sizeof (dmu_replay_record_t));
190 ba->drr->drr_type = DRR_WRITE;
176 bzero(dsp->dsa_drr, sizeof (dmu_replay_record_t));
177 dsp->dsa_drr->drr_type = DRR_WRITE;
191 drrw->drr_object = object;
192 drrw->drr_type = type;
193 drrw->drr_offset = offset;
194 drrw->drr_length = blksz;
178 drrw->drr_object = object;
179 drrw->drr_type = type;
180 drrw->drr_offset = offset;
181 drrw->drr_length = blksz;
195 drrw->drr_toguid = ba->toguid;
182 drrw->drr_toguid = dsp->dsa_toguid;
196 drrw->drr_checksumtype = BP_GET_CHECKSUM(bp);
197 if (zio_checksum_table[drrw->drr_checksumtype].ci_dedup)
198 drrw->drr_checksumflags |= DRR_CHECKSUM_DEDUP;
199 DDK_SET_LSIZE(&drrw->drr_key, BP_GET_LSIZE(bp));
200 DDK_SET_PSIZE(&drrw->drr_key, BP_GET_PSIZE(bp));
201 DDK_SET_COMPRESS(&drrw->drr_key, BP_GET_COMPRESS(bp));
202 drrw->drr_key.ddk_cksum = bp->blk_cksum;
203
183 drrw->drr_checksumtype = BP_GET_CHECKSUM(bp);
184 if (zio_checksum_table[drrw->drr_checksumtype].ci_dedup)
185 drrw->drr_checksumflags |= DRR_CHECKSUM_DEDUP;
186 DDK_SET_LSIZE(&drrw->drr_key, BP_GET_LSIZE(bp));
187 DDK_SET_PSIZE(&drrw->drr_key, BP_GET_PSIZE(bp));
188 DDK_SET_COMPRESS(&drrw->drr_key, BP_GET_COMPRESS(bp));
189 drrw->drr_key.ddk_cksum = bp->blk_cksum;
190
204 if (dump_bytes(ba, ba->drr, sizeof (dmu_replay_record_t)) != 0)
191 if (dump_bytes(dsp, dsp->dsa_drr, sizeof (dmu_replay_record_t)) != 0)
205 return (EINTR);
192 return (EINTR);
206 if (dump_bytes(ba, data, blksz) != 0)
193 if (dump_bytes(dsp, data, blksz) != 0)
207 return (EINTR);
208 return (0);
209}
210
211static int
194 return (EINTR);
195 return (0);
196}
197
198static int
212dump_spill(struct backuparg *ba, uint64_t object, int blksz, void *data)
199dump_spill(dmu_sendarg_t *dsp, uint64_t object, int blksz, void *data)
213{
200{
214 struct drr_spill *drrs = &(ba->drr->drr_u.drr_spill);
201 struct drr_spill *drrs = &(dsp->dsa_drr->drr_u.drr_spill);
215
202
216 if (ba->pending_op != PENDING_NONE) {
217 if (dump_bytes(ba, ba->drr, sizeof (dmu_replay_record_t)) != 0)
203 if (dsp->dsa_pending_op != PENDING_NONE) {
204 if (dump_bytes(dsp, dsp->dsa_drr,
205 sizeof (dmu_replay_record_t)) != 0)
218 return (EINTR);
206 return (EINTR);
219 ba->pending_op = PENDING_NONE;
207 dsp->dsa_pending_op = PENDING_NONE;
220 }
221
222 /* write a SPILL record */
208 }
209
210 /* write a SPILL record */
223 bzero(ba->drr, sizeof (dmu_replay_record_t));
224 ba->drr->drr_type = DRR_SPILL;
211 bzero(dsp->dsa_drr, sizeof (dmu_replay_record_t));
212 dsp->dsa_drr->drr_type = DRR_SPILL;
225 drrs->drr_object = object;
226 drrs->drr_length = blksz;
213 drrs->drr_object = object;
214 drrs->drr_length = blksz;
227 drrs->drr_toguid = ba->toguid;
215 drrs->drr_toguid = dsp->dsa_toguid;
228
216
229 if (dump_bytes(ba, ba->drr, sizeof (dmu_replay_record_t)))
217 if (dump_bytes(dsp, dsp->dsa_drr, sizeof (dmu_replay_record_t)))
230 return (EINTR);
218 return (EINTR);
231 if (dump_bytes(ba, data, blksz))
219 if (dump_bytes(dsp, data, blksz))
232 return (EINTR);
233 return (0);
234}
235
236static int
220 return (EINTR);
221 return (0);
222}
223
224static int
237dump_freeobjects(struct backuparg *ba, uint64_t firstobj, uint64_t numobjs)
225dump_freeobjects(dmu_sendarg_t *dsp, uint64_t firstobj, uint64_t numobjs)
238{
226{
239 struct drr_freeobjects *drrfo = &(ba->drr->drr_u.drr_freeobjects);
227 struct drr_freeobjects *drrfo = &(dsp->dsa_drr->drr_u.drr_freeobjects);
240
241 /*
242 * If there is a pending op, but it's not PENDING_FREEOBJECTS,
243 * push it out, since free block aggregation can only be done for
244 * blocks of the same type (i.e., DRR_FREE records can only be
245 * aggregated with other DRR_FREE records. DRR_FREEOBJECTS records
246 * can only be aggregated with other DRR_FREEOBJECTS records.
247 */
228
229 /*
230 * If there is a pending op, but it's not PENDING_FREEOBJECTS,
231 * push it out, since free block aggregation can only be done for
232 * blocks of the same type (i.e., DRR_FREE records can only be
233 * aggregated with other DRR_FREE records. DRR_FREEOBJECTS records
234 * can only be aggregated with other DRR_FREEOBJECTS records.
235 */
248 if (ba->pending_op != PENDING_NONE &&
249 ba->pending_op != PENDING_FREEOBJECTS) {
250 if (dump_bytes(ba, ba->drr, sizeof (dmu_replay_record_t)) != 0)
236 if (dsp->dsa_pending_op != PENDING_NONE &&
237 dsp->dsa_pending_op != PENDING_FREEOBJECTS) {
238 if (dump_bytes(dsp, dsp->dsa_drr,
239 sizeof (dmu_replay_record_t)) != 0)
251 return (EINTR);
240 return (EINTR);
252 ba->pending_op = PENDING_NONE;
241 dsp->dsa_pending_op = PENDING_NONE;
253 }
242 }
254 if (ba->pending_op == PENDING_FREEOBJECTS) {
243 if (dsp->dsa_pending_op == PENDING_FREEOBJECTS) {
255 /*
256 * See whether this free object array can be aggregated
257 * with pending one
258 */
259 if (drrfo->drr_firstobj + drrfo->drr_numobjs == firstobj) {
260 drrfo->drr_numobjs += numobjs;
261 return (0);
262 } else {
263 /* can't be aggregated. Push out pending record */
244 /*
245 * See whether this free object array can be aggregated
246 * with pending one
247 */
248 if (drrfo->drr_firstobj + drrfo->drr_numobjs == firstobj) {
249 drrfo->drr_numobjs += numobjs;
250 return (0);
251 } else {
252 /* can't be aggregated. Push out pending record */
264 if (dump_bytes(ba, ba->drr,
253 if (dump_bytes(dsp, dsp->dsa_drr,
265 sizeof (dmu_replay_record_t)) != 0)
266 return (EINTR);
254 sizeof (dmu_replay_record_t)) != 0)
255 return (EINTR);
267 ba->pending_op = PENDING_NONE;
256 dsp->dsa_pending_op = PENDING_NONE;
268 }
269 }
270
271 /* write a FREEOBJECTS record */
257 }
258 }
259
260 /* write a FREEOBJECTS record */
272 bzero(ba->drr, sizeof (dmu_replay_record_t));
273 ba->drr->drr_type = DRR_FREEOBJECTS;
261 bzero(dsp->dsa_drr, sizeof (dmu_replay_record_t));
262 dsp->dsa_drr->drr_type = DRR_FREEOBJECTS;
274 drrfo->drr_firstobj = firstobj;
275 drrfo->drr_numobjs = numobjs;
263 drrfo->drr_firstobj = firstobj;
264 drrfo->drr_numobjs = numobjs;
276 drrfo->drr_toguid = ba->toguid;
265 drrfo->drr_toguid = dsp->dsa_toguid;
277
266
278 ba->pending_op = PENDING_FREEOBJECTS;
267 dsp->dsa_pending_op = PENDING_FREEOBJECTS;
279
280 return (0);
281}
282
283static int
268
269 return (0);
270}
271
272static int
284dump_dnode(struct backuparg *ba, uint64_t object, dnode_phys_t *dnp)
273dump_dnode(dmu_sendarg_t *dsp, uint64_t object, dnode_phys_t *dnp)
285{
274{
286 struct drr_object *drro = &(ba->drr->drr_u.drr_object);
275 struct drr_object *drro = &(dsp->dsa_drr->drr_u.drr_object);
287
288 if (dnp == NULL || dnp->dn_type == DMU_OT_NONE)
276
277 if (dnp == NULL || dnp->dn_type == DMU_OT_NONE)
289 return (dump_freeobjects(ba, object, 1));
278 return (dump_freeobjects(dsp, object, 1));
290
279
291 if (ba->pending_op != PENDING_NONE) {
292 if (dump_bytes(ba, ba->drr, sizeof (dmu_replay_record_t)) != 0)
280 if (dsp->dsa_pending_op != PENDING_NONE) {
281 if (dump_bytes(dsp, dsp->dsa_drr,
282 sizeof (dmu_replay_record_t)) != 0)
293 return (EINTR);
283 return (EINTR);
294 ba->pending_op = PENDING_NONE;
284 dsp->dsa_pending_op = PENDING_NONE;
295 }
296
297 /* write an OBJECT record */
285 }
286
287 /* write an OBJECT record */
298 bzero(ba->drr, sizeof (dmu_replay_record_t));
299 ba->drr->drr_type = DRR_OBJECT;
288 bzero(dsp->dsa_drr, sizeof (dmu_replay_record_t));
289 dsp->dsa_drr->drr_type = DRR_OBJECT;
300 drro->drr_object = object;
301 drro->drr_type = dnp->dn_type;
302 drro->drr_bonustype = dnp->dn_bonustype;
303 drro->drr_blksz = dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT;
304 drro->drr_bonuslen = dnp->dn_bonuslen;
305 drro->drr_checksumtype = dnp->dn_checksum;
306 drro->drr_compress = dnp->dn_compress;
290 drro->drr_object = object;
291 drro->drr_type = dnp->dn_type;
292 drro->drr_bonustype = dnp->dn_bonustype;
293 drro->drr_blksz = dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT;
294 drro->drr_bonuslen = dnp->dn_bonuslen;
295 drro->drr_checksumtype = dnp->dn_checksum;
296 drro->drr_compress = dnp->dn_compress;
307 drro->drr_toguid = ba->toguid;
297 drro->drr_toguid = dsp->dsa_toguid;
308
298
309 if (dump_bytes(ba, ba->drr, sizeof (dmu_replay_record_t)) != 0)
299 if (dump_bytes(dsp, dsp->dsa_drr, sizeof (dmu_replay_record_t)) != 0)
310 return (EINTR);
311
300 return (EINTR);
301
312 if (dump_bytes(ba, DN_BONUS(dnp), P2ROUNDUP(dnp->dn_bonuslen, 8)) != 0)
302 if (dump_bytes(dsp, DN_BONUS(dnp), P2ROUNDUP(dnp->dn_bonuslen, 8)) != 0)
313 return (EINTR);
314
315 /* free anything past the end of the file */
303 return (EINTR);
304
305 /* free anything past the end of the file */
316 if (dump_free(ba, object, (dnp->dn_maxblkid + 1) *
306 if (dump_free(dsp, object, (dnp->dn_maxblkid + 1) *
317 (dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT), -1ULL))
318 return (EINTR);
307 (dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT), -1ULL))
308 return (EINTR);
319 if (ba->err)
309 if (dsp->dsa_err)
320 return (EINTR);
321 return (0);
322}
323
324#define BP_SPAN(dnp, level) \
325 (((uint64_t)dnp->dn_datablkszsec) << (SPA_MINBLOCKSHIFT + \
326 (level) * (dnp->dn_indblkshift - SPA_BLKPTRSHIFT)))
327
328/* ARGSUSED */
329static int
330backup_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, arc_buf_t *pbuf,
331 const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg)
332{
310 return (EINTR);
311 return (0);
312}
313
314#define BP_SPAN(dnp, level) \
315 (((uint64_t)dnp->dn_datablkszsec) << (SPA_MINBLOCKSHIFT + \
316 (level) * (dnp->dn_indblkshift - SPA_BLKPTRSHIFT)))
317
318/* ARGSUSED */
319static int
320backup_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, arc_buf_t *pbuf,
321 const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg)
322{
333 struct backuparg *ba = arg;
323 dmu_sendarg_t *dsp = arg;
334 dmu_object_type_t type = bp ? BP_GET_TYPE(bp) : DMU_OT_NONE;
335 int err = 0;
336
337 if (issig(JUSTLOOKING) && issig(FORREAL))
338 return (EINTR);
339
340 if (zb->zb_object != DMU_META_DNODE_OBJECT &&
341 DMU_OBJECT_IS_SPECIAL(zb->zb_object)) {
342 return (0);
343 } else if (bp == NULL && zb->zb_object == DMU_META_DNODE_OBJECT) {
344 uint64_t span = BP_SPAN(dnp, zb->zb_level);
345 uint64_t dnobj = (zb->zb_blkid * span) >> DNODE_SHIFT;
324 dmu_object_type_t type = bp ? BP_GET_TYPE(bp) : DMU_OT_NONE;
325 int err = 0;
326
327 if (issig(JUSTLOOKING) && issig(FORREAL))
328 return (EINTR);
329
330 if (zb->zb_object != DMU_META_DNODE_OBJECT &&
331 DMU_OBJECT_IS_SPECIAL(zb->zb_object)) {
332 return (0);
333 } else if (bp == NULL && zb->zb_object == DMU_META_DNODE_OBJECT) {
334 uint64_t span = BP_SPAN(dnp, zb->zb_level);
335 uint64_t dnobj = (zb->zb_blkid * span) >> DNODE_SHIFT;
346 err = dump_freeobjects(ba, dnobj, span >> DNODE_SHIFT);
336 err = dump_freeobjects(dsp, dnobj, span >> DNODE_SHIFT);
347 } else if (bp == NULL) {
348 uint64_t span = BP_SPAN(dnp, zb->zb_level);
337 } else if (bp == NULL) {
338 uint64_t span = BP_SPAN(dnp, zb->zb_level);
349 err = dump_free(ba, zb->zb_object, zb->zb_blkid * span, span);
339 err = dump_free(dsp, zb->zb_object, zb->zb_blkid * span, span);
350 } else if (zb->zb_level > 0 || type == DMU_OT_OBJSET) {
351 return (0);
352 } else if (type == DMU_OT_DNODE) {
353 dnode_phys_t *blk;
354 int i;
355 int blksz = BP_GET_LSIZE(bp);
356 uint32_t aflags = ARC_WAIT;
357 arc_buf_t *abuf;
358
359 if (dsl_read(NULL, spa, bp, pbuf,
360 arc_getbuf_func, &abuf, ZIO_PRIORITY_ASYNC_READ,
361 ZIO_FLAG_CANFAIL, &aflags, zb) != 0)
362 return (EIO);
363
364 blk = abuf->b_data;
365 for (i = 0; i < blksz >> DNODE_SHIFT; i++) {
366 uint64_t dnobj = (zb->zb_blkid <<
367 (DNODE_BLOCK_SHIFT - DNODE_SHIFT)) + i;
340 } else if (zb->zb_level > 0 || type == DMU_OT_OBJSET) {
341 return (0);
342 } else if (type == DMU_OT_DNODE) {
343 dnode_phys_t *blk;
344 int i;
345 int blksz = BP_GET_LSIZE(bp);
346 uint32_t aflags = ARC_WAIT;
347 arc_buf_t *abuf;
348
349 if (dsl_read(NULL, spa, bp, pbuf,
350 arc_getbuf_func, &abuf, ZIO_PRIORITY_ASYNC_READ,
351 ZIO_FLAG_CANFAIL, &aflags, zb) != 0)
352 return (EIO);
353
354 blk = abuf->b_data;
355 for (i = 0; i < blksz >> DNODE_SHIFT; i++) {
356 uint64_t dnobj = (zb->zb_blkid <<
357 (DNODE_BLOCK_SHIFT - DNODE_SHIFT)) + i;
368 err = dump_dnode(ba, dnobj, blk+i);
358 err = dump_dnode(dsp, dnobj, blk+i);
369 if (err)
370 break;
371 }
372 (void) arc_buf_remove_ref(abuf, &abuf);
373 } else if (type == DMU_OT_SA) {
374 uint32_t aflags = ARC_WAIT;
375 arc_buf_t *abuf;
376 int blksz = BP_GET_LSIZE(bp);
377
378 if (arc_read_nolock(NULL, spa, bp,
379 arc_getbuf_func, &abuf, ZIO_PRIORITY_ASYNC_READ,
380 ZIO_FLAG_CANFAIL, &aflags, zb) != 0)
381 return (EIO);
382
359 if (err)
360 break;
361 }
362 (void) arc_buf_remove_ref(abuf, &abuf);
363 } else if (type == DMU_OT_SA) {
364 uint32_t aflags = ARC_WAIT;
365 arc_buf_t *abuf;
366 int blksz = BP_GET_LSIZE(bp);
367
368 if (arc_read_nolock(NULL, spa, bp,
369 arc_getbuf_func, &abuf, ZIO_PRIORITY_ASYNC_READ,
370 ZIO_FLAG_CANFAIL, &aflags, zb) != 0)
371 return (EIO);
372
383 err = dump_spill(ba, zb->zb_object, blksz, abuf->b_data);
373 err = dump_spill(dsp, zb->zb_object, blksz, abuf->b_data);
384 (void) arc_buf_remove_ref(abuf, &abuf);
385 } else { /* it's a level-0 block of a regular object */
386 uint32_t aflags = ARC_WAIT;
387 arc_buf_t *abuf;
388 int blksz = BP_GET_LSIZE(bp);
389
390 if (dsl_read(NULL, spa, bp, pbuf,
391 arc_getbuf_func, &abuf, ZIO_PRIORITY_ASYNC_READ,

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

399 (char *)ptr < (char *)abuf->b_data + blksz;
400 ptr++)
401 *ptr = 0x2f5baddb10c;
402 } else {
403 return (EIO);
404 }
405 }
406
374 (void) arc_buf_remove_ref(abuf, &abuf);
375 } else { /* it's a level-0 block of a regular object */
376 uint32_t aflags = ARC_WAIT;
377 arc_buf_t *abuf;
378 int blksz = BP_GET_LSIZE(bp);
379
380 if (dsl_read(NULL, spa, bp, pbuf,
381 arc_getbuf_func, &abuf, ZIO_PRIORITY_ASYNC_READ,

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

389 (char *)ptr < (char *)abuf->b_data + blksz;
390 ptr++)
391 *ptr = 0x2f5baddb10c;
392 } else {
393 return (EIO);
394 }
395 }
396
407 err = dump_data(ba, type, zb->zb_object, zb->zb_blkid * blksz,
397 err = dump_data(dsp, type, zb->zb_object, zb->zb_blkid * blksz,
408 blksz, bp, abuf->b_data);
409 (void) arc_buf_remove_ref(abuf, &abuf);
410 }
411
412 ASSERT(err == 0 || err == EINTR);
413 return (err);
414}
415
416int
398 blksz, bp, abuf->b_data);
399 (void) arc_buf_remove_ref(abuf, &abuf);
400 }
401
402 ASSERT(err == 0 || err == EINTR);
403 return (err);
404}
405
406int
417dmu_sendbackup(objset_t *tosnap, objset_t *fromsnap, boolean_t fromorigin,
418 struct file *fp, offset_t *off)
407dmu_send(objset_t *tosnap, objset_t *fromsnap, boolean_t fromorigin,
408 int outfd, struct file *fp, offset_t *off)
419{
420 dsl_dataset_t *ds = tosnap->os_dsl_dataset;
421 dsl_dataset_t *fromds = fromsnap ? fromsnap->os_dsl_dataset : NULL;
422 dmu_replay_record_t *drr;
409{
410 dsl_dataset_t *ds = tosnap->os_dsl_dataset;
411 dsl_dataset_t *fromds = fromsnap ? fromsnap->os_dsl_dataset : NULL;
412 dmu_replay_record_t *drr;
423 struct backuparg ba;
413 dmu_sendarg_t *dsp;
424 int err;
425 uint64_t fromtxg = 0;
426
427 /* tosnap must be a snapshot */
428 if (ds->ds_phys->ds_next_snap_obj == 0)
429 return (EINVAL);
430
431 /* fromsnap must be an earlier snapshot from the same fs as tosnap */

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

456 drr->drr_type = DRR_BEGIN;
457 drr->drr_u.drr_begin.drr_magic = DMU_BACKUP_MAGIC;
458 DMU_SET_STREAM_HDRTYPE(drr->drr_u.drr_begin.drr_versioninfo,
459 DMU_SUBSTREAM);
460
461#ifdef _KERNEL
462 if (dmu_objset_type(tosnap) == DMU_OST_ZFS) {
463 uint64_t version;
414 int err;
415 uint64_t fromtxg = 0;
416
417 /* tosnap must be a snapshot */
418 if (ds->ds_phys->ds_next_snap_obj == 0)
419 return (EINVAL);
420
421 /* fromsnap must be an earlier snapshot from the same fs as tosnap */

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

446 drr->drr_type = DRR_BEGIN;
447 drr->drr_u.drr_begin.drr_magic = DMU_BACKUP_MAGIC;
448 DMU_SET_STREAM_HDRTYPE(drr->drr_u.drr_begin.drr_versioninfo,
449 DMU_SUBSTREAM);
450
451#ifdef _KERNEL
452 if (dmu_objset_type(tosnap) == DMU_OST_ZFS) {
453 uint64_t version;
464 if (zfs_get_zplprop(tosnap, ZFS_PROP_VERSION, &version) != 0)
454 if (zfs_get_zplprop(tosnap, ZFS_PROP_VERSION, &version) != 0) {
455 kmem_free(drr, sizeof (dmu_replay_record_t));
465 return (EINVAL);
456 return (EINVAL);
457 }
466 if (version == ZPL_VERSION_SA) {
467 DMU_SET_FEATUREFLAGS(
468 drr->drr_u.drr_begin.drr_versioninfo,
469 DMU_BACKUP_FEATURE_SA_SPILL);
470 }
471 }
472#endif
473

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

484 drr->drr_u.drr_begin.drr_fromguid = fromds->ds_phys->ds_guid;
485 dsl_dataset_name(ds, drr->drr_u.drr_begin.drr_toname);
486
487 if (fromds)
488 fromtxg = fromds->ds_phys->ds_creation_txg;
489 if (fromorigin)
490 dsl_dataset_rele(fromds, FTAG);
491
458 if (version == ZPL_VERSION_SA) {
459 DMU_SET_FEATUREFLAGS(
460 drr->drr_u.drr_begin.drr_versioninfo,
461 DMU_BACKUP_FEATURE_SA_SPILL);
462 }
463 }
464#endif
465

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

476 drr->drr_u.drr_begin.drr_fromguid = fromds->ds_phys->ds_guid;
477 dsl_dataset_name(ds, drr->drr_u.drr_begin.drr_toname);
478
479 if (fromds)
480 fromtxg = fromds->ds_phys->ds_creation_txg;
481 if (fromorigin)
482 dsl_dataset_rele(fromds, FTAG);
483
492 ba.drr = drr;
493 ba.td = curthread;
494 ba.fp = fp;
495 ba.os = tosnap;
496 ba.off = off;
497 ba.toguid = ds->ds_phys->ds_guid;
498 ZIO_SET_CHECKSUM(&ba.zc, 0, 0, 0, 0);
499 ba.pending_op = PENDING_NONE;
484 dsp = kmem_zalloc(sizeof (dmu_sendarg_t), KM_SLEEP);
500
485
501 if (dump_bytes(&ba, drr, sizeof (dmu_replay_record_t)) != 0) {
502 kmem_free(drr, sizeof (dmu_replay_record_t));
503 return (ba.err);
486 dsp->dsa_drr = drr;
487 dsp->dsa_outfd = outfd;
488 dsp->dsa_proc = curproc;
489 dsp->dsa_td = curthread;
490 dsp->dsa_fp = fp;
491 dsp->dsa_os = tosnap;
492 dsp->dsa_off = off;
493 dsp->dsa_toguid = ds->ds_phys->ds_guid;
494 ZIO_SET_CHECKSUM(&dsp->dsa_zc, 0, 0, 0, 0);
495 dsp->dsa_pending_op = PENDING_NONE;
496
497 mutex_enter(&ds->ds_sendstream_lock);
498 list_insert_head(&ds->ds_sendstreams, dsp);
499 mutex_exit(&ds->ds_sendstream_lock);
500
501 if (dump_bytes(dsp, drr, sizeof (dmu_replay_record_t)) != 0) {
502 err = dsp->dsa_err;
503 goto out;
504 }
505
506 err = traverse_dataset(ds, fromtxg, TRAVERSE_PRE | TRAVERSE_PREFETCH,
504 }
505
506 err = traverse_dataset(ds, fromtxg, TRAVERSE_PRE | TRAVERSE_PREFETCH,
507 backup_cb, &ba);
507 backup_cb, dsp);
508
508
509 if (ba.pending_op != PENDING_NONE)
510 if (dump_bytes(&ba, drr, sizeof (dmu_replay_record_t)) != 0)
509 if (dsp->dsa_pending_op != PENDING_NONE)
510 if (dump_bytes(dsp, drr, sizeof (dmu_replay_record_t)) != 0)
511 err = EINTR;
512
513 if (err) {
511 err = EINTR;
512
513 if (err) {
514 if (err == EINTR && ba.err)
515 err = ba.err;
516 kmem_free(drr, sizeof (dmu_replay_record_t));
517 return (err);
514 if (err == EINTR && dsp->dsa_err)
515 err = dsp->dsa_err;
516 goto out;
518 }
519
520 bzero(drr, sizeof (dmu_replay_record_t));
521 drr->drr_type = DRR_END;
517 }
518
519 bzero(drr, sizeof (dmu_replay_record_t));
520 drr->drr_type = DRR_END;
522 drr->drr_u.drr_end.drr_checksum = ba.zc;
523 drr->drr_u.drr_end.drr_toguid = ba.toguid;
521 drr->drr_u.drr_end.drr_checksum = dsp->dsa_zc;
522 drr->drr_u.drr_end.drr_toguid = dsp->dsa_toguid;
524
523
525 if (dump_bytes(&ba, drr, sizeof (dmu_replay_record_t)) != 0) {
526 kmem_free(drr, sizeof (dmu_replay_record_t));
527 return (ba.err);
524 if (dump_bytes(dsp, drr, sizeof (dmu_replay_record_t)) != 0) {
525 err = dsp->dsa_err;
526 goto out;
528 }
529
527 }
528
529out:
530 mutex_enter(&ds->ds_sendstream_lock);
531 list_remove(&ds->ds_sendstreams, dsp);
532 mutex_exit(&ds->ds_sendstream_lock);
533
530 kmem_free(drr, sizeof (dmu_replay_record_t));
534 kmem_free(drr, sizeof (dmu_replay_record_t));
535 kmem_free(dsp, sizeof (dmu_sendarg_t));
531
536
532 return (0);
537 return (err);
533}
534
535int
536dmu_send_estimate(objset_t *tosnap, objset_t *fromsnap, boolean_t fromorigin,
537 uint64_t *sizep)
538{
539 dsl_dataset_t *ds = tosnap->os_dsl_dataset;
540 dsl_dataset_t *fromds = fromsnap ? fromsnap->os_dsl_dataset : NULL;

--- 1182 unchanged lines hidden ---
538}
539
540int
541dmu_send_estimate(objset_t *tosnap, objset_t *fromsnap, boolean_t fromorigin,
542 uint64_t *sizep)
543{
544 dsl_dataset_t *ds = tosnap->os_dsl_dataset;
545 dsl_dataset_t *fromds = fromsnap ? fromsnap->os_dsl_dataset : NULL;

--- 1182 unchanged lines hidden ---