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
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
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 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2012, 2017 by Delphix. All rights reserved.
25 * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
26 */
27
28 #include <sys/zfs_context.h>
29 #include <sys/dbuf.h>
30 #include <sys/dnode.h>
31 #include <sys/dmu.h>
32 #include <sys/dmu_tx.h>
33 #include <sys/dmu_objset.h>
34 #include <sys/dsl_dataset.h>
35 #include <sys/spa.h>
36 #include <sys/range_tree.h>
37 #include <sys/zfeature.h>
38
39 static void
40 dnode_increase_indirection(dnode_t *dn, dmu_tx_t *tx)
41 {
42 dmu_buf_impl_t *db;
43 int txgoff = tx->tx_txg & TXG_MASK;
380 typedef struct dnode_sync_free_range_arg {
381 dnode_t *dsfra_dnode;
382 dmu_tx_t *dsfra_tx;
383 } dnode_sync_free_range_arg_t;
384
385 static void
386 dnode_sync_free_range(void *arg, uint64_t blkid, uint64_t nblks)
387 {
388 dnode_sync_free_range_arg_t *dsfra = arg;
389 dnode_t *dn = dsfra->dsfra_dnode;
390
391 mutex_exit(&dn->dn_mtx);
392 dnode_sync_free_range_impl(dn, blkid, nblks, dsfra->dsfra_tx);
393 mutex_enter(&dn->dn_mtx);
394 }
395
396 /*
397 * Try to kick all the dnode's dbufs out of the cache...
398 */
399 void
400 dnode_evict_dbufs(dnode_t *dn)
401 {
402 dmu_buf_impl_t db_marker;
403 dmu_buf_impl_t *db, *db_next;
404
405 mutex_enter(&dn->dn_dbufs_mtx);
406 for (db = avl_first(&dn->dn_dbufs); db != NULL; db = db_next) {
407
408 #ifdef DEBUG
409 DB_DNODE_ENTER(db);
410 ASSERT3P(DB_DNODE(db), ==, dn);
411 DB_DNODE_EXIT(db);
412 #endif /* DEBUG */
413
414 mutex_enter(&db->db_mtx);
415 if (db->db_state != DB_EVICTING &&
416 refcount_is_zero(&db->db_holds)) {
417 db_marker.db_level = db->db_level;
418 db_marker.db_blkid = db->db_blkid;
419 db_marker.db_state = DB_SEARCH;
420 avl_insert_here(&dn->dn_dbufs, &db_marker, db,
421 AVL_BEFORE);
422
423 dbuf_destroy(db);
424
425 db_next = AVL_NEXT(&dn->dn_dbufs, &db_marker);
426 avl_remove(&dn->dn_dbufs, &db_marker);
427 } else {
428 db->db_pending_evict = TRUE;
429 mutex_exit(&db->db_mtx);
430 db_next = AVL_NEXT(&dn->dn_dbufs, db);
431 }
432 }
433 mutex_exit(&dn->dn_dbufs_mtx);
434
480 kmem_free(dr, sizeof (dbuf_dirty_record_t));
481 dbuf_rele_and_unlock(db, (void *)(uintptr_t)txg);
482 }
483 }
484
485 static void
486 dnode_sync_free(dnode_t *dn, dmu_tx_t *tx)
487 {
488 int txgoff = tx->tx_txg & TXG_MASK;
489
490 ASSERT(dmu_tx_is_syncing(tx));
491
492 /*
493 * Our contents should have been freed in dnode_sync() by the
494 * free range record inserted by the caller of dnode_free().
495 */
496 ASSERT0(DN_USED_BYTES(dn->dn_phys));
497 ASSERT(BP_IS_HOLE(dn->dn_phys->dn_blkptr));
498
499 dnode_undirty_dbufs(&dn->dn_dirty_records[txgoff]);
500 dnode_evict_dbufs(dn);
501
502 /*
503 * XXX - It would be nice to assert this, but we may still
504 * have residual holds from async evictions from the arc...
505 *
506 * zfs_obj_to_path() also depends on this being
507 * commented out.
508 *
509 * ASSERT3U(refcount_count(&dn->dn_holds), ==, 1);
510 */
511
512 /* Undirty next bits */
513 dn->dn_next_nlevels[txgoff] = 0;
514 dn->dn_next_indblkshift[txgoff] = 0;
515 dn->dn_next_blksz[txgoff] = 0;
516
517 /* ASSERT(blkptrs are zero); */
518 ASSERT(dn->dn_phys->dn_type != DMU_OT_NONE);
519 ASSERT(dn->dn_type != DMU_OT_NONE);
520
|
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
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
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 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2014 Nexenta Systems, Inc. All rights reserved.
25 * Copyright (c) 2012, 2017 by Delphix. All rights reserved.
26 * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
27 */
28
29 #include <sys/zfs_context.h>
30 #include <sys/dbuf.h>
31 #include <sys/dnode.h>
32 #include <sys/dmu.h>
33 #include <sys/dmu_tx.h>
34 #include <sys/dmu_objset.h>
35 #include <sys/dsl_dataset.h>
36 #include <sys/spa.h>
37 #include <sys/range_tree.h>
38 #include <sys/zfeature.h>
39
40 static void
41 dnode_increase_indirection(dnode_t *dn, dmu_tx_t *tx)
42 {
43 dmu_buf_impl_t *db;
44 int txgoff = tx->tx_txg & TXG_MASK;
381 typedef struct dnode_sync_free_range_arg {
382 dnode_t *dsfra_dnode;
383 dmu_tx_t *dsfra_tx;
384 } dnode_sync_free_range_arg_t;
385
386 static void
387 dnode_sync_free_range(void *arg, uint64_t blkid, uint64_t nblks)
388 {
389 dnode_sync_free_range_arg_t *dsfra = arg;
390 dnode_t *dn = dsfra->dsfra_dnode;
391
392 mutex_exit(&dn->dn_mtx);
393 dnode_sync_free_range_impl(dn, blkid, nblks, dsfra->dsfra_tx);
394 mutex_enter(&dn->dn_mtx);
395 }
396
397 /*
398 * Try to kick all the dnode's dbufs out of the cache...
399 */
400 void
401 dnode_evict_dbufs(dnode_t *dn, int level)
402 {
403 dmu_buf_impl_t db_marker;
404 dmu_buf_impl_t *db, *db_next;
405
406 mutex_enter(&dn->dn_dbufs_mtx);
407 for (db = avl_first(&dn->dn_dbufs); db != NULL; db = db_next) {
408
409 #ifdef DEBUG
410 DB_DNODE_ENTER(db);
411 ASSERT3P(DB_DNODE(db), ==, dn);
412 DB_DNODE_EXIT(db);
413 #endif /* DEBUG */
414
415 mutex_enter(&db->db_mtx);
416 if (level != DBUF_EVICT_ALL && db->db_level != level) {
417 mutex_exit(&db->db_mtx);
418 db_next = AVL_NEXT(&dn->dn_dbufs, db);
419 continue;
420 }
421
422 if (db->db_state != DB_EVICTING &&
423 refcount_is_zero(&db->db_holds)) {
424 db_marker.db_level = db->db_level;
425 db_marker.db_blkid = db->db_blkid;
426 db_marker.db_state = DB_SEARCH;
427 avl_insert_here(&dn->dn_dbufs, &db_marker, db,
428 AVL_BEFORE);
429
430 dbuf_destroy(db);
431
432 db_next = AVL_NEXT(&dn->dn_dbufs, &db_marker);
433 avl_remove(&dn->dn_dbufs, &db_marker);
434 } else {
435 db->db_pending_evict = TRUE;
436 mutex_exit(&db->db_mtx);
437 db_next = AVL_NEXT(&dn->dn_dbufs, db);
438 }
439 }
440 mutex_exit(&dn->dn_dbufs_mtx);
441
487 kmem_free(dr, sizeof (dbuf_dirty_record_t));
488 dbuf_rele_and_unlock(db, (void *)(uintptr_t)txg);
489 }
490 }
491
492 static void
493 dnode_sync_free(dnode_t *dn, dmu_tx_t *tx)
494 {
495 int txgoff = tx->tx_txg & TXG_MASK;
496
497 ASSERT(dmu_tx_is_syncing(tx));
498
499 /*
500 * Our contents should have been freed in dnode_sync() by the
501 * free range record inserted by the caller of dnode_free().
502 */
503 ASSERT0(DN_USED_BYTES(dn->dn_phys));
504 ASSERT(BP_IS_HOLE(dn->dn_phys->dn_blkptr));
505
506 dnode_undirty_dbufs(&dn->dn_dirty_records[txgoff]);
507 dnode_evict_dbufs(dn, DBUF_EVICT_ALL);
508 ASSERT(avl_is_empty(&dn->dn_dbufs));
509
510 /*
511 * XXX - It would be nice to assert this, but we may still
512 * have residual holds from async evictions from the arc...
513 *
514 * zfs_obj_to_path() also depends on this being
515 * commented out.
516 *
517 * ASSERT3U(refcount_count(&dn->dn_holds), ==, 1);
518 */
519
520 /* Undirty next bits */
521 dn->dn_next_nlevels[txgoff] = 0;
522 dn->dn_next_indblkshift[txgoff] = 0;
523 dn->dn_next_blksz[txgoff] = 0;
524
525 /* ASSERT(blkptrs are zero); */
526 ASSERT(dn->dn_phys->dn_type != DMU_OT_NONE);
527 ASSERT(dn->dn_type != DMU_OT_NONE);
528
|