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