Deleted Added
full compact
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 ---