dmu_send.c (4944:96d96f8de974) dmu_send.c (5326:6752aa2bd5bc)
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

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

290 char *buf;
291 uint64_t voff;
292 int buflen; /* number of valid bytes in buf */
293 int bufoff; /* next offset to read */
294 int bufsize; /* amount of memory allocated for buf */
295 zio_cksum_t zc;
296};
297
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

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

290 char *buf;
291 uint64_t voff;
292 int buflen; /* number of valid bytes in buf */
293 int bufoff; /* next offset to read */
294 int bufsize; /* amount of memory allocated for buf */
295 zio_cksum_t zc;
296};
297
298/* ARGSUSED */
299static int
298static int
300replay_incremental_check(void *arg1, void *arg2, dmu_tx_t *tx)
299replay_incremental_check(dsl_dataset_t *ds, struct drr_begin *drrb)
301{
300{
302 dsl_dataset_t *ds = arg1;
303 struct drr_begin *drrb = arg2;
304 const char *snapname;
305 int err;
306 uint64_t val;
307
308 /* must already be a snapshot of this fs */
309 if (ds->ds_phys->ds_prev_snap_obj == 0)
310 return (ENODEV);
311
312 /* most recent snapshot must match fromguid */
313 if (ds->ds_prev->ds_phys->ds_guid != drrb->drr_fromguid)
314 return (ENODEV);
301 const char *snapname;
302 int err;
303 uint64_t val;
304
305 /* must already be a snapshot of this fs */
306 if (ds->ds_phys->ds_prev_snap_obj == 0)
307 return (ENODEV);
308
309 /* most recent snapshot must match fromguid */
310 if (ds->ds_prev->ds_phys->ds_guid != drrb->drr_fromguid)
311 return (ENODEV);
315 /* must not have any changes since most recent snapshot */
316 if (ds->ds_phys->ds_bp.blk_birth >
317 ds->ds_prev->ds_phys->ds_creation_txg)
318 return (ETXTBSY);
319
320 /* new snapshot name must not exist */
321 snapname = strrchr(drrb->drr_toname, '@');
322 if (snapname == NULL)
323 return (EEXIST);
324
325 snapname++;
326 err = zap_lookup(ds->ds_dir->dd_pool->dp_meta_objset,
327 ds->ds_phys->ds_snapnames_zapobj, snapname, 8, 1, &val);
328 if (err == 0)
312
313 /* new snapshot name must not exist */
314 snapname = strrchr(drrb->drr_toname, '@');
315 if (snapname == NULL)
316 return (EEXIST);
317
318 snapname++;
319 err = zap_lookup(ds->ds_dir->dd_pool->dp_meta_objset,
320 ds->ds_phys->ds_snapnames_zapobj, snapname, 8, 1, &val);
321 if (err == 0)
329 return (EEXIST);
322 return (EEXIST);
330 if (err != ENOENT)
323 if (err != ENOENT)
331 return (err);
324 return (err);
332
333 return (0);
334}
335
336/* ARGSUSED */
325
326 return (0);
327}
328
329/* ARGSUSED */
330static int
331replay_offline_incremental_check(void *arg1, void *arg2, dmu_tx_t *tx)
332{
333 dsl_dataset_t *ds = arg1;
334 struct drr_begin *drrb = arg2;
335
336 /* must not have any changes since most recent snapshot */
337 if (dsl_dataset_modified_since_lastsnap(ds))
338 return (ETXTBSY);
339
340 return (replay_incremental_check(ds, drrb));
341}
342
343/* ARGSUSED */
337static void
344static void
338replay_incremental_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx)
345replay_offline_incremental_sync(void *arg1, void *arg2, cred_t *cr,
346 dmu_tx_t *tx)
339{
340 dsl_dataset_t *ds = arg1;
341 dmu_buf_will_dirty(ds->ds_dbuf, tx);
342 ds->ds_phys->ds_flags |= DS_FLAG_INCONSISTENT;
343
344 spa_history_internal_log(LOG_DS_REPLAY_INC_SYNC,
345 ds->ds_dir->dd_pool->dp_spa, tx, cr, "dataset = %lld",
346 ds->ds_phys->ds_dir_obj);

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

397 ds->ds_dir->dd_pool->dp_spa, tx, cr, "dataset = %lld",
398 ds->ds_phys->ds_dir_obj);
399
400 *cp = '@';
401
402 dsl_dataset_close(ds, DS_MODE_EXCLUSIVE, FTAG);
403}
404
347{
348 dsl_dataset_t *ds = arg1;
349 dmu_buf_will_dirty(ds->ds_dbuf, tx);
350 ds->ds_phys->ds_flags |= DS_FLAG_INCONSISTENT;
351
352 spa_history_internal_log(LOG_DS_REPLAY_INC_SYNC,
353 ds->ds_dir->dd_pool->dp_spa, tx, cr, "dataset = %lld",
354 ds->ds_phys->ds_dir_obj);

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

405 ds->ds_dir->dd_pool->dp_spa, tx, cr, "dataset = %lld",
406 ds->ds_phys->ds_dir_obj);
407
408 *cp = '@';
409
410 dsl_dataset_close(ds, DS_MODE_EXCLUSIVE, FTAG);
411}
412
413struct onlineincarg {
414 dsl_dir_t *dd;
415 dsl_dataset_t *ohds;
416 boolean_t force;
417 const char *cosname;
418};
419
420/* ARGSUSED */
405static int
421static int
422replay_online_incremental_check(void *arg1, void *arg2, dmu_tx_t *tx)
423{
424 struct onlineincarg *oia = arg1;
425
426 if (dsl_dataset_modified_since_lastsnap(oia->ohds) && !oia->force)
427 return (ETXTBSY);
428
429 return (replay_incremental_check(oia->ohds, arg2));
430}
431
432/* ARGSUSED */
433static void
434replay_online_incremental_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx)
435{
436 struct onlineincarg *oia = arg1;
437 dsl_dataset_t *ohds = oia->ohds;
438 dsl_dir_t *dd = oia->dd;
439 dsl_dataset_t *ods, *ds;
440 uint64_t dsobj;
441
442 VERIFY(0 == dsl_dataset_open_obj(ohds->ds_dir->dd_pool,
443 ohds->ds_phys->ds_prev_snap_obj, NULL,
444 DS_MODE_STANDARD, FTAG, &ods));
445
446 dsobj = dsl_dataset_create_sync(dd, strrchr(oia->cosname, '/') + 1,
447 ods, tx);
448
449 /* open the temporary clone */
450 VERIFY(0 == dsl_dataset_open_obj(dd->dd_pool, dsobj, NULL,
451 DS_MODE_EXCLUSIVE, FTAG, &ds));
452
453 dmu_buf_will_dirty(ds->ds_dbuf, tx);
454 ds->ds_phys->ds_flags |= DS_FLAG_INCONSISTENT;
455
456 spa_history_internal_log(LOG_DS_REPLAY_INC_SYNC,
457 ds->ds_dir->dd_pool->dp_spa, tx, cr, "dataset = %lld",
458 ds->ds_phys->ds_dir_obj);
459
460 dsl_dataset_close(ds, DS_MODE_EXCLUSIVE, FTAG);
461 dsl_dataset_close(ods, DS_MODE_STANDARD, FTAG);
462}
463
464static int
406replay_end_check(void *arg1, void *arg2, dmu_tx_t *tx)
407{
408 objset_t *os = arg1;
409 struct drr_begin *drrb = arg2;
410 char *snapname;
411
412 /* XXX verify that drr_toname is in dd */
413

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

724 err = dmu_free_range(os, drrf->drr_object,
725 drrf->drr_offset, drrf->drr_length, tx);
726 dmu_tx_commit(tx);
727 return (err);
728}
729
730int
731dmu_recvbackup(char *tosnap, struct drr_begin *drrb, uint64_t *sizep,
465replay_end_check(void *arg1, void *arg2, dmu_tx_t *tx)
466{
467 objset_t *os = arg1;
468 struct drr_begin *drrb = arg2;
469 char *snapname;
470
471 /* XXX verify that drr_toname is in dd */
472

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

783 err = dmu_free_range(os, drrf->drr_object,
784 drrf->drr_offset, drrf->drr_length, tx);
785 dmu_tx_commit(tx);
786 return (err);
787}
788
789int
790dmu_recvbackup(char *tosnap, struct drr_begin *drrb, uint64_t *sizep,
732 boolean_t force, vnode_t *vp, uint64_t voffset)
791 boolean_t force, boolean_t online, vnode_t *vp, uint64_t voffset,
792 char *cosname)
733{
734 struct restorearg ra;
735 dmu_replay_record_t *drr;
736 char *cp;
737 objset_t *os = NULL;
738 zio_cksum_t pzc;
793{
794 struct restorearg ra;
795 dmu_replay_record_t *drr;
796 char *cp;
797 objset_t *os = NULL;
798 zio_cksum_t pzc;
799 char *clonebuf = NULL;
800 size_t len;
739
740 bzero(&ra, sizeof (ra));
741 ra.vp = vp;
742 ra.voff = voffset;
743 ra.bufsize = 1<<20;
744 ra.buf = kmem_alloc(ra.bufsize, KM_SLEEP);
745
746 if (drrb->drr_magic == DMU_BACKUP_MAGIC) {

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

785 strchr(drrb->drr_toname, '@') == NULL) {
786 ra.err = EINVAL;
787 goto out;
788 }
789
790 /*
791 * Process the begin in syncing context.
792 */
801
802 bzero(&ra, sizeof (ra));
803 ra.vp = vp;
804 ra.voff = voffset;
805 ra.bufsize = 1<<20;
806 ra.buf = kmem_alloc(ra.bufsize, KM_SLEEP);
807
808 if (drrb->drr_magic == DMU_BACKUP_MAGIC) {

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

847 strchr(drrb->drr_toname, '@') == NULL) {
848 ra.err = EINVAL;
849 goto out;
850 }
851
852 /*
853 * Process the begin in syncing context.
854 */
793 if (drrb->drr_fromguid) {
794 /* incremental backup */
855 if (drrb->drr_fromguid && !online) {
856 /* offline incremental receive */
857
795 dsl_dataset_t *ds = NULL;
796
797 cp = strchr(tosnap, '@');
798 *cp = '\0';
799 ra.err = dsl_dataset_open(tosnap, DS_MODE_EXCLUSIVE, FTAG, &ds);
800 *cp = '@';
801 if (ra.err)
802 goto out;

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

811 drrb->drr_fromguid) {
812 dsl_dataset_close(ds, DS_MODE_EXCLUSIVE, FTAG);
813 kmem_free(ra.buf, ra.bufsize);
814 return (ENODEV);
815 }
816 (void) dsl_dataset_rollback(ds);
817 }
818 ra.err = dsl_sync_task_do(ds->ds_dir->dd_pool,
858 dsl_dataset_t *ds = NULL;
859
860 cp = strchr(tosnap, '@');
861 *cp = '\0';
862 ra.err = dsl_dataset_open(tosnap, DS_MODE_EXCLUSIVE, FTAG, &ds);
863 *cp = '@';
864 if (ra.err)
865 goto out;

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

874 drrb->drr_fromguid) {
875 dsl_dataset_close(ds, DS_MODE_EXCLUSIVE, FTAG);
876 kmem_free(ra.buf, ra.bufsize);
877 return (ENODEV);
878 }
879 (void) dsl_dataset_rollback(ds);
880 }
881 ra.err = dsl_sync_task_do(ds->ds_dir->dd_pool,
819 replay_incremental_check, replay_incremental_sync,
820 ds, drrb, 1);
882 replay_offline_incremental_check,
883 replay_offline_incremental_sync, ds, drrb, 1);
821 dsl_dataset_close(ds, DS_MODE_EXCLUSIVE, FTAG);
884 dsl_dataset_close(ds, DS_MODE_EXCLUSIVE, FTAG);
885 } else if (drrb->drr_fromguid && online) {
886 /* online incremental receive */
887
888 const char *tail;
889 struct onlineincarg oia = { 0 };
890
891 /*
892 * Get the dsl_dir for the parent of the
893 * temporary clone.
894 */
895 cp = strchr(tosnap, '@');
896 *cp = '\0';
897
898 /* tmp clone is: tonsap + '/' + '%' + "snapX" */
899 len = strlen(tosnap) + 2 + strlen(cp + 1) + 1;
900 clonebuf = kmem_alloc(len, KM_SLEEP);
901 (void) snprintf(clonebuf, len, "%s%c%c%s%c",
902 tosnap, '/', '%', cp + 1, '\0');
903 ra.err = dsl_dir_open(tosnap, FTAG, &oia.dd, &tail);
904 *cp = '@';
905 if (ra.err)
906 goto out;
907
908 /* open the dataset we are logically receiving into */
909 *cp = '\0';
910 ra.err = dsl_dataset_open(tosnap, DS_MODE_STANDARD,
911 FTAG, &oia.ohds);
912 *cp = '@';
913 if (ra.err) {
914 dsl_dir_close(oia.dd, FTAG);
915 goto out;
916 }
917
918 oia.force = force;
919 oia.cosname = clonebuf;
920 ra.err = dsl_sync_task_do(oia.dd->dd_pool,
921 replay_online_incremental_check,
922 replay_online_incremental_sync, &oia, drrb, 5);
923 dsl_dataset_close(oia.ohds, DS_MODE_STANDARD, FTAG);
924 dsl_dir_close(oia.dd, FTAG);
822 } else {
823 /* full backup */
925 } else {
926 /* full backup */
927
824 dsl_dir_t *dd = NULL;
825 const char *tail;
826
827 /* can't restore full backup into topmost fs, for now */
828 if (strrchr(drrb->drr_toname, '/') == NULL) {
829 ra.err = EINVAL;
830 goto out;
831 }

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

849 goto out;
850
851 /*
852 * Open the objset we are modifying.
853 */
854
855 cp = strchr(tosnap, '@');
856 *cp = '\0';
928 dsl_dir_t *dd = NULL;
929 const char *tail;
930
931 /* can't restore full backup into topmost fs, for now */
932 if (strrchr(drrb->drr_toname, '/') == NULL) {
933 ra.err = EINVAL;
934 goto out;
935 }

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

953 goto out;
954
955 /*
956 * Open the objset we are modifying.
957 */
958
959 cp = strchr(tosnap, '@');
960 *cp = '\0';
857 ra.err = dmu_objset_open(tosnap, DMU_OST_ANY,
858 DS_MODE_PRIMARY | DS_MODE_INCONSISTENT, &os);
961 ra.err = dmu_objset_open(clonebuf == NULL ? tosnap : clonebuf,
962 DMU_OST_ANY, DS_MODE_PRIMARY | DS_MODE_INCONSISTENT, &os);
859 *cp = '@';
860 ASSERT3U(ra.err, ==, 0);
861
862 /*
863 * Read records and process them.
864 */
865 pzc = ra.zc;
866 while (ra.err == 0 &&

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

913 * everything before the DRR_END record.
914 */
915 if (drre.drr_checksum.zc_word[0] != 0 &&
916 !ZIO_CHECKSUM_EQUAL(drre.drr_checksum, pzc)) {
917 ra.err = ECKSUM;
918 goto out;
919 }
920
963 *cp = '@';
964 ASSERT3U(ra.err, ==, 0);
965
966 /*
967 * Read records and process them.
968 */
969 pzc = ra.zc;
970 while (ra.err == 0 &&

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

1017 * everything before the DRR_END record.
1018 */
1019 if (drre.drr_checksum.zc_word[0] != 0 &&
1020 !ZIO_CHECKSUM_EQUAL(drre.drr_checksum, pzc)) {
1021 ra.err = ECKSUM;
1022 goto out;
1023 }
1024
921 ra.err = dsl_sync_task_do(dmu_objset_ds(os)->
922 ds_dir->dd_pool, replay_end_check, replay_end_sync,
923 os, drrb, 3);
1025 if (clonebuf == NULL) {
1026 ra.err = dsl_sync_task_do(dmu_objset_ds(os)->
1027 ds_dir->dd_pool, replay_end_check,
1028 replay_end_sync, os, drrb, 3);
1029 }
924 goto out;
925 }
926 default:
927 ra.err = EINVAL;
928 goto out;
929 }
930 pzc = ra.zc;
931 }
932
933out:
1030 goto out;
1031 }
1032 default:
1033 ra.err = EINVAL;
1034 goto out;
1035 }
1036 pzc = ra.zc;
1037 }
1038
1039out:
934 if (os)
1040 if (os) {
1041 if (drrb->drr_fromguid && online && !ra.err)
1042 dmu_objset_name(os, cosname);
935 dmu_objset_close(os);
1043 dmu_objset_close(os);
1044 }
936
937 /*
938 * Make sure we don't rollback/destroy unless we actually
939 * processed the begin properly. 'os' will only be set if this
940 * is the case.
941 */
942 if (ra.err && os && tosnap && strchr(tosnap, '@')) {
943 /*
944 * rollback or destroy what we created, so we don't
945 * leave it in the restoring state.
946 */
947 dsl_dataset_t *ds;
948 int err;
949
950 cp = strchr(tosnap, '@');
951 *cp = '\0';
1045
1046 /*
1047 * Make sure we don't rollback/destroy unless we actually
1048 * processed the begin properly. 'os' will only be set if this
1049 * is the case.
1050 */
1051 if (ra.err && os && tosnap && strchr(tosnap, '@')) {
1052 /*
1053 * rollback or destroy what we created, so we don't
1054 * leave it in the restoring state.
1055 */
1056 dsl_dataset_t *ds;
1057 int err;
1058
1059 cp = strchr(tosnap, '@');
1060 *cp = '\0';
952 err = dsl_dataset_open(tosnap,
1061 err = dsl_dataset_open(clonebuf == NULL ? tosnap : clonebuf,
953 DS_MODE_EXCLUSIVE | DS_MODE_INCONSISTENT,
954 FTAG, &ds);
955 if (err == 0) {
956 txg_wait_synced(ds->ds_dir->dd_pool, 0);
957 if (drrb->drr_fromguid) {
1062 DS_MODE_EXCLUSIVE | DS_MODE_INCONSISTENT,
1063 FTAG, &ds);
1064 if (err == 0) {
1065 txg_wait_synced(ds->ds_dir->dd_pool, 0);
1066 if (drrb->drr_fromguid) {
958 /* incremental: rollback to most recent snap */
959 (void) dsl_dataset_rollback(ds);
960 dsl_dataset_close(ds, DS_MODE_EXCLUSIVE, FTAG);
1067 if (clonebuf != NULL) {
1068 /*
1069 * online incremental: destroy
1070 * the temporarily created clone.
1071 */
1072 dsl_dataset_close(ds, DS_MODE_EXCLUSIVE,
1073 FTAG);
1074 (void) dmu_objset_destroy(clonebuf);
1075 } else {
1076 /*
1077 * offline incremental: rollback to
1078 * most recent snapshot.
1079 */
1080 (void) dsl_dataset_rollback(ds);
1081 dsl_dataset_close(ds, DS_MODE_EXCLUSIVE,
1082 FTAG);
1083 }
961 } else {
962 /* full: destroy whole fs */
963 dsl_dataset_close(ds, DS_MODE_EXCLUSIVE, FTAG);
964 (void) dsl_dataset_destroy(tosnap);
965 }
966 }
967 *cp = '@';
968 }
969
1084 } else {
1085 /* full: destroy whole fs */
1086 dsl_dataset_close(ds, DS_MODE_EXCLUSIVE, FTAG);
1087 (void) dsl_dataset_destroy(tosnap);
1088 }
1089 }
1090 *cp = '@';
1091 }
1092
1093 if (clonebuf != NULL)
1094 kmem_free(clonebuf, len);
970 kmem_free(ra.buf, ra.bufsize);
971 if (sizep)
972 *sizep = ra.voff;
973 return (ra.err);
974}
1095 kmem_free(ra.buf, ra.bufsize);
1096 if (sizep)
1097 *sizep = ra.voff;
1098 return (ra.err);
1099}
1100
1101int
1102dmu_replay_end_snapshot(char *name, struct drr_begin *drrb)
1103{
1104 objset_t *os;
1105 int err;
1106
1107 err = dmu_objset_open(name, DMU_OST_ZFS, DS_MODE_STANDARD, &os);
1108 if (err)
1109 return (err);
1110
1111 err = dsl_sync_task_do(dmu_objset_ds(os)->ds_dir->dd_pool,
1112 replay_end_check, replay_end_sync, os, drrb, 3);
1113 dmu_objset_close(os);
1114 return (err);
1115}