usr/src/lib/libzfs/common/libzfs_sendrecv.c
changeset 11381 c77e4d2b2e75
parent 11022 63ab26072e41
child 11461 5113530c9d30
equal deleted inserted replaced
11380:73d454719071 11381:c77e4d2b2e75
    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,
    67 } dataref_t;
    69 } dataref_t;
    68 
    70 
    69 typedef struct dedup_entry {
    71 typedef struct dedup_entry {
    70 	struct dedup_entry	*dde_next;
    72 	struct dedup_entry	*dde_next;
    71 	zio_cksum_t dde_chksum;
    73 	zio_cksum_t dde_chksum;
       
    74 	uint64_t dde_prop;
    72 	dataref_t dde_ref;
    75 	dataref_t dde_ref;
    73 } dedup_entry_t;
    76 } dedup_entry_t;
    74 
    77 
    75 #define	MAX_DDT_PHYSMEM_PERCENT		20
    78 #define	MAX_DDT_PHYSMEM_PERCENT		20
    76 #define	SMALLEST_POSSIBLE_MAX_DDT_MB		128
    79 #define	SMALLEST_POSSIBLE_MAX_DDT_MB		128
   106 	return (outlen);
   109 	return (outlen);
   107 }
   110 }
   108 
   111 
   109 static void
   112 static void
   110 ddt_hash_append(libzfs_handle_t *hdl, dedup_table_t *ddt, dedup_entry_t **ddepp,
   113 ddt_hash_append(libzfs_handle_t *hdl, dedup_table_t *ddt, dedup_entry_t **ddepp,
   111     zio_cksum_t *cs, dataref_t *dr)
   114     zio_cksum_t *cs, uint64_t prop, dataref_t *dr)
   112 {
   115 {
   113 	dedup_entry_t	*dde;
   116 	dedup_entry_t	*dde;
   114 
   117 
   115 	if (ddt->cur_ddt_size >= ddt->max_ddt_size) {
   118 	if (ddt->cur_ddt_size >= ddt->max_ddt_size) {
   116 		if (ddt->ddt_full == B_FALSE) {
   119 		if (ddt->ddt_full == B_FALSE) {
   125 	if ((dde = umem_cache_alloc(ddt->ddecache, UMEM_DEFAULT))
   128 	if ((dde = umem_cache_alloc(ddt->ddecache, UMEM_DEFAULT))
   126 	    != NULL) {
   129 	    != NULL) {
   127 		assert(*ddepp == NULL);
   130 		assert(*ddepp == NULL);
   128 		dde->dde_next = NULL;
   131 		dde->dde_next = NULL;
   129 		dde->dde_chksum = *cs;
   132 		dde->dde_chksum = *cs;
       
   133 		dde->dde_prop = prop;
   130 		dde->dde_ref = *dr;
   134 		dde->dde_ref = *dr;
   131 		*ddepp = dde;
   135 		*ddepp = dde;
   132 		ddt->cur_ddt_size += sizeof (dedup_entry_t);
   136 		ddt->cur_ddt_size += sizeof (dedup_entry_t);
   133 		ddt->ddt_count++;
   137 		ddt->ddt_count++;
   134 	}
   138 	}
   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 		}