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