Deleted Added
full compact
dnode.c (286545) dnode.c (286575)
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

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

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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
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

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

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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
24 * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
24 */
25
26#include <sys/zfs_context.h>
27#include <sys/dbuf.h>
28#include <sys/dnode.h>
29#include <sys/dmu.h>
30#include <sys/dmu_impl.h>
31#include <sys/dmu_tx.h>

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

400 dn->dn_datablkszsec = size >> SPA_MINBLOCKSHIFT;
401 dn->dn_datablkshift = ISP2(size) ? highbit64(size - 1) : 0;
402}
403
404static dnode_t *
405dnode_create(objset_t *os, dnode_phys_t *dnp, dmu_buf_impl_t *db,
406 uint64_t object, dnode_handle_t *dnh)
407{
25 */
26
27#include <sys/zfs_context.h>
28#include <sys/dbuf.h>
29#include <sys/dnode.h>
30#include <sys/dmu.h>
31#include <sys/dmu_impl.h>
32#include <sys/dmu_tx.h>

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

401 dn->dn_datablkszsec = size >> SPA_MINBLOCKSHIFT;
402 dn->dn_datablkshift = ISP2(size) ? highbit64(size - 1) : 0;
403}
404
405static dnode_t *
406dnode_create(objset_t *os, dnode_phys_t *dnp, dmu_buf_impl_t *db,
407 uint64_t object, dnode_handle_t *dnh)
408{
408 dnode_t *dn = kmem_cache_alloc(dnode_cache, KM_SLEEP);
409 dnode_t *dn;
409
410
411 dn = kmem_cache_alloc(dnode_cache, KM_SLEEP);
410 ASSERT(!POINTER_IS_VALID(dn->dn_objset));
411 dn->dn_moved = 0;
412
413 /*
414 * Defer setting dn_objset until the dnode is ready to be a candidate
415 * for the dnode_move() callback.
416 */
417 dn->dn_object = object;

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

438 dn->dn_have_spill = ((dnp->dn_flags & DNODE_FLAG_SPILL_BLKPTR) != 0);
439 dn->dn_id_flags = 0;
440
441 dmu_zfetch_init(&dn->dn_zfetch, dn);
442
443 ASSERT(DMU_OT_IS_VALID(dn->dn_phys->dn_type));
444
445 mutex_enter(&os->os_lock);
412 ASSERT(!POINTER_IS_VALID(dn->dn_objset));
413 dn->dn_moved = 0;
414
415 /*
416 * Defer setting dn_objset until the dnode is ready to be a candidate
417 * for the dnode_move() callback.
418 */
419 dn->dn_object = object;

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

440 dn->dn_have_spill = ((dnp->dn_flags & DNODE_FLAG_SPILL_BLKPTR) != 0);
441 dn->dn_id_flags = 0;
442
443 dmu_zfetch_init(&dn->dn_zfetch, dn);
444
445 ASSERT(DMU_OT_IS_VALID(dn->dn_phys->dn_type));
446
447 mutex_enter(&os->os_lock);
446 list_insert_head(&os->os_dnodes, dn);
448 if (dnh->dnh_dnode != NULL) {
449 /* Lost the allocation race. */
450 mutex_exit(&os->os_lock);
451 kmem_cache_free(dnode_cache, dn);
452 return (dnh->dnh_dnode);
453 }
454
455 /*
456 * Exclude special dnodes from os_dnodes so an empty os_dnodes
457 * signifies that the special dnodes have no references from
458 * their children (the entries in os_dnodes). This allows
459 * dnode_destroy() to easily determine if the last child has
460 * been removed and then complete eviction of the objset.
461 */
462 if (!DMU_OBJECT_IS_SPECIAL(object))
463 list_insert_head(&os->os_dnodes, dn);
447 membar_producer();
464 membar_producer();
465
448 /*
466 /*
449 * Everything else must be valid before assigning dn_objset makes the
450 * dnode eligible for dnode_move().
467 * Everything else must be valid before assigning dn_objset
468 * makes the dnode eligible for dnode_move().
451 */
452 dn->dn_objset = os;
469 */
470 dn->dn_objset = os;
471
472 dnh->dnh_dnode = dn;
453 mutex_exit(&os->os_lock);
454
455 arc_space_consume(sizeof (dnode_t), ARC_SPACE_OTHER);
456 return (dn);
457}
458
459/*
460 * Caller must be holding the dnode handle, which is released upon return.
461 */
462static void
463dnode_destroy(dnode_t *dn)
464{
465 objset_t *os = dn->dn_objset;
473 mutex_exit(&os->os_lock);
474
475 arc_space_consume(sizeof (dnode_t), ARC_SPACE_OTHER);
476 return (dn);
477}
478
479/*
480 * Caller must be holding the dnode handle, which is released upon return.
481 */
482static void
483dnode_destroy(dnode_t *dn)
484{
485 objset_t *os = dn->dn_objset;
486 boolean_t complete_os_eviction = B_FALSE;
466
467 ASSERT((dn->dn_id_flags & DN_ID_NEW_EXIST) == 0);
468
469 mutex_enter(&os->os_lock);
470 POINTER_INVALIDATE(&dn->dn_objset);
487
488 ASSERT((dn->dn_id_flags & DN_ID_NEW_EXIST) == 0);
489
490 mutex_enter(&os->os_lock);
491 POINTER_INVALIDATE(&dn->dn_objset);
471 list_remove(&os->os_dnodes, dn);
492 if (!DMU_OBJECT_IS_SPECIAL(dn->dn_object)) {
493 list_remove(&os->os_dnodes, dn);
494 complete_os_eviction =
495 list_is_empty(&os->os_dnodes) &&
496 list_link_active(&os->os_evicting_node);
497 }
472 mutex_exit(&os->os_lock);
473
474 /* the dnode can no longer move, so we can release the handle */
475 zrl_remove(&dn->dn_handle->dnh_zrlock);
476
477 dn->dn_allocated_txg = 0;
478 dn->dn_free_txg = 0;
479 dn->dn_assigned_txg = 0;

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

498 dn->dn_newuid = 0;
499 dn->dn_newgid = 0;
500 dn->dn_id_flags = 0;
501 dn->dn_unlisted_l0_blkid = 0;
502
503 dmu_zfetch_rele(&dn->dn_zfetch);
504 kmem_cache_free(dnode_cache, dn);
505 arc_space_return(sizeof (dnode_t), ARC_SPACE_OTHER);
498 mutex_exit(&os->os_lock);
499
500 /* the dnode can no longer move, so we can release the handle */
501 zrl_remove(&dn->dn_handle->dnh_zrlock);
502
503 dn->dn_allocated_txg = 0;
504 dn->dn_free_txg = 0;
505 dn->dn_assigned_txg = 0;

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

524 dn->dn_newuid = 0;
525 dn->dn_newgid = 0;
526 dn->dn_id_flags = 0;
527 dn->dn_unlisted_l0_blkid = 0;
528
529 dmu_zfetch_rele(&dn->dn_zfetch);
530 kmem_cache_free(dnode_cache, dn);
531 arc_space_return(sizeof (dnode_t), ARC_SPACE_OTHER);
532
533 if (complete_os_eviction)
534 dmu_objset_evict_done(os);
506}
507
508void
509dnode_allocate(dnode_t *dn, dmu_object_type_t ot, int blocksize, int ibs,
510 dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
511{
512 int i;
513

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

966 /*
967 * Wait for final references to the dnode to clear. This can
968 * only happen if the arc is asyncronously evicting state that
969 * has a hold on this dnode while we are trying to evict this
970 * dnode.
971 */
972 while (refcount_count(&dn->dn_holds) > 0)
973 delay(1);
535}
536
537void
538dnode_allocate(dnode_t *dn, dmu_object_type_t ot, int blocksize, int ibs,
539 dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
540{
541 int i;
542

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

995 /*
996 * Wait for final references to the dnode to clear. This can
997 * only happen if the arc is asyncronously evicting state that
998 * has a hold on this dnode while we are trying to evict this
999 * dnode.
1000 */
1001 while (refcount_count(&dn->dn_holds) > 0)
1002 delay(1);
1003 ASSERT(dn->dn_dbuf == NULL ||
1004 dmu_buf_get_user(&dn->dn_dbuf->db) == NULL);
974 zrl_add(&dnh->dnh_zrlock);
975 dnode_destroy(dn); /* implicit zrl_remove() */
976 zrl_destroy(&dnh->dnh_zrlock);
977 dnh->dnh_dnode = NULL;
978}
979
1005 zrl_add(&dnh->dnh_zrlock);
1006 dnode_destroy(dn); /* implicit zrl_remove() */
1007 zrl_destroy(&dnh->dnh_zrlock);
1008 dnh->dnh_dnode = NULL;
1009}
1010
980dnode_t *
1011void
981dnode_special_open(objset_t *os, dnode_phys_t *dnp, uint64_t object,
982 dnode_handle_t *dnh)
983{
1012dnode_special_open(objset_t *os, dnode_phys_t *dnp, uint64_t object,
1013 dnode_handle_t *dnh)
1014{
984 dnode_t *dn = dnode_create(os, dnp, NULL, object, dnh);
985 dnh->dnh_dnode = dn;
1015 dnode_t *dn;
1016
1017 dn = dnode_create(os, dnp, NULL, object, dnh);
986 zrl_init(&dnh->dnh_zrlock);
987 DNODE_VERIFY(dn);
1018 zrl_init(&dnh->dnh_zrlock);
1019 DNODE_VERIFY(dn);
988 return (dn);
989}
990
991static void
1020}
1021
1022static void
992dnode_buf_pageout(dmu_buf_t *db, void *arg)
1023dnode_buf_pageout(void *dbu)
993{
1024{
994 dnode_children_t *children_dnodes = arg;
1025 dnode_children_t *children_dnodes = dbu;
995 int i;
1026 int i;
996 int epb = db->db_size >> DNODE_SHIFT;
997
1027
998 ASSERT(epb == children_dnodes->dnc_count);
999
1000 for (i = 0; i < epb; i++) {
1028 for (i = 0; i < children_dnodes->dnc_count; i++) {
1001 dnode_handle_t *dnh = &children_dnodes->dnc_children[i];
1002 dnode_t *dn;
1003
1004 /*
1005 * The dnode handle lock guards against the dnode moving to
1006 * another valid address, so there is no need here to guard
1007 * against changes to or from NULL.
1008 */

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

1022 ASSERT(refcount_is_zero(&dn->dn_holds));
1023 ASSERT(refcount_is_zero(&dn->dn_tx_holds));
1024
1025 dnode_destroy(dn); /* implicit zrl_remove() */
1026 zrl_destroy(&dnh->dnh_zrlock);
1027 dnh->dnh_dnode = NULL;
1028 }
1029 kmem_free(children_dnodes, sizeof (dnode_children_t) +
1029 dnode_handle_t *dnh = &children_dnodes->dnc_children[i];
1030 dnode_t *dn;
1031
1032 /*
1033 * The dnode handle lock guards against the dnode moving to
1034 * another valid address, so there is no need here to guard
1035 * against changes to or from NULL.
1036 */

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

1050 ASSERT(refcount_is_zero(&dn->dn_holds));
1051 ASSERT(refcount_is_zero(&dn->dn_tx_holds));
1052
1053 dnode_destroy(dn); /* implicit zrl_remove() */
1054 zrl_destroy(&dnh->dnh_zrlock);
1055 dnh->dnh_dnode = NULL;
1056 }
1057 kmem_free(children_dnodes, sizeof (dnode_children_t) +
1030 epb * sizeof (dnode_handle_t));
1058 children_dnodes->dnc_count * sizeof (dnode_handle_t));
1031}
1032
1033/*
1034 * errors:
1035 * EINVAL - invalid object number.
1036 * EIO - i/o error.
1037 * succeeds even for free dnodes.
1038 */

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

1112 int i;
1113 dnode_children_t *winner;
1114 children_dnodes = kmem_zalloc(sizeof (dnode_children_t) +
1115 epb * sizeof (dnode_handle_t), KM_SLEEP);
1116 children_dnodes->dnc_count = epb;
1117 dnh = &children_dnodes->dnc_children[0];
1118 for (i = 0; i < epb; i++) {
1119 zrl_init(&dnh[i].dnh_zrlock);
1059}
1060
1061/*
1062 * errors:
1063 * EINVAL - invalid object number.
1064 * EIO - i/o error.
1065 * succeeds even for free dnodes.
1066 */

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

1140 int i;
1141 dnode_children_t *winner;
1142 children_dnodes = kmem_zalloc(sizeof (dnode_children_t) +
1143 epb * sizeof (dnode_handle_t), KM_SLEEP);
1144 children_dnodes->dnc_count = epb;
1145 dnh = &children_dnodes->dnc_children[0];
1146 for (i = 0; i < epb; i++) {
1147 zrl_init(&dnh[i].dnh_zrlock);
1120 dnh[i].dnh_dnode = NULL;
1121 }
1148 }
1122 if (winner = dmu_buf_set_user(&db->db, children_dnodes,
1123 dnode_buf_pageout)) {
1149 dmu_buf_init_user(&children_dnodes->dnc_dbu,
1150 dnode_buf_pageout, NULL);
1151 winner = dmu_buf_set_user(&db->db, &children_dnodes->dnc_dbu);
1152 if (winner != NULL) {
1124
1125 for (i = 0; i < epb; i++) {
1126 zrl_destroy(&dnh[i].dnh_zrlock);
1127 }
1128
1129 kmem_free(children_dnodes, sizeof (dnode_children_t) +
1130 epb * sizeof (dnode_handle_t));
1131 children_dnodes = winner;
1132 }
1133 }
1134 ASSERT(children_dnodes->dnc_count == epb);
1135
1136 dnh = &children_dnodes->dnc_children[idx];
1137 zrl_add(&dnh->dnh_zrlock);
1153
1154 for (i = 0; i < epb; i++) {
1155 zrl_destroy(&dnh[i].dnh_zrlock);
1156 }
1157
1158 kmem_free(children_dnodes, sizeof (dnode_children_t) +
1159 epb * sizeof (dnode_handle_t));
1160 children_dnodes = winner;
1161 }
1162 }
1163 ASSERT(children_dnodes->dnc_count == epb);
1164
1165 dnh = &children_dnodes->dnc_children[idx];
1166 zrl_add(&dnh->dnh_zrlock);
1138 if ((dn = dnh->dnh_dnode) == NULL) {
1167 dn = dnh->dnh_dnode;
1168 if (dn == NULL) {
1139 dnode_phys_t *phys = (dnode_phys_t *)db->db.db_data+idx;
1169 dnode_phys_t *phys = (dnode_phys_t *)db->db.db_data+idx;
1140 dnode_t *winner;
1141
1142 dn = dnode_create(os, phys, db, object, dnh);
1170
1171 dn = dnode_create(os, phys, db, object, dnh);
1143 winner = atomic_cas_ptr(&dnh->dnh_dnode, NULL, dn);
1144 if (winner != NULL) {
1145 zrl_add(&dnh->dnh_zrlock);
1146 dnode_destroy(dn); /* implicit zrl_remove() */
1147 dn = winner;
1148 }
1149 }
1150
1151 mutex_enter(&dn->dn_mtx);
1152 type = dn->dn_type;
1153 if (dn->dn_free_txg ||
1154 ((flag & DNODE_MUST_BE_ALLOCATED) && type == DMU_OT_NONE) ||
1155 ((flag & DNODE_MUST_BE_FREE) &&
1156 (type != DMU_OT_NONE || !refcount_is_zero(&dn->dn_holds)))) {
1157 mutex_exit(&dn->dn_mtx);
1158 zrl_remove(&dnh->dnh_zrlock);
1159 dbuf_rele(db, FTAG);
1160 return (type == DMU_OT_NONE ? ENOENT : EEXIST);
1161 }
1172 }
1173
1174 mutex_enter(&dn->dn_mtx);
1175 type = dn->dn_type;
1176 if (dn->dn_free_txg ||
1177 ((flag & DNODE_MUST_BE_ALLOCATED) && type == DMU_OT_NONE) ||
1178 ((flag & DNODE_MUST_BE_FREE) &&
1179 (type != DMU_OT_NONE || !refcount_is_zero(&dn->dn_holds)))) {
1180 mutex_exit(&dn->dn_mtx);
1181 zrl_remove(&dnh->dnh_zrlock);
1182 dbuf_rele(db, FTAG);
1183 return (type == DMU_OT_NONE ? ENOENT : EEXIST);
1184 }
1162 mutex_exit(&dn->dn_mtx);
1163
1164 if (refcount_add(&dn->dn_holds, tag) == 1)
1165 dbuf_add_ref(db, dnh);
1185 if (refcount_add(&dn->dn_holds, tag) == 1)
1186 dbuf_add_ref(db, dnh);
1187 mutex_exit(&dn->dn_mtx);
1188
1166 /* Now we can rely on the hold to prevent the dnode from moving. */
1167 zrl_remove(&dnh->dnh_zrlock);
1168
1169 DNODE_VERIFY(dn);
1170 ASSERT3P(dn->dn_dbuf, ==, db);
1171 ASSERT3U(dn->dn_object, ==, object);
1172 dbuf_rele(db, FTAG);
1173

--- 849 unchanged lines hidden ---
1189 /* Now we can rely on the hold to prevent the dnode from moving. */
1190 zrl_remove(&dnh->dnh_zrlock);
1191
1192 DNODE_VERIFY(dn);
1193 ASSERT3P(dn->dn_dbuf, ==, db);
1194 ASSERT3U(dn->dn_object, ==, object);
1195 dbuf_rele(db, FTAG);
1196

--- 849 unchanged lines hidden ---