dmu_objset.c (207626) | dmu_objset.c (209962) |
---|---|
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 --- 5 unchanged lines hidden (view full) --- 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21/* | 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 --- 5 unchanged lines hidden (view full) --- 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21/* |
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. | 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. |
23 * Use is subject to license terms. 24 */ 25 26#include <sys/cred.h> 27#include <sys/zfs_context.h> 28#include <sys/dmu_objset.h> 29#include <sys/dsl_dir.h> 30#include <sys/dsl_dataset.h> --- 128 unchanged lines hidden (view full) --- 159 osi->os_secondary_cache = newval; 160} 161 162void 163dmu_objset_byteswap(void *buf, size_t size) 164{ 165 objset_phys_t *osp = buf; 166 | 23 * Use is subject to license terms. 24 */ 25 26#include <sys/cred.h> 27#include <sys/zfs_context.h> 28#include <sys/dmu_objset.h> 29#include <sys/dsl_dir.h> 30#include <sys/dsl_dataset.h> --- 128 unchanged lines hidden (view full) --- 159 osi->os_secondary_cache = newval; 160} 161 162void 163dmu_objset_byteswap(void *buf, size_t size) 164{ 165 objset_phys_t *osp = buf; 166 |
167 ASSERT(size == sizeof (objset_phys_t)); | 167 ASSERT(size == OBJSET_OLD_PHYS_SIZE || size == sizeof (objset_phys_t)); |
168 dnode_byteswap(&osp->os_meta_dnode); 169 byteswap_uint64_array(&osp->os_zil_header, sizeof (zil_header_t)); 170 osp->os_type = BSWAP_64(osp->os_type); | 168 dnode_byteswap(&osp->os_meta_dnode); 169 byteswap_uint64_array(&osp->os_zil_header, sizeof (zil_header_t)); 170 osp->os_type = BSWAP_64(osp->os_type); |
171 osp->os_flags = BSWAP_64(osp->os_flags); 172 if (size == sizeof (objset_phys_t)) { 173 dnode_byteswap(&osp->os_userused_dnode); 174 dnode_byteswap(&osp->os_groupused_dnode); 175 } |
|
171} 172 173int 174dmu_objset_open_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp, 175 objset_impl_t **osip) 176{ 177 objset_impl_t *osi; 178 int i, err; --- 26 unchanged lines hidden (view full) --- 205 ZIO_PRIORITY_SYNC_READ, ZIO_FLAG_CANFAIL, &aflags, &zb); 206 if (err) { 207 kmem_free(osi, sizeof (objset_impl_t)); 208 /* convert checksum errors into IO errors */ 209 if (err == ECKSUM) 210 err = EIO; 211 return (err); 212 } | 176} 177 178int 179dmu_objset_open_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp, 180 objset_impl_t **osip) 181{ 182 objset_impl_t *osi; 183 int i, err; --- 26 unchanged lines hidden (view full) --- 210 ZIO_PRIORITY_SYNC_READ, ZIO_FLAG_CANFAIL, &aflags, &zb); 211 if (err) { 212 kmem_free(osi, sizeof (objset_impl_t)); 213 /* convert checksum errors into IO errors */ 214 if (err == ECKSUM) 215 err = EIO; 216 return (err); 217 } |
218 219 /* Increase the blocksize if we are permitted. */ 220 if (spa_version(spa) >= SPA_VERSION_USERSPACE && 221 arc_buf_size(osi->os_phys_buf) < sizeof (objset_phys_t)) { 222 arc_buf_t *buf = arc_buf_alloc(spa, 223 sizeof (objset_phys_t), &osi->os_phys_buf, 224 ARC_BUFC_METADATA); 225 bzero(buf->b_data, sizeof (objset_phys_t)); 226 bcopy(osi->os_phys_buf->b_data, buf->b_data, 227 arc_buf_size(osi->os_phys_buf)); 228 (void) arc_buf_remove_ref(osi->os_phys_buf, 229 &osi->os_phys_buf); 230 osi->os_phys_buf = buf; 231 } 232 |
|
213 osi->os_phys = osi->os_phys_buf->b_data; | 233 osi->os_phys = osi->os_phys_buf->b_data; |
234 osi->os_flags = osi->os_phys->os_flags; |
|
214 } else { | 235 } else { |
215 osi->os_phys_buf = arc_buf_alloc(spa, sizeof (objset_phys_t), | 236 int size = spa_version(spa) >= SPA_VERSION_USERSPACE ? 237 sizeof (objset_phys_t) : OBJSET_OLD_PHYS_SIZE; 238 osi->os_phys_buf = arc_buf_alloc(spa, size, |
216 &osi->os_phys_buf, ARC_BUFC_METADATA); 217 osi->os_phys = osi->os_phys_buf->b_data; | 239 &osi->os_phys_buf, ARC_BUFC_METADATA); 240 osi->os_phys = osi->os_phys_buf->b_data; |
218 bzero(osi->os_phys, sizeof (objset_phys_t)); | 241 bzero(osi->os_phys, size); |
219 } 220 221 /* 222 * Note: the changed_cb will be called once before the register 223 * func returns, thus changing the checksum/compression from the 224 * default (fletcher2/off). Snapshots don't need to know about 225 * checksum/compression/copies. 226 */ --- 44 unchanged lines hidden (view full) --- 271 offsetof(dmu_buf_impl_t, db_link)); 272 273 mutex_init(&osi->os_lock, NULL, MUTEX_DEFAULT, NULL); 274 mutex_init(&osi->os_obj_lock, NULL, MUTEX_DEFAULT, NULL); 275 mutex_init(&osi->os_user_ptr_lock, NULL, MUTEX_DEFAULT, NULL); 276 277 osi->os_meta_dnode = dnode_special_open(osi, 278 &osi->os_phys->os_meta_dnode, DMU_META_DNODE_OBJECT); | 242 } 243 244 /* 245 * Note: the changed_cb will be called once before the register 246 * func returns, thus changing the checksum/compression from the 247 * default (fletcher2/off). Snapshots don't need to know about 248 * checksum/compression/copies. 249 */ --- 44 unchanged lines hidden (view full) --- 294 offsetof(dmu_buf_impl_t, db_link)); 295 296 mutex_init(&osi->os_lock, NULL, MUTEX_DEFAULT, NULL); 297 mutex_init(&osi->os_obj_lock, NULL, MUTEX_DEFAULT, NULL); 298 mutex_init(&osi->os_user_ptr_lock, NULL, MUTEX_DEFAULT, NULL); 299 300 osi->os_meta_dnode = dnode_special_open(osi, 301 &osi->os_phys->os_meta_dnode, DMU_META_DNODE_OBJECT); |
302 if (arc_buf_size(osi->os_phys_buf) >= sizeof (objset_phys_t)) { 303 osi->os_userused_dnode = dnode_special_open(osi, 304 &osi->os_phys->os_userused_dnode, DMU_USERUSED_OBJECT); 305 osi->os_groupused_dnode = dnode_special_open(osi, 306 &osi->os_phys->os_groupused_dnode, DMU_GROUPUSED_OBJECT); 307 } |
|
279 280 /* 281 * We should be the only thread trying to do this because we 282 * have ds_opening_lock 283 */ 284 if (ds) { 285 VERIFY(NULL == dsl_dataset_set_user_ptr(ds, osi, 286 dmu_objset_evict)); --- 164 unchanged lines hidden (view full) --- 451 452 /* 453 * We should need only a single pass over the dnode list, since 454 * nothing can be added to the list at this point. 455 */ 456 os.os = osi; 457 (void) dmu_objset_evict_dbufs(&os); 458 | 308 309 /* 310 * We should be the only thread trying to do this because we 311 * have ds_opening_lock 312 */ 313 if (ds) { 314 VERIFY(NULL == dsl_dataset_set_user_ptr(ds, osi, 315 dmu_objset_evict)); --- 164 unchanged lines hidden (view full) --- 480 481 /* 482 * We should need only a single pass over the dnode list, since 483 * nothing can be added to the list at this point. 484 */ 485 os.os = osi; 486 (void) dmu_objset_evict_dbufs(&os); 487 |
459 ASSERT3P(list_head(&osi->os_dnodes), ==, osi->os_meta_dnode); 460 ASSERT3P(list_tail(&osi->os_dnodes), ==, osi->os_meta_dnode); 461 ASSERT3P(list_head(&osi->os_meta_dnode->dn_dbufs), ==, NULL); 462 | |
463 dnode_special_close(osi->os_meta_dnode); | 488 dnode_special_close(osi->os_meta_dnode); |
489 if (osi->os_userused_dnode) { 490 dnode_special_close(osi->os_userused_dnode); 491 dnode_special_close(osi->os_groupused_dnode); 492 } |
|
464 zil_free(osi->os_zil); 465 | 493 zil_free(osi->os_zil); 494 |
495 ASSERT3P(list_head(&osi->os_dnodes), ==, NULL); 496 |
|
466 VERIFY(arc_buf_remove_ref(osi->os_phys_buf, &osi->os_phys_buf) == 1); 467 mutex_destroy(&osi->os_lock); 468 mutex_destroy(&osi->os_obj_lock); 469 mutex_destroy(&osi->os_user_ptr_lock); 470 kmem_free(osi, sizeof (objset_impl_t)); 471} 472 473/* called from dsl for meta-objset */ --- 41 unchanged lines hidden (view full) --- 515 mdn->dn_next_nlevels[tx->tx_txg & TXG_MASK] = 516 mdn->dn_nlevels = levels; 517 } 518 519 ASSERT(type != DMU_OST_NONE); 520 ASSERT(type != DMU_OST_ANY); 521 ASSERT(type < DMU_OST_NUMTYPES); 522 osi->os_phys->os_type = type; | 497 VERIFY(arc_buf_remove_ref(osi->os_phys_buf, &osi->os_phys_buf) == 1); 498 mutex_destroy(&osi->os_lock); 499 mutex_destroy(&osi->os_obj_lock); 500 mutex_destroy(&osi->os_user_ptr_lock); 501 kmem_free(osi, sizeof (objset_impl_t)); 502} 503 504/* called from dsl for meta-objset */ --- 41 unchanged lines hidden (view full) --- 546 mdn->dn_next_nlevels[tx->tx_txg & TXG_MASK] = 547 mdn->dn_nlevels = levels; 548 } 549 550 ASSERT(type != DMU_OST_NONE); 551 ASSERT(type != DMU_OST_ANY); 552 ASSERT(type < DMU_OST_NUMTYPES); 553 osi->os_phys->os_type = type; |
554 if (dmu_objset_userused_enabled(osi)) { 555 osi->os_phys->os_flags |= OBJSET_FLAG_USERACCOUNTING_COMPLETE; 556 osi->os_flags = osi->os_phys->os_flags; 557 } |
|
523 524 dsl_dataset_dirty(ds, tx); 525 526 return (osi); 527} 528 529struct oscarg { 530 void (*userfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); --- 168 unchanged lines hidden (view full) --- 699 return (err); 700} 701 702struct snaparg { 703 dsl_sync_task_group_t *dstg; 704 char *snapname; 705 char failed[MAXPATHLEN]; 706 boolean_t checkperms; | 558 559 dsl_dataset_dirty(ds, tx); 560 561 return (osi); 562} 563 564struct oscarg { 565 void (*userfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); --- 168 unchanged lines hidden (view full) --- 734 return (err); 735} 736 737struct snaparg { 738 dsl_sync_task_group_t *dstg; 739 char *snapname; 740 char failed[MAXPATHLEN]; 741 boolean_t checkperms; |
707 list_t objsets; | 742 nvlist_t *props; |
708}; 709 | 743}; 744 |
710struct osnode { 711 list_node_t node; 712 objset_t *os; 713}; | 745static int 746snapshot_check(void *arg1, void *arg2, dmu_tx_t *tx) 747{ 748 objset_t *os = arg1; 749 struct snaparg *sn = arg2; |
714 | 750 |
751 /* The props have already been checked by zfs_check_userprops(). */ 752 753 return (dsl_dataset_snapshot_check(os->os->os_dsl_dataset, 754 sn->snapname, tx)); 755} 756 757static void 758snapshot_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx) 759{ 760 objset_t *os = arg1; 761 dsl_dataset_t *ds = os->os->os_dsl_dataset; 762 struct snaparg *sn = arg2; 763 764 dsl_dataset_snapshot_sync(ds, sn->snapname, cr, tx); 765 766 if (sn->props) 767 dsl_props_set_sync(ds->ds_prev, sn->props, cr, tx); 768} 769 |
|
715static int 716dmu_objset_snapshot_one(char *name, void *arg) 717{ 718 struct snaparg *sn = arg; 719 objset_t *os; 720 int err; 721 722 (void) strcpy(sn->failed, name); --- 19 unchanged lines hidden (view full) --- 742 743 /* 744 * NB: we need to wait for all in-flight changes to get to disk, 745 * so that we snapshot those changes. zil_suspend does this as 746 * a side effect. 747 */ 748 err = zil_suspend(dmu_objset_zil(os)); 749 if (err == 0) { | 770static int 771dmu_objset_snapshot_one(char *name, void *arg) 772{ 773 struct snaparg *sn = arg; 774 objset_t *os; 775 int err; 776 777 (void) strcpy(sn->failed, name); --- 19 unchanged lines hidden (view full) --- 797 798 /* 799 * NB: we need to wait for all in-flight changes to get to disk, 800 * so that we snapshot those changes. zil_suspend does this as 801 * a side effect. 802 */ 803 err = zil_suspend(dmu_objset_zil(os)); 804 if (err == 0) { |
750 struct osnode *osn; 751 dsl_sync_task_create(sn->dstg, dsl_dataset_snapshot_check, 752 dsl_dataset_snapshot_sync, os->os->os_dsl_dataset, 753 sn->snapname, 3); 754 osn = kmem_alloc(sizeof (struct osnode), KM_SLEEP); 755 osn->os = os; 756 list_insert_tail(&sn->objsets, osn); | 805 dsl_sync_task_create(sn->dstg, snapshot_check, 806 snapshot_sync, os, sn, 3); |
757 } else { 758 dmu_objset_close(os); 759 } 760 761 return (err); 762} 763 764int | 807 } else { 808 dmu_objset_close(os); 809 } 810 811 return (err); 812} 813 814int |
765dmu_objset_snapshot(char *fsname, char *snapname, boolean_t recursive) | 815dmu_objset_snapshot(char *fsname, char *snapname, 816 nvlist_t *props, boolean_t recursive) |
766{ 767 dsl_sync_task_t *dst; | 817{ 818 dsl_sync_task_t *dst; |
768 struct osnode *osn; 769 struct snaparg sn = { 0 }; | 819 struct snaparg sn; |
770 spa_t *spa; 771 int err; 772 773 (void) strcpy(sn.failed, fsname); 774 775 err = spa_open(fsname, &spa, FTAG); 776 if (err) 777 return (err); 778 779 sn.dstg = dsl_sync_task_group_create(spa_get_dsl(spa)); 780 sn.snapname = snapname; | 820 spa_t *spa; 821 int err; 822 823 (void) strcpy(sn.failed, fsname); 824 825 err = spa_open(fsname, &spa, FTAG); 826 if (err) 827 return (err); 828 829 sn.dstg = dsl_sync_task_group_create(spa_get_dsl(spa)); 830 sn.snapname = snapname; |
781 list_create(&sn.objsets, sizeof (struct osnode), 782 offsetof(struct osnode, node)); | 831 sn.props = props; |
783 784 if (recursive) { 785 sn.checkperms = B_TRUE; 786 err = dmu_objset_find(fsname, 787 dmu_objset_snapshot_one, &sn, DS_FIND_CHILDREN); 788 } else { 789 sn.checkperms = B_FALSE; 790 err = dmu_objset_snapshot_one(fsname, &sn); 791 } 792 | 832 833 if (recursive) { 834 sn.checkperms = B_TRUE; 835 err = dmu_objset_find(fsname, 836 dmu_objset_snapshot_one, &sn, DS_FIND_CHILDREN); 837 } else { 838 sn.checkperms = B_FALSE; 839 err = dmu_objset_snapshot_one(fsname, &sn); 840 } 841 |
793 if (err) 794 goto out; | 842 if (err == 0) 843 err = dsl_sync_task_group_wait(sn.dstg); |
795 | 844 |
796 err = dsl_sync_task_group_wait(sn.dstg); 797 | |
798 for (dst = list_head(&sn.dstg->dstg_tasks); dst; 799 dst = list_next(&sn.dstg->dstg_tasks, dst)) { | 845 for (dst = list_head(&sn.dstg->dstg_tasks); dst; 846 dst = list_next(&sn.dstg->dstg_tasks, dst)) { |
800 dsl_dataset_t *ds = dst->dst_arg1; | 847 objset_t *os = dst->dst_arg1; 848 dsl_dataset_t *ds = os->os->os_dsl_dataset; |
801 if (dst->dst_err) 802 dsl_dataset_name(ds, sn.failed); | 849 if (dst->dst_err) 850 dsl_dataset_name(ds, sn.failed); |
851 zil_resume(dmu_objset_zil(os)); 852 dmu_objset_close(os); |
|
803 } 804 | 853 } 854 |
805out: 806 while (osn = list_head(&sn.objsets)) { 807 list_remove(&sn.objsets, osn); 808 zil_resume(dmu_objset_zil(osn->os)); 809 dmu_objset_close(osn->os); 810 kmem_free(osn, sizeof (struct osnode)); 811 } 812 list_destroy(&sn.objsets); 813 | |
814 if (err) 815 (void) strcpy(fsname, sn.failed); 816 dsl_sync_task_group_destroy(sn.dstg); 817 spa_close(spa, FTAG); 818 return (err); 819} 820 821static void | 855 if (err) 856 (void) strcpy(fsname, sn.failed); 857 dsl_sync_task_group_destroy(sn.dstg); 858 spa_close(spa, FTAG); 859 return (err); 860} 861 862static void |
822dmu_objset_sync_dnodes(list_t *list, dmu_tx_t *tx) | 863dmu_objset_sync_dnodes(list_t *list, list_t *newlist, dmu_tx_t *tx) |
823{ 824 dnode_t *dn; 825 826 while (dn = list_head(list)) { 827 ASSERT(dn->dn_object != DMU_META_DNODE_OBJECT); 828 ASSERT(dn->dn_dbuf->db_data_pending); 829 /* | 864{ 865 dnode_t *dn; 866 867 while (dn = list_head(list)) { 868 ASSERT(dn->dn_object != DMU_META_DNODE_OBJECT); 869 ASSERT(dn->dn_dbuf->db_data_pending); 870 /* |
830 * Initialize dn_zio outside dnode_sync() 831 * to accomodate meta-dnode | 871 * Initialize dn_zio outside dnode_sync() because the 872 * meta-dnode needs to set it ouside dnode_sync(). |
832 */ 833 dn->dn_zio = dn->dn_dbuf->db_data_pending->dr_zio; 834 ASSERT(dn->dn_zio); 835 836 ASSERT3U(dn->dn_nlevels, <=, DN_MAX_LEVELS); 837 list_remove(list, dn); | 873 */ 874 dn->dn_zio = dn->dn_dbuf->db_data_pending->dr_zio; 875 ASSERT(dn->dn_zio); 876 877 ASSERT3U(dn->dn_nlevels, <=, DN_MAX_LEVELS); 878 list_remove(list, dn); |
879 880 if (newlist) { 881 (void) dnode_add_ref(dn, newlist); 882 list_insert_tail(newlist, dn); 883 } 884 |
|
838 dnode_sync(dn, tx); 839 } 840} 841 842/* ARGSUSED */ 843static void 844ready(zio_t *zio, arc_buf_t *abuf, void *arg) 845{ 846 blkptr_t *bp = zio->io_bp; 847 blkptr_t *bp_orig = &zio->io_bp_orig; 848 objset_impl_t *os = arg; 849 dnode_phys_t *dnp = &os->os_phys->os_meta_dnode; 850 851 ASSERT(bp == os->os_rootbp); 852 ASSERT(BP_GET_TYPE(bp) == DMU_OT_OBJSET); 853 ASSERT(BP_GET_LEVEL(bp) == 0); 854 855 /* | 885 dnode_sync(dn, tx); 886 } 887} 888 889/* ARGSUSED */ 890static void 891ready(zio_t *zio, arc_buf_t *abuf, void *arg) 892{ 893 blkptr_t *bp = zio->io_bp; 894 blkptr_t *bp_orig = &zio->io_bp_orig; 895 objset_impl_t *os = arg; 896 dnode_phys_t *dnp = &os->os_phys->os_meta_dnode; 897 898 ASSERT(bp == os->os_rootbp); 899 ASSERT(BP_GET_TYPE(bp) == DMU_OT_OBJSET); 900 ASSERT(BP_GET_LEVEL(bp) == 0); 901 902 /* |
856 * Update rootbp fill count. | 903 * Update rootbp fill count: it should be the number of objects 904 * allocated in the object set (not counting the "special" 905 * objects that are stored in the objset_phys_t -- the meta 906 * dnode and user/group accounting objects). |
857 */ | 907 */ |
858 bp->blk_fill = 1; /* count the meta-dnode */ | 908 bp->blk_fill = 0; |
859 for (int i = 0; i < dnp->dn_nblkptr; i++) 860 bp->blk_fill += dnp->dn_blkptr[i].blk_fill; 861 862 if (zio->io_flags & ZIO_FLAG_IO_REWRITE) { 863 ASSERT(DVA_EQUAL(BP_IDENTITY(bp), BP_IDENTITY(bp_orig))); 864 } else { 865 if (zio->io_bp_orig.blk_birth == os->os_synctx->tx_txg) 866 (void) dsl_dataset_block_kill(os->os_dsl_dataset, --- 6 unchanged lines hidden (view full) --- 873void 874dmu_objset_sync(objset_impl_t *os, zio_t *pio, dmu_tx_t *tx) 875{ 876 int txgoff; 877 zbookmark_t zb; 878 writeprops_t wp = { 0 }; 879 zio_t *zio; 880 list_t *list; | 909 for (int i = 0; i < dnp->dn_nblkptr; i++) 910 bp->blk_fill += dnp->dn_blkptr[i].blk_fill; 911 912 if (zio->io_flags & ZIO_FLAG_IO_REWRITE) { 913 ASSERT(DVA_EQUAL(BP_IDENTITY(bp), BP_IDENTITY(bp_orig))); 914 } else { 915 if (zio->io_bp_orig.blk_birth == os->os_synctx->tx_txg) 916 (void) dsl_dataset_block_kill(os->os_dsl_dataset, --- 6 unchanged lines hidden (view full) --- 923void 924dmu_objset_sync(objset_impl_t *os, zio_t *pio, dmu_tx_t *tx) 925{ 926 int txgoff; 927 zbookmark_t zb; 928 writeprops_t wp = { 0 }; 929 zio_t *zio; 930 list_t *list; |
931 list_t *newlist = NULL; |
|
881 dbuf_dirty_record_t *dr; 882 883 dprintf_ds(os->os_dsl_dataset, "txg=%llu\n", tx->tx_txg); 884 885 ASSERT(dmu_tx_is_syncing(tx)); 886 /* XXX the write_done callback should really give us the tx... */ 887 os->os_synctx = tx; 888 --- 21 unchanged lines hidden (view full) --- 910 wp.wp_oscompress = os->os_compress; 911 912 if (BP_IS_OLDER(os->os_rootbp, tx->tx_txg)) { 913 (void) dsl_dataset_block_kill(os->os_dsl_dataset, 914 os->os_rootbp, pio, tx); 915 } 916 917 arc_release(os->os_phys_buf, &os->os_phys_buf); | 932 dbuf_dirty_record_t *dr; 933 934 dprintf_ds(os->os_dsl_dataset, "txg=%llu\n", tx->tx_txg); 935 936 ASSERT(dmu_tx_is_syncing(tx)); 937 /* XXX the write_done callback should really give us the tx... */ 938 os->os_synctx = tx; 939 --- 21 unchanged lines hidden (view full) --- 961 wp.wp_oscompress = os->os_compress; 962 963 if (BP_IS_OLDER(os->os_rootbp, tx->tx_txg)) { 964 (void) dsl_dataset_block_kill(os->os_dsl_dataset, 965 os->os_rootbp, pio, tx); 966 } 967 968 arc_release(os->os_phys_buf, &os->os_phys_buf); |
969 |
|
918 zio = arc_write(pio, os->os_spa, &wp, DMU_OS_IS_L2CACHEABLE(os), 919 tx->tx_txg, os->os_rootbp, os->os_phys_buf, ready, NULL, os, 920 ZIO_PRIORITY_ASYNC_WRITE, ZIO_FLAG_MUSTSUCCEED, &zb); 921 922 /* | 970 zio = arc_write(pio, os->os_spa, &wp, DMU_OS_IS_L2CACHEABLE(os), 971 tx->tx_txg, os->os_rootbp, os->os_phys_buf, ready, NULL, os, 972 ZIO_PRIORITY_ASYNC_WRITE, ZIO_FLAG_MUSTSUCCEED, &zb); 973 974 /* |
923 * Sync meta-dnode - the parent IO for the sync is the root block | 975 * Sync special dnodes - the parent IO for the sync is the root block |
924 */ 925 os->os_meta_dnode->dn_zio = zio; 926 dnode_sync(os->os_meta_dnode, tx); 927 | 976 */ 977 os->os_meta_dnode->dn_zio = zio; 978 dnode_sync(os->os_meta_dnode, tx); 979 |
980 os->os_phys->os_flags = os->os_flags; 981 982 if (os->os_userused_dnode && 983 os->os_userused_dnode->dn_type != DMU_OT_NONE) { 984 os->os_userused_dnode->dn_zio = zio; 985 dnode_sync(os->os_userused_dnode, tx); 986 os->os_groupused_dnode->dn_zio = zio; 987 dnode_sync(os->os_groupused_dnode, tx); 988 } 989 |
|
928 txgoff = tx->tx_txg & TXG_MASK; 929 | 990 txgoff = tx->tx_txg & TXG_MASK; 991 |
930 dmu_objset_sync_dnodes(&os->os_free_dnodes[txgoff], tx); 931 dmu_objset_sync_dnodes(&os->os_dirty_dnodes[txgoff], tx); | 992 if (dmu_objset_userused_enabled(os)) { 993 newlist = &os->os_synced_dnodes; 994 /* 995 * We must create the list here because it uses the 996 * dn_dirty_link[] of this txg. 997 */ 998 list_create(newlist, sizeof (dnode_t), 999 offsetof(dnode_t, dn_dirty_link[txgoff])); 1000 } |
932 | 1001 |
1002 dmu_objset_sync_dnodes(&os->os_free_dnodes[txgoff], newlist, tx); 1003 dmu_objset_sync_dnodes(&os->os_dirty_dnodes[txgoff], newlist, tx); 1004 |
|
933 list = &os->os_meta_dnode->dn_dirty_records[txgoff]; 934 while (dr = list_head(list)) { 935 ASSERT(dr->dr_dbuf->db_level == 0); 936 list_remove(list, dr); 937 if (dr->dr_zio) 938 zio_nowait(dr->dr_zio); 939 } 940 /* 941 * Free intent log blocks up to this tx. 942 */ 943 zil_sync(os->os_zil, tx); 944 os->os_phys->os_zil_header = os->os_zil_header; 945 zio_nowait(zio); 946} 947 | 1005 list = &os->os_meta_dnode->dn_dirty_records[txgoff]; 1006 while (dr = list_head(list)) { 1007 ASSERT(dr->dr_dbuf->db_level == 0); 1008 list_remove(list, dr); 1009 if (dr->dr_zio) 1010 zio_nowait(dr->dr_zio); 1011 } 1012 /* 1013 * Free intent log blocks up to this tx. 1014 */ 1015 zil_sync(os->os_zil, tx); 1016 os->os_phys->os_zil_header = os->os_zil_header; 1017 zio_nowait(zio); 1018} 1019 |
1020static objset_used_cb_t *used_cbs[DMU_OST_NUMTYPES]; 1021 |
|
948void | 1022void |
1023dmu_objset_register_type(dmu_objset_type_t ost, objset_used_cb_t *cb) 1024{ 1025 used_cbs[ost] = cb; 1026} 1027 1028boolean_t 1029dmu_objset_userused_enabled(objset_impl_t *os) 1030{ 1031 return (spa_version(os->os_spa) >= SPA_VERSION_USERSPACE && 1032 used_cbs[os->os_phys->os_type] && 1033 os->os_userused_dnode); 1034} 1035 1036void 1037dmu_objset_do_userquota_callbacks(objset_impl_t *os, dmu_tx_t *tx) 1038{ 1039 dnode_t *dn; 1040 list_t *list = &os->os_synced_dnodes; 1041 static const char zerobuf[DN_MAX_BONUSLEN] = {0}; 1042 1043 ASSERT(list_head(list) == NULL || dmu_objset_userused_enabled(os)); 1044 1045 while (dn = list_head(list)) { 1046 dmu_object_type_t bonustype; 1047 1048 ASSERT(!DMU_OBJECT_IS_SPECIAL(dn->dn_object)); 1049 ASSERT(dn->dn_oldphys); 1050 ASSERT(dn->dn_phys->dn_type == DMU_OT_NONE || 1051 dn->dn_phys->dn_flags & 1052 DNODE_FLAG_USERUSED_ACCOUNTED); 1053 1054 /* Allocate the user/groupused objects if necessary. */ 1055 if (os->os_userused_dnode->dn_type == DMU_OT_NONE) { 1056 VERIFY(0 == zap_create_claim(&os->os, 1057 DMU_USERUSED_OBJECT, 1058 DMU_OT_USERGROUP_USED, DMU_OT_NONE, 0, tx)); 1059 VERIFY(0 == zap_create_claim(&os->os, 1060 DMU_GROUPUSED_OBJECT, 1061 DMU_OT_USERGROUP_USED, DMU_OT_NONE, 0, tx)); 1062 } 1063 1064 /* 1065 * If the object was not previously 1066 * accounted, pretend that it was free. 1067 */ 1068 if (!(dn->dn_oldphys->dn_flags & 1069 DNODE_FLAG_USERUSED_ACCOUNTED)) { 1070 bzero(dn->dn_oldphys, sizeof (dnode_phys_t)); 1071 } 1072 1073 /* 1074 * If the object was freed, use the previous bonustype. 1075 */ 1076 bonustype = dn->dn_phys->dn_bonustype ? 1077 dn->dn_phys->dn_bonustype : dn->dn_oldphys->dn_bonustype; 1078 ASSERT(dn->dn_phys->dn_type != 0 || 1079 (bcmp(DN_BONUS(dn->dn_phys), zerobuf, 1080 DN_MAX_BONUSLEN) == 0 && 1081 DN_USED_BYTES(dn->dn_phys) == 0)); 1082 ASSERT(dn->dn_oldphys->dn_type != 0 || 1083 (bcmp(DN_BONUS(dn->dn_oldphys), zerobuf, 1084 DN_MAX_BONUSLEN) == 0 && 1085 DN_USED_BYTES(dn->dn_oldphys) == 0)); 1086 used_cbs[os->os_phys->os_type](&os->os, bonustype, 1087 DN_BONUS(dn->dn_oldphys), DN_BONUS(dn->dn_phys), 1088 DN_USED_BYTES(dn->dn_oldphys), 1089 DN_USED_BYTES(dn->dn_phys), tx); 1090 1091 /* 1092 * The mutex is needed here for interlock with dnode_allocate. 1093 */ 1094 mutex_enter(&dn->dn_mtx); 1095 zio_buf_free(dn->dn_oldphys, sizeof (dnode_phys_t)); 1096 dn->dn_oldphys = NULL; 1097 mutex_exit(&dn->dn_mtx); 1098 1099 list_remove(list, dn); 1100 dnode_rele(dn, list); 1101 } 1102} 1103 1104boolean_t 1105dmu_objset_userspace_present(objset_t *os) 1106{ 1107 return (os->os->os_phys->os_flags & 1108 OBJSET_FLAG_USERACCOUNTING_COMPLETE); 1109} 1110 1111int 1112dmu_objset_userspace_upgrade(objset_t *os) 1113{ 1114 uint64_t obj; 1115 int err = 0; 1116 1117 if (dmu_objset_userspace_present(os)) 1118 return (0); 1119 if (!dmu_objset_userused_enabled(os->os)) 1120 return (ENOTSUP); 1121 if (dmu_objset_is_snapshot(os)) 1122 return (EINVAL); 1123 1124 /* 1125 * We simply need to mark every object dirty, so that it will be 1126 * synced out and now accounted. If this is called 1127 * concurrently, or if we already did some work before crashing, 1128 * that's fine, since we track each object's accounted state 1129 * independently. 1130 */ 1131 1132 for (obj = 0; err == 0; err = dmu_object_next(os, &obj, FALSE, 0)) { 1133 dmu_tx_t *tx; 1134 dmu_buf_t *db; 1135 int objerr; 1136 1137 if (issig(JUSTLOOKING) && issig(FORREAL)) 1138 return (EINTR); 1139 1140 objerr = dmu_bonus_hold(os, obj, FTAG, &db); 1141 if (objerr) 1142 continue; 1143 tx = dmu_tx_create(os); 1144 dmu_tx_hold_bonus(tx, obj); 1145 objerr = dmu_tx_assign(tx, TXG_WAIT); 1146 if (objerr) { 1147 dmu_tx_abort(tx); 1148 continue; 1149 } 1150 dmu_buf_will_dirty(db, tx); 1151 dmu_buf_rele(db, FTAG); 1152 dmu_tx_commit(tx); 1153 } 1154 1155 os->os->os_flags |= OBJSET_FLAG_USERACCOUNTING_COMPLETE; 1156 txg_wait_synced(dmu_objset_pool(os), 0); 1157 return (0); 1158} 1159 1160void |
|
949dmu_objset_space(objset_t *os, uint64_t *refdbytesp, uint64_t *availbytesp, 950 uint64_t *usedobjsp, uint64_t *availobjsp) 951{ 952 dsl_dataset_space(os->os->os_dsl_dataset, refdbytesp, availbytesp, 953 usedobjsp, availobjsp); 954} 955 956uint64_t --- 16 unchanged lines hidden (view full) --- 973 ASSERT(os->os->os_dsl_dataset || 974 os->os->os_phys->os_type == DMU_OST_META); 975 976 if (os->os->os_dsl_dataset != NULL) 977 dsl_dataset_stats(os->os->os_dsl_dataset, nv); 978 979 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_TYPE, 980 os->os->os_phys->os_type); | 1161dmu_objset_space(objset_t *os, uint64_t *refdbytesp, uint64_t *availbytesp, 1162 uint64_t *usedobjsp, uint64_t *availobjsp) 1163{ 1164 dsl_dataset_space(os->os->os_dsl_dataset, refdbytesp, availbytesp, 1165 usedobjsp, availobjsp); 1166} 1167 1168uint64_t --- 16 unchanged lines hidden (view full) --- 1185 ASSERT(os->os->os_dsl_dataset || 1186 os->os->os_phys->os_type == DMU_OST_META); 1187 1188 if (os->os->os_dsl_dataset != NULL) 1189 dsl_dataset_stats(os->os->os_dsl_dataset, nv); 1190 1191 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_TYPE, 1192 os->os->os_phys->os_type); |
1193 dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USERACCOUNTING, 1194 dmu_objset_userspace_present(os)); |
|
981} 982 983int 984dmu_objset_is_snapshot(objset_t *os) 985{ 986 if (os->os->os_dsl_dataset != NULL) 987 return (dsl_dataset_is_snapshot(os->os->os_dsl_dataset)); 988 else --- 273 unchanged lines hidden --- | 1195} 1196 1197int 1198dmu_objset_is_snapshot(objset_t *os) 1199{ 1200 if (os->os->os_dsl_dataset != NULL) 1201 return (dsl_dataset_is_snapshot(os->os->os_dsl_dataset)); 1202 else --- 273 unchanged lines hidden --- |