xref: /freebsd/sys/contrib/openzfs/include/sys/dmu_tx.h (revision b1c1ee4429fcca8f69873a8be66184e68e1b19d7)
1 // SPDX-License-Identifier: CDDL-1.0
2 /*
3  * CDDL HEADER START
4  *
5  * The contents of this file are subject to the terms of the
6  * Common Development and Distribution License (the "License").
7  * You may not use this file except in compliance with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or https://opensource.org/licenses/CDDL-1.0.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 /*
27  * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
28  * Copyright (c) 2025, Klara, Inc.
29  */
30 
31 #ifndef	_SYS_DMU_TX_H
32 #define	_SYS_DMU_TX_H
33 
34 #include <sys/inttypes.h>
35 #include <sys/dmu.h>
36 #include <sys/txg.h>
37 #include <sys/zfs_refcount.h>
38 
39 #ifdef	__cplusplus
40 extern "C" {
41 #endif
42 
43 struct dmu_buf_impl;
44 struct dmu_tx_hold;
45 struct dnode_link;
46 struct dsl_pool;
47 struct dnode;
48 struct dsl_dir;
49 
50 struct dmu_tx {
51 	/*
52 	 * No synchronization is needed because a tx can only be handled
53 	 * by one thread.
54 	 */
55 	list_t tx_holds; /* list of dmu_tx_hold_t */
56 	objset_t *tx_objset;
57 	struct dsl_dir *tx_dir;
58 	struct dsl_pool *tx_pool;
59 	uint64_t tx_txg;
60 	uint64_t tx_lastsnap_txg;
61 	uint64_t tx_lasttried_txg;
62 	txg_handle_t tx_txgh;
63 	void *tx_tempreserve_cookie;
64 	struct dmu_tx_hold *tx_needassign_txh;
65 
66 	/* list of dmu_tx_callback_t on this dmu_tx */
67 	list_t tx_callbacks;
68 
69 	/* placeholder for syncing context, doesn't need specific holds */
70 	boolean_t tx_anyobj;
71 
72 	/* transaction is marked as being a "net free" of space */
73 	boolean_t tx_netfree;
74 
75 	/* time this transaction was created */
76 	hrtime_t tx_start;
77 
78 	/* need to wait for sufficient dirty space */
79 	boolean_t tx_wait_dirty;
80 
81 	/* has this transaction already been delayed? */
82 	boolean_t tx_dirty_delayed;
83 
84 	/* whether dmu_tx_wait() should return on suspend */
85 	boolean_t tx_break_on_suspend;
86 
87 	int tx_err;
88 };
89 
90 enum dmu_tx_hold_type {
91 	THT_NEWOBJECT,
92 	THT_WRITE,
93 	THT_BONUS,
94 	THT_FREE,
95 	THT_ZAP,
96 	THT_SPACE,
97 	THT_SPILL,
98 	THT_CLONE,
99 	THT_APPEND,
100 	THT_NUMTYPES
101 };
102 
103 typedef struct dmu_tx_hold {
104 	dmu_tx_t *txh_tx;
105 	list_node_t txh_node;
106 	struct dnode *txh_dnode;
107 	zfs_refcount_t txh_space_towrite;
108 	zfs_refcount_t txh_memory_tohold;
109 	enum dmu_tx_hold_type txh_type;
110 	uint64_t txh_arg1;
111 	uint64_t txh_arg2;
112 } dmu_tx_hold_t;
113 
114 typedef struct dmu_tx_callback {
115 	list_node_t		dcb_node;    /* linked to tx_callbacks list */
116 	dmu_tx_callback_func_t	*dcb_func;   /* caller function pointer */
117 	void			*dcb_data;   /* caller private data */
118 } dmu_tx_callback_t;
119 
120 /*
121  * Used for dmu tx kstat.
122  */
123 typedef struct dmu_tx_stats {
124 	kstat_named_t dmu_tx_assigned;
125 	kstat_named_t dmu_tx_delay;
126 	kstat_named_t dmu_tx_error;
127 	kstat_named_t dmu_tx_suspended;
128 	kstat_named_t dmu_tx_group;
129 	kstat_named_t dmu_tx_memory_reserve;
130 	kstat_named_t dmu_tx_memory_reclaim;
131 	kstat_named_t dmu_tx_dirty_throttle;
132 	kstat_named_t dmu_tx_dirty_delay;
133 	kstat_named_t dmu_tx_dirty_over_max;
134 	kstat_named_t dmu_tx_dirty_frees_delay;
135 	kstat_named_t dmu_tx_wrlog_delay;
136 	kstat_named_t dmu_tx_quota;
137 } dmu_tx_stats_t;
138 
139 extern dmu_tx_stats_t dmu_tx_stats;
140 
141 #define	DMU_TX_STAT_INCR(stat, val) \
142     atomic_add_64(&dmu_tx_stats.stat.value.ui64, (val));
143 #define	DMU_TX_STAT_BUMP(stat) \
144     DMU_TX_STAT_INCR(stat, 1);
145 
146 /*
147  * These routines are defined in dmu.h, and are called by the user.
148  */
149 dmu_tx_t *dmu_tx_create(objset_t *dd);
150 int dmu_tx_assign(dmu_tx_t *tx, dmu_tx_flag_t flags);
151 void dmu_tx_commit(dmu_tx_t *tx);
152 void dmu_tx_abort(dmu_tx_t *tx);
153 uint64_t dmu_tx_get_txg(dmu_tx_t *tx);
154 struct dsl_pool *dmu_tx_pool(dmu_tx_t *tx);
155 void dmu_tx_wait(dmu_tx_t *tx);
156 
157 /*
158  * These routines are defined in dmu_spa.h, and are called by the SPA.
159  */
160 extern dmu_tx_t *dmu_tx_create_assigned(struct dsl_pool *dp, uint64_t txg);
161 
162 /*
163  * These routines are only called by the DMU.
164  */
165 dmu_tx_t *dmu_tx_create_dd(dsl_dir_t *dd);
166 int dmu_tx_is_syncing(dmu_tx_t *tx);
167 int dmu_tx_private_ok(dmu_tx_t *tx);
168 void dmu_tx_add_new_object(dmu_tx_t *tx, dnode_t *dn);
169 void dmu_tx_dirty_buf(dmu_tx_t *tx, struct dmu_buf_impl *db);
170 void dmu_tx_hold_space(dmu_tx_t *tx, uint64_t space);
171 
172 #ifdef ZFS_DEBUG
173 #define	DMU_TX_DIRTY_BUF(tx, db)	dmu_tx_dirty_buf(tx, db)
174 #else
175 #define	DMU_TX_DIRTY_BUF(tx, db)
176 #endif
177 
178 void dmu_tx_init(void);
179 void dmu_tx_fini(void);
180 
181 #ifdef	__cplusplus
182 }
183 #endif
184 
185 #endif	/* _SYS_DMU_TX_H */
186