43 #include "zfs_namecheck.h" |
43 #include "zfs_namecheck.h" |
44 #include "zfs_prop.h" |
44 #include "zfs_prop.h" |
45 #include "zfs_fletcher.h" |
45 #include "zfs_fletcher.h" |
46 #include "libzfs_impl.h" |
46 #include "libzfs_impl.h" |
47 #include <sha2.h> |
47 #include <sha2.h> |
|
48 #include <sys/zio_checksum.h> |
|
49 #include <sys/ddt.h> |
48 |
50 |
49 /* in libzfs_dataset.c */ |
51 /* in libzfs_dataset.c */ |
50 extern void zfs_setprop_error(libzfs_handle_t *, zfs_prop_t, int, char *); |
52 extern void zfs_setprop_error(libzfs_handle_t *, zfs_prop_t, int, char *); |
51 |
53 |
52 static int zfs_receive_impl(libzfs_handle_t *, const char *, recvflags_t, |
54 static int zfs_receive_impl(libzfs_handle_t *, const char *, recvflags_t, |
143 * return value: true - entry was found |
147 * return value: true - entry was found |
144 * false - entry was not found |
148 * false - entry was not found |
145 */ |
149 */ |
146 static boolean_t |
150 static boolean_t |
147 ddt_update(libzfs_handle_t *hdl, dedup_table_t *ddt, zio_cksum_t *cs, |
151 ddt_update(libzfs_handle_t *hdl, dedup_table_t *ddt, zio_cksum_t *cs, |
148 dataref_t *dr) |
152 uint64_t prop, dataref_t *dr) |
149 { |
153 { |
150 uint32_t hashcode; |
154 uint32_t hashcode; |
151 dedup_entry_t **ddepp; |
155 dedup_entry_t **ddepp; |
152 |
156 |
153 hashcode = BF64_GET(cs->zc_word[0], 0, ddt->numhashbits); |
157 hashcode = BF64_GET(cs->zc_word[0], 0, ddt->numhashbits); |
154 |
158 |
155 for (ddepp = &(ddt->dedup_hash_array[hashcode]); *ddepp != NULL; |
159 for (ddepp = &(ddt->dedup_hash_array[hashcode]); *ddepp != NULL; |
156 ddepp = &((*ddepp)->dde_next)) { |
160 ddepp = &((*ddepp)->dde_next)) { |
157 if (ZIO_CHECKSUM_EQUAL(((*ddepp)->dde_chksum), *cs)) { |
161 if (ZIO_CHECKSUM_EQUAL(((*ddepp)->dde_chksum), *cs) && |
|
162 (*ddepp)->dde_prop == prop) { |
158 *dr = (*ddepp)->dde_ref; |
163 *dr = (*ddepp)->dde_ref; |
159 return (B_TRUE); |
164 return (B_TRUE); |
160 } |
165 } |
161 } |
166 } |
162 ddt_hash_append(hdl, ddt, ddepp, cs, dr); |
167 ddt_hash_append(hdl, ddt, ddepp, cs, prop, dr); |
163 return (B_FALSE); |
168 return (B_FALSE); |
164 } |
169 } |
165 |
170 |
166 static int |
171 static int |
167 cksum_and_write(const void *buf, uint64_t len, zio_cksum_t *zc, int outfd) |
172 cksum_and_write(const void *buf, uint64_t len, zio_cksum_t *zc, int outfd) |
198 struct drr_end *drre = &thedrr.drr_u.drr_end; |
203 struct drr_end *drre = &thedrr.drr_u.drr_end; |
199 struct drr_object *drro = &thedrr.drr_u.drr_object; |
204 struct drr_object *drro = &thedrr.drr_u.drr_object; |
200 struct drr_write *drrw = &thedrr.drr_u.drr_write; |
205 struct drr_write *drrw = &thedrr.drr_u.drr_write; |
201 FILE *ofp; |
206 FILE *ofp; |
202 int outfd; |
207 int outfd; |
203 dmu_replay_record_t wbr_drr; |
208 dmu_replay_record_t wbr_drr = {0}; |
204 struct drr_write_byref *wbr_drrr = &wbr_drr.drr_u.drr_write_byref; |
209 struct drr_write_byref *wbr_drrr = &wbr_drr.drr_u.drr_write_byref; |
205 dedup_table_t ddt; |
210 dedup_table_t ddt; |
206 zio_cksum_t stream_cksum; |
211 zio_cksum_t stream_cksum; |
207 uint64_t physmem = sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE); |
212 uint64_t physmem = sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE); |
208 uint64_t numbuckets; |
213 uint64_t numbuckets; |
241 int fflags; |
246 int fflags; |
242 ZIO_SET_CHECKSUM(&stream_cksum, 0, 0, 0, 0); |
247 ZIO_SET_CHECKSUM(&stream_cksum, 0, 0, 0, 0); |
243 |
248 |
244 /* set the DEDUP feature flag for this stream */ |
249 /* set the DEDUP feature flag for this stream */ |
245 fflags = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo); |
250 fflags = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo); |
246 fflags |= DMU_BACKUP_FEATURE_DEDUP; |
251 fflags |= (DMU_BACKUP_FEATURE_DEDUP | |
|
252 DMU_BACKUP_FEATURE_DEDUPPROPS); |
247 DMU_SET_FEATUREFLAGS(drrb->drr_versioninfo, fflags); |
253 DMU_SET_FEATUREFLAGS(drrb->drr_versioninfo, fflags); |
248 |
254 |
249 if (cksum_and_write(drr, sizeof (dmu_replay_record_t), |
255 if (cksum_and_write(drr, sizeof (dmu_replay_record_t), |
250 &stream_cksum, outfd) == -1) |
256 &stream_cksum, outfd) == -1) |
251 goto out; |
257 goto out; |
307 case DRR_WRITE: |
313 case DRR_WRITE: |
308 { |
314 { |
309 dataref_t dataref; |
315 dataref_t dataref; |
310 |
316 |
311 (void) ssread(buf, drrw->drr_length, ofp); |
317 (void) ssread(buf, drrw->drr_length, ofp); |
|
318 |
312 /* |
319 /* |
313 * If the block doesn't already have a dedup |
320 * Use the existing checksum if it's dedup-capable, |
314 * checksum, calculate one. |
321 * else calculate a SHA256 checksum for it. |
315 */ |
322 */ |
316 if (ZIO_CHECKSUM_EQUAL(drrw->drr_blkcksum, |
323 |
317 zero_cksum)) { |
324 if (ZIO_CHECKSUM_EQUAL(drrw->drr_key.ddk_cksum, |
|
325 zero_cksum) || |
|
326 !DRR_IS_DEDUP_CAPABLE(drrw->drr_checksumflags)) { |
318 SHA256_CTX ctx; |
327 SHA256_CTX ctx; |
319 zio_cksum_t tmpsha256; |
328 zio_cksum_t tmpsha256; |
320 |
329 |
321 SHA256Init(&ctx); |
330 SHA256Init(&ctx); |
322 SHA256Update(&ctx, buf, drrw->drr_length); |
331 SHA256Update(&ctx, buf, drrw->drr_length); |
323 SHA256Final(&tmpsha256, &ctx); |
332 SHA256Final(&tmpsha256, &ctx); |
324 drrw->drr_blkcksum.zc_word[0] = |
333 drrw->drr_key.ddk_cksum.zc_word[0] = |
325 BE_64(tmpsha256.zc_word[0]); |
334 BE_64(tmpsha256.zc_word[0]); |
326 drrw->drr_blkcksum.zc_word[1] = |
335 drrw->drr_key.ddk_cksum.zc_word[1] = |
327 BE_64(tmpsha256.zc_word[1]); |
336 BE_64(tmpsha256.zc_word[1]); |
328 drrw->drr_blkcksum.zc_word[2] = |
337 drrw->drr_key.ddk_cksum.zc_word[2] = |
329 BE_64(tmpsha256.zc_word[2]); |
338 BE_64(tmpsha256.zc_word[2]); |
330 drrw->drr_blkcksum.zc_word[3] = |
339 drrw->drr_key.ddk_cksum.zc_word[3] = |
331 BE_64(tmpsha256.zc_word[3]); |
340 BE_64(tmpsha256.zc_word[3]); |
|
341 drrw->drr_checksumtype = ZIO_CHECKSUM_SHA256; |
|
342 drrw->drr_checksumflags = DRR_CHECKSUM_DEDUP; |
332 } |
343 } |
333 |
344 |
334 dataref.ref_guid = drrw->drr_toguid; |
345 dataref.ref_guid = drrw->drr_toguid; |
335 dataref.ref_object = drrw->drr_object; |
346 dataref.ref_object = drrw->drr_object; |
336 dataref.ref_offset = drrw->drr_offset; |
347 dataref.ref_offset = drrw->drr_offset; |
337 |
348 |
338 if (ddt_update(dda->dedup_hdl, &ddt, |
349 if (ddt_update(dda->dedup_hdl, &ddt, |
339 &drrw->drr_blkcksum, &dataref)) { |
350 &drrw->drr_key.ddk_cksum, drrw->drr_key.ddk_prop, |
|
351 &dataref)) { |
340 /* block already present in stream */ |
352 /* block already present in stream */ |
341 wbr_drrr->drr_object = drrw->drr_object; |
353 wbr_drrr->drr_object = drrw->drr_object; |
342 wbr_drrr->drr_offset = drrw->drr_offset; |
354 wbr_drrr->drr_offset = drrw->drr_offset; |
343 wbr_drrr->drr_length = drrw->drr_length; |
355 wbr_drrr->drr_length = drrw->drr_length; |
344 wbr_drrr->drr_toguid = drrw->drr_toguid; |
356 wbr_drrr->drr_toguid = drrw->drr_toguid; |
346 wbr_drrr->drr_refobject = |
358 wbr_drrr->drr_refobject = |
347 dataref.ref_object; |
359 dataref.ref_object; |
348 wbr_drrr->drr_refoffset = |
360 wbr_drrr->drr_refoffset = |
349 dataref.ref_offset; |
361 dataref.ref_offset; |
350 |
362 |
351 wbr_drrr->drr_blkcksum = drrw->drr_blkcksum; |
363 wbr_drrr->drr_checksumtype = |
|
364 drrw->drr_checksumtype; |
|
365 wbr_drrr->drr_checksumflags = |
|
366 drrw->drr_checksumtype; |
|
367 wbr_drrr->drr_key.ddk_cksum = |
|
368 drrw->drr_key.ddk_cksum; |
|
369 wbr_drrr->drr_key.ddk_prop = |
|
370 drrw->drr_key.ddk_prop; |
352 |
371 |
353 if (cksum_and_write(&wbr_drr, |
372 if (cksum_and_write(&wbr_drr, |
354 sizeof (dmu_replay_record_t), &stream_cksum, |
373 sizeof (dmu_replay_record_t), &stream_cksum, |
355 outfd) == -1) |
374 outfd) == -1) |
356 goto out; |
375 goto out; |
1135 if (zfs_spa_version(zhp, &spa_version) == 0 && |
1154 if (zfs_spa_version(zhp, &spa_version) == 0 && |
1136 spa_version >= SPA_VERSION_USERREFS) |
1155 spa_version >= SPA_VERSION_USERREFS) |
1137 holdsnaps = B_TRUE; |
1156 holdsnaps = B_TRUE; |
1138 |
1157 |
1139 if (flags.dedup) { |
1158 if (flags.dedup) { |
1140 featureflags |= DMU_BACKUP_FEATURE_DEDUP; |
1159 featureflags |= (DMU_BACKUP_FEATURE_DEDUP | |
|
1160 DMU_BACKUP_FEATURE_DEDUPPROPS); |
1141 if (err = pipe(pipefd)) { |
1161 if (err = pipe(pipefd)) { |
1142 zfs_error_aux(zhp->zfs_hdl, strerror(errno)); |
1162 zfs_error_aux(zhp->zfs_hdl, strerror(errno)); |
1143 return (zfs_error(zhp->zfs_hdl, EZFS_PIPEFAILED, |
1163 return (zfs_error(zhp->zfs_hdl, EZFS_PIPEFAILED, |
1144 errbuf)); |
1164 errbuf)); |
1145 } |
1165 } |