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