Commit | Line | Data |
---|---|---|
703720e4 | 1 | /* |
506bd6d1 | 2 | * Copyright (c) 2011-2015 The DragonFly Project. All rights reserved. |
703720e4 MD |
3 | * |
4 | * This code is derived from software contributed to The DragonFly Project | |
5 | * by Matthew Dillon <dillon@dragonflybsd.org> | |
6 | * by Venkatesh Srinivas <vsrinivas@dragonflybsd.org> | |
7 | * | |
8 | * Redistribution and use in source and binary forms, with or without | |
9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | |
11 | * | |
12 | * 1. Redistributions of source code must retain the above copyright | |
13 | * notice, this list of conditions and the following disclaimer. | |
14 | * 2. Redistributions in binary form must reproduce the above copyright | |
15 | * notice, this list of conditions and the following disclaimer in | |
16 | * the documentation and/or other materials provided with the | |
17 | * distribution. | |
18 | * 3. Neither the name of The DragonFly Project nor the names of its | |
19 | * contributors may be used to endorse or promote products derived | |
20 | * from this software without specific, prior written permission. | |
21 | * | |
22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
23 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
24 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
25 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
26 | * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
27 | * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
28 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
29 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
30 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
31 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |
32 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
33 | * SUCH DAMAGE. | |
34 | */ | |
35 | ||
36 | /* | |
278ab2b2 MD |
37 | * HAMMER2 IN-MEMORY CACHE OF MEDIA STRUCTURES |
38 | * | |
703720e4 MD |
39 | * This header file contains structures used internally by the HAMMER2 |
40 | * implementation. See hammer2_disk.h for on-disk structures. | |
278ab2b2 MD |
41 | * |
42 | * There is an in-memory representation of all on-media data structure. | |
da6f36f4 MD |
43 | * Almost everything is represented by a hammer2_chain structure in-memory. |
44 | * Other higher-level structures typically map to chains. | |
278ab2b2 MD |
45 | * |
46 | * A great deal of data is accessed simply via its buffer cache buffer, | |
da6f36f4 MD |
47 | * which is mapped for the duration of the chain's lock. Hammer2 must |
48 | * implement its own buffer cache layer on top of the system layer to | |
49 | * allow for different threads to lock different sub-block-sized buffers. | |
278ab2b2 MD |
50 | * |
51 | * When modifications are made to a chain a new filesystem block must be | |
da6f36f4 MD |
52 | * allocated. Multiple modifications do not typically allocate new blocks |
53 | * until the current block has been flushed. Flushes do not block the | |
54 | * front-end unless the front-end operation crosses the current inode being | |
55 | * flushed. | |
278ab2b2 MD |
56 | * |
57 | * The in-memory representation may remain cached (for example in order to | |
58 | * placemark clustering locks) even after the related data has been | |
59 | * detached. | |
703720e4 MD |
60 | */ |
61 | ||
62 | #ifndef _VFS_HAMMER2_HAMMER2_H_ | |
63 | #define _VFS_HAMMER2_HAMMER2_H_ | |
64 | ||
65 | #include <sys/param.h> | |
66 | #include <sys/types.h> | |
67 | #include <sys/kernel.h> | |
68 | #include <sys/conf.h> | |
69 | #include <sys/systm.h> | |
70 | #include <sys/tree.h> | |
71 | #include <sys/malloc.h> | |
72 | #include <sys/mount.h> | |
73 | #include <sys/vnode.h> | |
74 | #include <sys/proc.h> | |
75 | #include <sys/mountctl.h> | |
76 | #include <sys/priv.h> | |
77 | #include <sys/stat.h> | |
46558838 | 78 | #include <sys/thread.h> |
703720e4 MD |
79 | #include <sys/globaldata.h> |
80 | #include <sys/lockf.h> | |
81 | #include <sys/buf.h> | |
82 | #include <sys/queue.h> | |
83 | #include <sys/limits.h> | |
5bc5bca2 | 84 | #include <sys/dmsg.h> |
355d67fc | 85 | #include <sys/mutex.h> |
278ab2b2 MD |
86 | #include <sys/kern_syscall.h> |
87 | ||
94491fa0 | 88 | #include <sys/signal2.h> |
278ab2b2 | 89 | #include <sys/buf2.h> |
355d67fc | 90 | #include <sys/mutex2.h> |
5ceaaa82 | 91 | #include <sys/thread2.h> |
703720e4 MD |
92 | |
93 | #include "hammer2_disk.h" | |
94 | #include "hammer2_mount.h" | |
2910a90c | 95 | #include "hammer2_ioctl.h" |
703720e4 | 96 | |
bca9f8e6 MD |
97 | struct hammer2_io; |
98 | struct hammer2_iocb; | |
5c23d7f1 | 99 | struct hammer2_chain; |
278ab2b2 | 100 | struct hammer2_cluster; |
703720e4 | 101 | struct hammer2_inode; |
506bd6d1 MD |
102 | struct hammer2_dev; |
103 | struct hammer2_pfs; | |
10c86c4e | 104 | struct hammer2_span; |
26bf1a36 MD |
105 | struct hammer2_state; |
106 | struct hammer2_msg; | |
2ed4fece | 107 | struct hammer2_thread; |
c847e838 | 108 | union hammer2_xop; |
703720e4 | 109 | |
94491fa0 MD |
110 | /* |
111 | * Mutex and lock shims. Hammer2 requires support for asynchronous and | |
112 | * abortable locks, and both exclusive and shared spinlocks. Normal | |
113 | * synchronous non-abortable locks can be substituted for spinlocks. | |
114 | */ | |
115 | typedef mtx_t hammer2_mtx_t; | |
116 | typedef mtx_link_t hammer2_mtx_link_t; | |
117 | typedef mtx_state_t hammer2_mtx_state_t; | |
118 | ||
119 | typedef struct spinlock hammer2_spin_t; | |
120 | ||
121 | #define hammer2_mtx_ex mtx_lock_ex_quick | |
122 | #define hammer2_mtx_sh mtx_lock_sh_quick | |
2efe493b | 123 | #define hammer2_mtx_sh_again mtx_lock_sh_again |
94491fa0 | 124 | #define hammer2_mtx_unlock mtx_unlock |
2efe493b | 125 | #define hammer2_mtx_downgrade mtx_downgrade |
94491fa0 MD |
126 | #define hammer2_mtx_owned mtx_owned |
127 | #define hammer2_mtx_init mtx_init | |
128 | #define hammer2_mtx_temp_release mtx_lock_temp_release | |
129 | #define hammer2_mtx_temp_restore mtx_lock_temp_restore | |
130 | #define hammer2_mtx_refs mtx_lockrefs | |
131 | ||
132 | #define hammer2_spin_init spin_init | |
133 | #define hammer2_spin_sh spin_lock_shared | |
134 | #define hammer2_spin_ex spin_lock | |
135 | #define hammer2_spin_unsh spin_unlock_shared | |
136 | #define hammer2_spin_unex spin_unlock | |
137 | ||
c847e838 MD |
138 | TAILQ_HEAD(hammer2_xop_list, hammer2_xop_head); |
139 | ||
140 | typedef struct hammer2_xop_list hammer2_xop_list_t; | |
141 | ||
142 | ||
94491fa0 MD |
143 | /* |
144 | * General lock support | |
145 | */ | |
146 | static __inline | |
147 | int | |
148 | hammer2_mtx_upgrade(hammer2_mtx_t *mtx) | |
149 | { | |
150 | int wasexclusive; | |
151 | ||
152 | if (mtx_islocked_ex(mtx)) { | |
153 | wasexclusive = 1; | |
154 | } else { | |
155 | mtx_unlock(mtx); | |
156 | mtx_lock_ex_quick(mtx); | |
157 | wasexclusive = 0; | |
158 | } | |
159 | return wasexclusive; | |
160 | } | |
161 | ||
50456506 MD |
162 | /* |
163 | * The xid tracks internal transactional updates. | |
164 | * | |
165 | * XXX fix-me, really needs to be 64-bits | |
166 | */ | |
167 | typedef uint32_t hammer2_xid_t; | |
168 | ||
169 | #define HAMMER2_XID_MIN 0x00000000U | |
170 | #define HAMMER2_XID_MAX 0x7FFFFFFFU | |
171 | ||
50e4f8f4 | 172 | /* |
1897c66e MD |
173 | * The chain structure tracks a portion of the media topology from the |
174 | * root (volume) down. Chains represent volumes, inodes, indirect blocks, | |
175 | * data blocks, and freemap nodes and leafs. | |
176 | * | |
da6f36f4 MD |
177 | * The chain structure utilizes a simple singly-homed topology and the |
178 | * chain's in-memory topology will move around as the chains do, due mainly | |
179 | * to renames and indirect block creation. | |
180 | * | |
181 | * Block Table Updates | |
1897c66e | 182 | * |
da6f36f4 MD |
183 | * Block table updates for insertions and updates are delayed until the |
184 | * flush. This allows us to avoid having to modify the parent chain | |
185 | * all the way to the root. | |
1897c66e | 186 | * |
da6f36f4 MD |
187 | * Block table deletions are performed immediately (modifying the parent |
188 | * in the process) because the flush code uses the chain structure to | |
189 | * track delayed updates and the chain will be (likely) gone or moved to | |
190 | * another location in the topology after a deletion. | |
8138a154 | 191 | * |
da6f36f4 MD |
192 | * A prior iteration of the code tried to keep the relationship intact |
193 | * on deletes by doing a delete-duplicate operation on the chain, but | |
194 | * it added way too much complexity to the codebase. | |
8138a154 | 195 | * |
da6f36f4 | 196 | * Flush Synchronization |
8138a154 | 197 | * |
da6f36f4 MD |
198 | * The flush code must flush modified chains bottom-up. Because chain |
199 | * structures can shift around and are NOT topologically stable, | |
200 | * modified chains are independently indexed for the flush. As the flush | |
201 | * runs it modifies (or further modifies) and updates the parents, | |
202 | * propagating the flush all the way to the volume root. | |
5c23d7f1 | 203 | * |
da6f36f4 MD |
204 | * Modifying front-end operations can occur during a flush but will block |
205 | * in two cases: (1) when the front-end tries to operate on the inode | |
206 | * currently in the midst of being flushed and (2) if the front-end | |
207 | * crosses an inode currently being flushed (such as during a rename). | |
208 | * So, for example, if you rename directory "x" to "a/b/c/d/e/f/g/x" and | |
209 | * the flusher is currently working on "a/b/c", the rename will block | |
210 | * temporarily in order to ensure that "x" exists in one place or the | |
211 | * other. | |
0dea3156 | 212 | * |
da6f36f4 MD |
213 | * Meta-data statistics are updated by the flusher. The front-end will |
214 | * make estimates but meta-data must be fully synchronized only during a | |
215 | * flush in order to ensure that it remains correct across a crash. | |
0dea3156 | 216 | * |
da6f36f4 MD |
217 | * Multiple flush synchronizations can theoretically be in-flight at the |
218 | * same time but the implementation is not coded to handle the case and | |
219 | * currently serializes them. | |
0dea3156 | 220 | * |
da6f36f4 | 221 | * Snapshots: |
0dea3156 | 222 | * |
da6f36f4 MD |
223 | * Snapshots currently require the subdirectory tree being snapshotted |
224 | * to be flushed. The snapshot then creates a new super-root inode which | |
225 | * copies the flushed blockdata of the directory or file that was | |
226 | * snapshotted. | |
0dea3156 | 227 | * |
da6f36f4 | 228 | * RBTREE NOTES: |
0dea3156 | 229 | * |
da6f36f4 MD |
230 | * - Note that the radix tree runs in powers of 2 only so sub-trees |
231 | * cannot straddle edges. | |
50e4f8f4 | 232 | */ |
ecc33e71 | 233 | RB_HEAD(hammer2_chain_tree, hammer2_chain); |
da6f36f4 | 234 | TAILQ_HEAD(h2_flush_list, hammer2_chain); |
1897c66e | 235 | TAILQ_HEAD(h2_core_list, hammer2_chain); |
bca9f8e6 | 236 | TAILQ_HEAD(h2_iocb_list, hammer2_iocb); |
1897c66e | 237 | |
8138a154 MD |
238 | #define CHAIN_CORE_DELETE_BMAP_ENTRIES \ |
239 | (HAMMER2_PBUFSIZE / sizeof(hammer2_blockref_t) / sizeof(uint32_t)) | |
5c23d7f1 | 240 | |
f1c7c224 MD |
241 | /* |
242 | * Core topology for chain (embedded in chain). Protected by a spinlock. | |
243 | */ | |
0dea3156 | 244 | struct hammer2_chain_core { |
94491fa0 | 245 | hammer2_spin_t spin; |
da6f36f4 | 246 | struct hammer2_chain_tree rbtree; /* sub-chains */ |
c057466c | 247 | int live_zero; /* blockref array opt */ |
1897c66e | 248 | u_int live_count; /* live (not deleted) chains in tree */ |
8138a154 | 249 | u_int chain_count; /* live + deleted chains under core */ |
a4dc31e0 | 250 | int generation; /* generation number (inserts only) */ |
0dea3156 MD |
251 | }; |
252 | ||
253 | typedef struct hammer2_chain_core hammer2_chain_core_t; | |
254 | ||
bca9f8e6 MD |
255 | RB_HEAD(hammer2_io_tree, hammer2_io); |
256 | ||
fdf62707 | 257 | /* |
bca9f8e6 | 258 | * IOCB - IO callback (into chain, cluster, or manual request) |
fdf62707 | 259 | */ |
bca9f8e6 MD |
260 | struct hammer2_iocb { |
261 | TAILQ_ENTRY(hammer2_iocb) entry; | |
262 | void (*callback)(struct hammer2_iocb *iocb); | |
263 | struct hammer2_io *dio; | |
264 | struct hammer2_cluster *cluster; | |
265 | struct hammer2_chain *chain; | |
266 | void *ptr; | |
267 | off_t lbase; | |
268 | int lsize; | |
269 | uint32_t flags; | |
270 | int error; | |
271 | }; | |
272 | ||
273 | typedef struct hammer2_iocb hammer2_iocb_t; | |
274 | ||
275 | #define HAMMER2_IOCB_INTERLOCK 0x00000001 | |
276 | #define HAMMER2_IOCB_ONQ 0x00000002 | |
277 | #define HAMMER2_IOCB_DONE 0x00000004 | |
278 | #define HAMMER2_IOCB_INPROG 0x00000008 | |
3148f677 | 279 | #define HAMMER2_IOCB_UNUSED10 0x00000010 |
bca9f8e6 MD |
280 | #define HAMMER2_IOCB_QUICK 0x00010000 |
281 | #define HAMMER2_IOCB_ZERO 0x00020000 | |
282 | #define HAMMER2_IOCB_READ 0x00040000 | |
283 | #define HAMMER2_IOCB_WAKEUP 0x00080000 | |
fdf62707 | 284 | |
bca9f8e6 MD |
285 | /* |
286 | * DIO - Management structure wrapping system buffer cache. | |
287 | * | |
288 | * Used for multiple purposes including concurrent management | |
289 | * if small requests by chains into larger DIOs. | |
290 | */ | |
fdf62707 | 291 | struct hammer2_io { |
0924b3f8 | 292 | RB_ENTRY(hammer2_io) rbnode; /* indexed by device offset */ |
bca9f8e6 | 293 | struct h2_iocb_list iocbq; |
fdf62707 | 294 | struct spinlock spin; |
506bd6d1 | 295 | struct hammer2_dev *hmp; |
fdf62707 | 296 | struct buf *bp; |
fdf62707 MD |
297 | off_t pbase; |
298 | int psize; | |
fdf62707 | 299 | int refs; |
0924b3f8 | 300 | int act; /* activity */ |
fdf62707 MD |
301 | }; |
302 | ||
303 | typedef struct hammer2_io hammer2_io_t; | |
304 | ||
bca9f8e6 | 305 | #define HAMMER2_DIO_INPROG 0x80000000 /* bio in progress */ |
3148f677 | 306 | #define HAMMER2_DIO_GOOD 0x40000000 /* dio->bp is stable */ |
bca9f8e6 MD |
307 | #define HAMMER2_DIO_WAITING 0x20000000 /* (old) */ |
308 | #define HAMMER2_DIO_DIRTY 0x10000000 /* flush on last drop */ | |
309 | ||
310 | #define HAMMER2_DIO_MASK 0x0FFFFFFF | |
311 | ||
fdf62707 MD |
312 | /* |
313 | * Primary chain structure keeps track of the topology in-memory. | |
314 | */ | |
50e4f8f4 | 315 | struct hammer2_chain { |
f1c7c224 | 316 | hammer2_mtx_t lock; |
da6f36f4 | 317 | hammer2_chain_core_t core; |
8138a154 | 318 | RB_ENTRY(hammer2_chain) rbnode; /* live chain(s) */ |
0dea3156 | 319 | hammer2_blockref_t bref; |
da6f36f4 | 320 | struct hammer2_chain *parent; |
0dea3156 | 321 | struct hammer2_state *state; /* if active cache msg */ |
506bd6d1 MD |
322 | struct hammer2_dev *hmp; |
323 | struct hammer2_pfs *pmp; /* A PFS or super-root (spmp) */ | |
50456506 | 324 | |
fdf62707 | 325 | hammer2_io_t *dio; /* physical data buffer */ |
0dea3156 | 326 | u_int bytes; /* physical data size */ |
5c23d7f1 | 327 | u_int flags; |
0dea3156 | 328 | u_int refs; |
731b2a84 | 329 | u_int lockcnt; |
23c7c7dd MD |
330 | int error; /* on-lock data error state */ |
331 | ||
0dea3156 | 332 | hammer2_media_data_t *data; /* data pointer shortcut */ |
da6f36f4 | 333 | TAILQ_ENTRY(hammer2_chain) flush_node; /* flush list */ |
50e4f8f4 MD |
334 | }; |
335 | ||
336 | typedef struct hammer2_chain hammer2_chain_t; | |
337 | ||
5c23d7f1 | 338 | int hammer2_chain_cmp(hammer2_chain_t *chain1, hammer2_chain_t *chain2); |
ecc33e71 | 339 | RB_PROTOTYPE(hammer2_chain_tree, hammer2_chain, rbnode, hammer2_chain_cmp); |
5c23d7f1 | 340 | |
1a7cfe5a MD |
341 | /* |
342 | * Special notes on flags: | |
343 | * | |
b93cc2e0 MD |
344 | * INITIAL - This flag allows a chain to be created and for storage to |
345 | * be allocated without having to immediately instantiate the | |
346 | * related buffer. The data is assumed to be all-zeros. It | |
347 | * is primarily used for indirect blocks. | |
1a7cfe5a | 348 | * |
3f4ec3cf MD |
349 | * MODIFIED - The chain's media data has been modified. Prevents chain |
350 | * free on lastdrop if still in the topology. | |
da6f36f4 | 351 | * |
3f4ec3cf MD |
352 | * UPDATE - Chain might not be modified but parent blocktable needs |
353 | * an update. Prevents chain free on lastdrop if still in | |
354 | * the topology. | |
b93cc2e0 MD |
355 | * |
356 | * FICTITIOUS - Faked chain as a placeholder for an error condition. This | |
357 | * chain is unsuitable for I/O. | |
358 | * | |
359 | * BMAPPED - Indicates that the chain is present in the parent blockmap. | |
360 | * | |
361 | * BMAPUPD - Indicates that the chain is present but needs to be updated | |
362 | * in the parent blockmap. | |
1a7cfe5a | 363 | */ |
0dea3156 MD |
364 | #define HAMMER2_CHAIN_MODIFIED 0x00000001 /* dirty chain data */ |
365 | #define HAMMER2_CHAIN_ALLOCATED 0x00000002 /* kmalloc'd chain */ | |
da6f36f4 | 366 | #define HAMMER2_CHAIN_DESTROY 0x00000004 |
3f01ebaa | 367 | #define HAMMER2_CHAIN_DEDUP 0x00000008 /* used as dedup src */ |
5f6853df | 368 | #define HAMMER2_CHAIN_DELETED 0x00000010 /* deleted chain */ |
01eabad4 | 369 | #define HAMMER2_CHAIN_INITIAL 0x00000020 /* initial create */ |
da6f36f4 MD |
370 | #define HAMMER2_CHAIN_UPDATE 0x00000040 /* need parent update */ |
371 | #define HAMMER2_CHAIN_DEFERRED 0x00000080 /* flush depth defer */ | |
125966e8 | 372 | #define HAMMER2_CHAIN_UNUSED000001000 0x00000100 |
da6f36f4 | 373 | #define HAMMER2_CHAIN_ONFLUSH 0x00000200 /* on a flush list */ |
b93cc2e0 | 374 | #define HAMMER2_CHAIN_FICTITIOUS 0x00000400 /* unsuitable for I/O */ |
0dea3156 | 375 | #define HAMMER2_CHAIN_VOLUMESYNC 0x00000800 /* needs volume sync */ |
eedd52a3 | 376 | #define HAMMER2_CHAIN_DELAYED 0x00001000 /* delayed flush */ |
f1c7c224 | 377 | #define HAMMER2_CHAIN_COUNTEDBREFS 0x00002000 /* block table stats */ |
5f6853df | 378 | #define HAMMER2_CHAIN_ONRBTREE 0x00004000 /* on parent RB tree */ |
22211834 | 379 | #define HAMMER2_CHAIN_UNUSED00008000 0x00008000 |
512beabd | 380 | #define HAMMER2_CHAIN_EMBEDDED 0x00010000 /* embedded data */ |
10136ab6 | 381 | #define HAMMER2_CHAIN_RELEASE 0x00020000 /* don't keep around */ |
da6f36f4 MD |
382 | #define HAMMER2_CHAIN_BMAPPED 0x00040000 /* present in blkmap */ |
383 | #define HAMMER2_CHAIN_BMAPUPD 0x00080000 /* +needs updating */ | |
f1c7c224 MD |
384 | #define HAMMER2_CHAIN_IOINPROG 0x00100000 /* I/O interlock */ |
385 | #define HAMMER2_CHAIN_IOSIGNAL 0x00200000 /* I/O interlock */ | |
50456506 | 386 | #define HAMMER2_CHAIN_PFSBOUNDARY 0x00400000 /* super->pfs inode */ |
c667909f | 387 | |
da6f36f4 MD |
388 | #define HAMMER2_CHAIN_FLUSH_MASK (HAMMER2_CHAIN_MODIFIED | \ |
389 | HAMMER2_CHAIN_UPDATE | \ | |
390 | HAMMER2_CHAIN_ONFLUSH) | |
391 | ||
23c7c7dd MD |
392 | /* |
393 | * Hammer2 error codes, used by chain->error and cluster->error. The error | |
394 | * code is typically set on-lock unless no I/O was requested, and set on | |
395 | * I/O otherwise. If set for a cluster it generally means that the cluster | |
396 | * code could not find a valid copy to present. | |
397 | * | |
b93cc2e0 MD |
398 | * IO - An I/O error occurred |
399 | * CHECK - I/O succeeded but did not match the check code | |
400 | * INCOMPLETE - A cluster is not complete enough to use, or | |
401 | * a chain cannot be loaded because its parent has an error. | |
402 | * | |
23c7c7dd MD |
403 | * NOTE: API allows callers to check zero/non-zero to determine if an error |
404 | * condition exists. | |
405 | * | |
406 | * NOTE: Chain's data field is usually NULL on an IO error but not necessarily | |
407 | * NULL on other errors. Check chain->error, not chain->data. | |
408 | */ | |
409 | #define HAMMER2_ERROR_NONE 0 | |
410 | #define HAMMER2_ERROR_IO 1 /* device I/O error */ | |
411 | #define HAMMER2_ERROR_CHECK 2 /* check code mismatch */ | |
412 | #define HAMMER2_ERROR_INCOMPLETE 3 /* incomplete cluster */ | |
0cc33e20 | 413 | #define HAMMER2_ERROR_DEPTH 4 /* temporary depth limit */ |
23c7c7dd | 414 | |
c667909f MD |
415 | /* |
416 | * Flags passed to hammer2_chain_lookup() and hammer2_chain_next() | |
1a7cfe5a | 417 | * |
c847e838 MD |
418 | * NOTES: |
419 | * NOLOCK - Input and output chains are referenced only and not | |
420 | * locked. Output chain might be temporarily locked | |
421 | * internally. | |
422 | * | |
423 | * NODATA - Asks that the chain->data not be resolved in order | |
424 | * to avoid I/O. | |
425 | * | |
426 | * NODIRECT - Prevents a lookup of offset 0 in an inode from returning | |
427 | * the inode itself if the inode is in DIRECTDATA mode | |
428 | * (i.e. file is <= 512 bytes). Used by the synchronization | |
429 | * code to prevent confusion. | |
430 | * | |
431 | * SHARED - The input chain is expected to be locked shared, | |
432 | * and the output chain is locked shared. | |
433 | * | |
434 | * MATCHIND - Allows an indirect block / freemap node to be returned | |
435 | * when the passed key range matches the radix. Remember | |
436 | * that key_end is inclusive (e.g. {0x000,0xFFF}, | |
437 | * not {0x000,0x1000}). | |
438 | * | |
439 | * (Cannot be used for remote or cluster ops). | |
440 | * | |
441 | * ALLNODES - Allows NULL focus. | |
442 | * | |
443 | * ALWAYS - Always resolve the data. If ALWAYS and NODATA are both | |
444 | * missing, bulk file data is not resolved but inodes and | |
445 | * other meta-data will. | |
f7712c43 | 446 | * |
c847e838 MD |
447 | * NOUNLOCK - Used by hammer2_chain_next() to leave the lock on |
448 | * the input chain intact. The chain is still dropped. | |
449 | * This allows the caller to add a reference to the chain | |
450 | * and retain it in a locked state (used by the | |
451 | * XOP/feed/collect code). | |
c667909f MD |
452 | */ |
453 | #define HAMMER2_LOOKUP_NOLOCK 0x00000001 /* ref only */ | |
8cce658d | 454 | #define HAMMER2_LOOKUP_NODATA 0x00000002 /* data left NULL */ |
f7712c43 | 455 | #define HAMMER2_LOOKUP_NODIRECT 0x00000004 /* no offset=0 DD */ |
a0ed3c24 | 456 | #define HAMMER2_LOOKUP_SHARED 0x00000100 |
10136ab6 | 457 | #define HAMMER2_LOOKUP_MATCHIND 0x00000200 /* return all chains */ |
a6cf1052 | 458 | #define HAMMER2_LOOKUP_ALLNODES 0x00000400 /* allow NULL focus */ |
1a7cfe5a | 459 | #define HAMMER2_LOOKUP_ALWAYS 0x00000800 /* resolve data */ |
c847e838 | 460 | #define HAMMER2_LOOKUP_NOUNLOCK 0x00001000 /* leave lock intact */ |
5c23d7f1 | 461 | |
01eabad4 MD |
462 | /* |
463 | * Flags passed to hammer2_chain_modify() and hammer2_chain_resize() | |
464 | * | |
465 | * NOTE: OPTDATA allows us to avoid instantiating buffers for INDIRECT | |
466 | * blocks in the INITIAL-create state. | |
467 | */ | |
01eabad4 | 468 | #define HAMMER2_MODIFY_OPTDATA 0x00000002 /* data can be NULL */ |
4d5318eb | 469 | #define HAMMER2_MODIFY_NO_MODIFY_TID 0x00000004 |
e2163f5b | 470 | #define HAMMER2_MODIFY_UNUSED0008 0x00000008 |
01eabad4 MD |
471 | |
472 | /* | |
473 | * Flags passed to hammer2_chain_lock() | |
b8ba9690 MD |
474 | * |
475 | * NOTE: RDONLY is set to optimize cluster operations when *no* modifications | |
476 | * will be made to either the cluster being locked or any underlying | |
477 | * cluster. It allows the cluster to lock and access data for a subset | |
478 | * of available nodes instead of all available nodes. | |
01eabad4 MD |
479 | */ |
480 | #define HAMMER2_RESOLVE_NEVER 1 | |
481 | #define HAMMER2_RESOLVE_MAYBE 2 | |
482 | #define HAMMER2_RESOLVE_ALWAYS 3 | |
a0ed3c24 MD |
483 | #define HAMMER2_RESOLVE_MASK 0x0F |
484 | ||
1a7cfe5a | 485 | #define HAMMER2_RESOLVE_SHARED 0x10 /* request shared lock */ |
e513e77e | 486 | #define HAMMER2_RESOLVE_UNUSED20 0x20 |
b8ba9690 | 487 | #define HAMMER2_RESOLVE_RDONLY 0x40 /* higher level op flag */ |
01eabad4 | 488 | |
91abd410 MD |
489 | /* |
490 | * Flags passed to hammer2_chain_delete() | |
491 | */ | |
da6f36f4 | 492 | #define HAMMER2_DELETE_PERMANENT 0x0001 |
b3659de2 | 493 | |
01d71aa5 MD |
494 | /* |
495 | * Flags passed to hammer2_chain_insert() or hammer2_chain_rename() | |
496 | */ | |
506bd6d1 | 497 | #define HAMMER2_INSERT_PFSROOT 0x0004 |
91abd410 | 498 | |
09dd2dfe MD |
499 | /* |
500 | * Flags passed to hammer2_chain_delete_duplicate() | |
501 | */ | |
502 | #define HAMMER2_DELDUP_RECORE 0x0001 | |
503 | ||
6ba3b984 MD |
504 | /* |
505 | * Cluster different types of storage together for allocations | |
506 | */ | |
507 | #define HAMMER2_FREECACHE_INODE 0 | |
508 | #define HAMMER2_FREECACHE_INDIR 1 | |
509 | #define HAMMER2_FREECACHE_DATA 2 | |
510 | #define HAMMER2_FREECACHE_UNUSED3 3 | |
511 | #define HAMMER2_FREECACHE_TYPES 4 | |
512 | ||
1a7cfe5a MD |
513 | /* |
514 | * hammer2_freemap_alloc() block preference | |
515 | */ | |
516 | #define HAMMER2_OFF_NOPREF ((hammer2_off_t)-1) | |
517 | ||
6ba3b984 MD |
518 | /* |
519 | * BMAP read-ahead maximum parameters | |
520 | */ | |
521 | #define HAMMER2_BMAP_COUNT 16 /* max bmap read-ahead */ | |
522 | #define HAMMER2_BMAP_BYTES (HAMMER2_PBUFSIZE * HAMMER2_BMAP_COUNT) | |
523 | ||
10136ab6 MD |
524 | /* |
525 | * hammer2_freemap_adjust() | |
526 | */ | |
527 | #define HAMMER2_FREEMAP_DORECOVER 1 | |
528 | #define HAMMER2_FREEMAP_DOMAYFREE 2 | |
529 | #define HAMMER2_FREEMAP_DOREALFREE 3 | |
530 | ||
703720e4 | 531 | /* |
278ab2b2 | 532 | * HAMMER2 cluster - A set of chains representing the same entity. |
5c23d7f1 | 533 | * |
94491fa0 MD |
534 | * hammer2_cluster typically represents a temporary set of representitive |
535 | * chains. The one exception is that a hammer2_cluster is embedded in | |
536 | * hammer2_inode. This embedded cluster is ONLY used to track the | |
537 | * representitive chains and cannot be directly locked. | |
538 | * | |
5ceaaa82 MD |
539 | * A cluster is usually temporary (and thus per-thread) for locking purposes, |
540 | * allowing us to embed the asynchronous storage required for cluster | |
541 | * operations in the cluster itself and adjust the state and status without | |
542 | * having to worry too much about SMP issues. | |
543 | * | |
544 | * The exception is the cluster embedded in the hammer2_inode structure. | |
545 | * This is used to cache the cluster state on an inode-by-inode basis. | |
546 | * Individual hammer2_chain structures not incorporated into clusters might | |
547 | * also stick around to cache miscellanious elements. | |
94491fa0 MD |
548 | * |
549 | * Because the cluster is a 'working copy' and is usually subject to cluster | |
550 | * quorum rules, it is quite possible for us to end up with an insufficient | |
551 | * number of live chains to execute an operation. If an insufficient number | |
552 | * of chains remain in a working copy, the operation may have to be | |
5ceaaa82 MD |
553 | * downgraded, retried, stall until the requisit number of chains are |
554 | * available, or possibly even error out depending on the mount type. | |
8db69c9f MD |
555 | * |
556 | * A cluster's focus is set when it is locked. The focus can only be set | |
557 | * to a chain still part of the synchronized set. | |
5c23d7f1 | 558 | */ |
278ab2b2 | 559 | #define HAMMER2_MAXCLUSTER 8 |
c847e838 MD |
560 | #define HAMMER2_XOPFIFO 16 |
561 | #define HAMMER2_XOPFIFO_MASK (HAMMER2_XOPFIFO - 1) | |
2ed4fece | 562 | #define HAMMER2_XOPGROUPS 16 |
c847e838 MD |
563 | #define HAMMER2_XOPGROUPS_MASK (HAMMER2_XOPGROUPS - 1) |
564 | #define HAMMER2_XOPMASK_VOP 0x80000000U | |
278ab2b2 | 565 | |
4b7e61e0 | 566 | struct hammer2_cluster_item { |
4b7e61e0 | 567 | hammer2_chain_t *chain; |
4b7e61e0 | 568 | int cache_index; |
3f4ec3cf | 569 | int error; |
b8ba9690 | 570 | uint32_t flags; |
4b7e61e0 MD |
571 | }; |
572 | ||
573 | typedef struct hammer2_cluster_item hammer2_cluster_item_t; | |
574 | ||
8db69c9f MD |
575 | /* |
576 | * INVALID - Invalid for focus, i.e. not part of synchronized set. | |
577 | * Once set, this bit is sticky across operations. | |
e513e77e MD |
578 | * |
579 | * FEMOD - Indicates that front-end modifying operations can | |
580 | * mess with this entry and MODSYNC will copy also | |
581 | * effect it. | |
8db69c9f MD |
582 | */ |
583 | #define HAMMER2_CITEM_INVALID 0x00000001 | |
e513e77e | 584 | #define HAMMER2_CITEM_FEMOD 0x00000002 |
c847e838 | 585 | #define HAMMER2_CITEM_NULL 0x00000004 |
8db69c9f | 586 | |
278ab2b2 | 587 | struct hammer2_cluster { |
278ab2b2 | 588 | int refs; /* track for deallocation */ |
b8ba9690 | 589 | int ddflag; |
506bd6d1 | 590 | struct hammer2_pfs *pmp; |
278ab2b2 MD |
591 | uint32_t flags; |
592 | int nchains; | |
23c7c7dd | 593 | int error; /* error code valid on lock */ |
8db69c9f | 594 | int focus_index; |
bca9f8e6 | 595 | hammer2_iocb_t iocb; |
278ab2b2 | 596 | hammer2_chain_t *focus; /* current focus (or mod) */ |
4b7e61e0 | 597 | hammer2_cluster_item_t array[HAMMER2_MAXCLUSTER]; |
278ab2b2 MD |
598 | }; |
599 | ||
94491fa0 | 600 | typedef struct hammer2_cluster hammer2_cluster_t; |
278ab2b2 | 601 | |
5ceaaa82 MD |
602 | /* |
603 | * WRHARD - Hard mounts can write fully synchronized | |
604 | * RDHARD - Hard mounts can read fully synchronized | |
b93cc2e0 MD |
605 | * UNHARD - Unsynchronized masters present |
606 | * NOHARD - No masters visible | |
5ceaaa82 MD |
607 | * WRSOFT - Soft mounts can write to at least the SOFT_MASTER |
608 | * RDSOFT - Soft mounts can read from at least a SOFT_SLAVE | |
b93cc2e0 MD |
609 | * UNSOFT - Unsynchronized slaves present |
610 | * NOSOFT - No slaves visible | |
5ceaaa82 MD |
611 | * RDSLAVE - slaves are accessible (possibly unsynchronized or remote). |
612 | * MSYNCED - All masters are fully synchronized | |
613 | * SSYNCED - All known local slaves are fully synchronized to masters | |
614 | * | |
615 | * All available masters are always incorporated. All PFSs belonging to a | |
616 | * cluster (master, slave, copy, whatever) always try to synchronize the | |
617 | * total number of known masters in the PFSs root inode. | |
618 | * | |
619 | * A cluster might have access to many slaves, copies, or caches, but we | |
620 | * have a limited number of cluster slots. Any such elements which are | |
621 | * directly mounted from block device(s) will always be incorporated. Note | |
622 | * that SSYNCED only applies to such elements which are directly mounted, | |
623 | * not to any remote slaves, copies, or caches that could be available. These | |
624 | * bits are used to monitor and drive our synchronization threads. | |
625 | * | |
626 | * When asking the question 'is any data accessible at all', then a simple | |
627 | * test against (RDHARD|RDSOFT|RDSLAVE) gives you the answer. If any of | |
628 | * these bits are set the object can be read with certain caveats: | |
629 | * RDHARD - no caveats. RDSOFT - authoritative but might not be synchronized. | |
630 | * and RDSLAVE - not authoritative, has some data but it could be old or | |
631 | * incomplete. | |
632 | * | |
633 | * When both soft and hard mounts are available, data will be read and written | |
634 | * via the soft mount only. But all might be in the cluster because | |
635 | * background synchronization threads still need to do their work. | |
636 | */ | |
a6cf1052 MD |
637 | #define HAMMER2_CLUSTER_INODE 0x00000001 /* embedded in inode struct */ |
638 | #define HAMMER2_CLUSTER_UNUSED2 0x00000002 | |
b8ba9690 | 639 | #define HAMMER2_CLUSTER_LOCKED 0x00000004 /* cluster lks not recursive */ |
5ceaaa82 MD |
640 | #define HAMMER2_CLUSTER_WRHARD 0x00000100 /* hard-mount can write */ |
641 | #define HAMMER2_CLUSTER_RDHARD 0x00000200 /* hard-mount can read */ | |
b93cc2e0 MD |
642 | #define HAMMER2_CLUSTER_UNHARD 0x00000400 /* unsynchronized masters */ |
643 | #define HAMMER2_CLUSTER_NOHARD 0x00000800 /* no masters visible */ | |
644 | #define HAMMER2_CLUSTER_WRSOFT 0x00001000 /* soft-mount can write */ | |
645 | #define HAMMER2_CLUSTER_RDSOFT 0x00002000 /* soft-mount can read */ | |
646 | #define HAMMER2_CLUSTER_UNSOFT 0x00004000 /* unsynchronized slaves */ | |
647 | #define HAMMER2_CLUSTER_NOSOFT 0x00008000 /* no slaves visible */ | |
648 | #define HAMMER2_CLUSTER_MSYNCED 0x00010000 /* all masters synchronized */ | |
649 | #define HAMMER2_CLUSTER_SSYNCED 0x00020000 /* known slaves synchronized */ | |
5ceaaa82 MD |
650 | |
651 | #define HAMMER2_CLUSTER_ANYDATA ( HAMMER2_CLUSTER_RDHARD | \ | |
652 | HAMMER2_CLUSTER_RDSOFT | \ | |
653 | HAMMER2_CLUSTER_RDSLAVE) | |
654 | ||
655 | #define HAMMER2_CLUSTER_RDOK ( HAMMER2_CLUSTER_RDHARD | \ | |
656 | HAMMER2_CLUSTER_RDSOFT) | |
657 | ||
658 | #define HAMMER2_CLUSTER_WROK ( HAMMER2_CLUSTER_WRHARD | \ | |
659 | HAMMER2_CLUSTER_WRSOFT) | |
278ab2b2 | 660 | |
b8ba9690 MD |
661 | #define HAMMER2_CLUSTER_ZFLAGS ( HAMMER2_CLUSTER_WRHARD | \ |
662 | HAMMER2_CLUSTER_RDHARD | \ | |
663 | HAMMER2_CLUSTER_WRSOFT | \ | |
664 | HAMMER2_CLUSTER_RDSOFT | \ | |
665 | HAMMER2_CLUSTER_MSYNCED | \ | |
666 | HAMMER2_CLUSTER_SSYNCED) | |
5c23d7f1 | 667 | |
23c7c7dd MD |
668 | /* |
669 | * Helper functions (cluster must be locked for flags to be valid). | |
670 | */ | |
671 | static __inline | |
672 | int | |
673 | hammer2_cluster_rdok(hammer2_cluster_t *cluster) | |
674 | { | |
675 | return (cluster->flags & HAMMER2_CLUSTER_RDOK); | |
676 | } | |
677 | ||
678 | static __inline | |
679 | int | |
680 | hammer2_cluster_wrok(hammer2_cluster_t *cluster) | |
681 | { | |
682 | return (cluster->flags & HAMMER2_CLUSTER_WROK); | |
683 | } | |
684 | ||
9797e933 MD |
685 | RB_HEAD(hammer2_inode_tree, hammer2_inode); |
686 | ||
5c23d7f1 MD |
687 | /* |
688 | * A hammer2 inode. | |
46558838 | 689 | * |
bca9f8e6 MD |
690 | * NOTE: The inode-embedded cluster is never used directly for I/O (since |
691 | * it may be shared). Instead it will be replicated-in and synchronized | |
692 | * back out if changed. | |
703720e4 MD |
693 | */ |
694 | struct hammer2_inode { | |
9797e933 | 695 | RB_ENTRY(hammer2_inode) rbnode; /* inumber lookup (HL) */ |
94491fa0 | 696 | hammer2_mtx_t lock; /* inode lock */ |
506bd6d1 | 697 | struct hammer2_pfs *pmp; /* PFS mount */ |
e028fa74 | 698 | struct hammer2_inode *pip; /* parent inode */ |
703720e4 | 699 | struct vnode *vp; |
eedd52a3 | 700 | struct spinlock cluster_spin; /* update cluster */ |
278ab2b2 | 701 | hammer2_cluster_t cluster; |
37aa19df | 702 | struct lockf advlock; |
476d2aad MD |
703 | u_int flags; |
704 | u_int refs; /* +vpref, +flushref */ | |
1e5c08ba | 705 | uint8_t comp_heuristic; |
7a9b14a0 | 706 | hammer2_inode_meta_t meta; /* copy of meta-data */ |
2121ef11 | 707 | hammer2_off_t osize; |
703720e4 MD |
708 | }; |
709 | ||
54eb943b MD |
710 | typedef struct hammer2_inode hammer2_inode_t; |
711 | ||
2121ef11 MD |
712 | /* |
713 | * MODIFIED - Inode is in a modified state, ip->meta may have changes. | |
714 | * RESIZED - Inode truncated (any) or inode extended beyond | |
715 | * EMBEDDED_BYTES. | |
716 | */ | |
476d2aad | 717 | #define HAMMER2_INODE_MODIFIED 0x0001 |
99da41ea | 718 | #define HAMMER2_INODE_SROOT 0x0002 /* kmalloc special case */ |
51bf8e9b | 719 | #define HAMMER2_INODE_RENAME_INPROG 0x0004 |
9797e933 | 720 | #define HAMMER2_INODE_ONRBTREE 0x0008 |
2121ef11 | 721 | #define HAMMER2_INODE_RESIZED 0x0010 /* requires inode_fsync */ |
f6197681 | 722 | #define HAMMER2_INODE_ISDELETED 0x0020 /* deleted, not in ihidden */ |
1f6671f8 | 723 | #define HAMMER2_INODE_ISUNLINKED 0x0040 |
7a9b14a0 | 724 | #define HAMMER2_INODE_METAGOOD 0x0080 /* inode meta-data good */ |
b5b45574 | 725 | #define HAMMER2_INODE_ONSIDEQ 0x0100 /* on side processing queue */ |
9797e933 MD |
726 | |
727 | int hammer2_inode_cmp(hammer2_inode_t *ip1, hammer2_inode_t *ip2); | |
728 | RB_PROTOTYPE2(hammer2_inode_tree, hammer2_inode, rbnode, hammer2_inode_cmp, | |
729 | hammer2_tid_t); | |
5c23d7f1 | 730 | |
eae2ed61 MD |
731 | /* |
732 | * inode-unlink side-structure | |
733 | */ | |
b5b45574 MD |
734 | struct hammer2_inode_sideq { |
735 | TAILQ_ENTRY(hammer2_inode_sideq) entry; | |
eae2ed61 MD |
736 | hammer2_inode_t *ip; |
737 | }; | |
b5b45574 | 738 | TAILQ_HEAD(h2_sideq_list, hammer2_inode_sideq); |
eae2ed61 | 739 | |
b5b45574 | 740 | typedef struct hammer2_inode_sideq hammer2_inode_sideq_t; |
eae2ed61 | 741 | |
0dea3156 | 742 | /* |
c603b86b | 743 | * Transaction management sub-structure under hammer2_pfs |
0dea3156 MD |
744 | */ |
745 | struct hammer2_trans { | |
c603b86b MD |
746 | uint32_t flags; |
747 | uint32_t sync_wait; | |
0dea3156 MD |
748 | }; |
749 | ||
750 | typedef struct hammer2_trans hammer2_trans_t; | |
751 | ||
c603b86b MD |
752 | #define HAMMER2_TRANS_ISFLUSH 0x80000000 /* flush code */ |
753 | #define HAMMER2_TRANS_BUFCACHE 0x40000000 /* bio strategy */ | |
754 | #define HAMMER2_TRANS_PREFLUSH 0x20000000 /* preflush state */ | |
755 | #define HAMMER2_TRANS_FPENDING 0x10000000 /* flush pending */ | |
756 | #define HAMMER2_TRANS_WAITING 0x08000000 /* someone waiting */ | |
757 | #define HAMMER2_TRANS_MASK 0x00FFFFFF /* count mask */ | |
d001f460 | 758 | |
91abd410 MD |
759 | #define HAMMER2_FREEMAP_HEUR_NRADIX 4 /* pwr 2 PBUFRADIX-MINIORADIX */ |
760 | #define HAMMER2_FREEMAP_HEUR_TYPES 8 | |
3f01ebaa | 761 | #define HAMMER2_FREEMAP_HEUR_SIZE (HAMMER2_FREEMAP_HEUR_NRADIX * \ |
91abd410 | 762 | HAMMER2_FREEMAP_HEUR_TYPES) |
004f88b4 | 763 | |
3f01ebaa MD |
764 | #define HAMMER2_DEDUP_HEUR_SIZE 65536 |
765 | #define HAMMER2_DEDUP_HEUR_MASK (HAMMER2_DEDUP_HEUR_SIZE - 1) | |
766 | ||
53f84d31 MD |
767 | #define HAMMER2_FLUSH_TOP 0x0001 |
768 | #define HAMMER2_FLUSH_ALL 0x0002 | |
769 | ||
770 | ||
1f6671f8 | 771 | /* |
2ed4fece | 772 | * Hammer2 support thread element. |
b0f58de8 | 773 | * |
2ed4fece MD |
774 | * Potentially many support threads can hang off of hammer2, primarily |
775 | * off the hammer2_pfs structure. Typically: | |
8db69c9f | 776 | * |
2ed4fece MD |
777 | * td x Nodes A synchronization thread for each node. |
778 | * td x Nodes x workers Worker threads for frontend operations. | |
779 | * td x 1 Bioq thread for logical buffer writes. | |
8db69c9f | 780 | * |
2ed4fece MD |
781 | * In addition, the synchronization thread(s) associated with the |
782 | * super-root PFS (spmp) for a node is responsible for automatic bulkfree | |
783 | * and dedup scans. | |
8db69c9f | 784 | */ |
2ed4fece | 785 | struct hammer2_thread { |
8db69c9f | 786 | struct hammer2_pfs *pmp; |
21a90458 | 787 | hammer2_xop_list_t *xopq; /* points into pmp->xopq[] */ |
8db69c9f MD |
788 | thread_t td; |
789 | uint32_t flags; | |
f7712c43 | 790 | int depth; |
2ed4fece MD |
791 | int clindex; /* cluster element index */ |
792 | int repidx; | |
2ed4fece MD |
793 | struct lock lk; /* thread control lock */ |
794 | }; | |
795 | ||
796 | typedef struct hammer2_thread hammer2_thread_t; | |
797 | ||
798 | #define HAMMER2_THREAD_UNMOUNTING 0x0001 /* unmount request */ | |
799 | #define HAMMER2_THREAD_DEV 0x0002 /* related to dev, not pfs */ | |
800 | #define HAMMER2_THREAD_UNUSED04 0x0004 | |
801 | #define HAMMER2_THREAD_REMASTER 0x0008 /* remaster request */ | |
802 | #define HAMMER2_THREAD_STOP 0x0010 /* exit request */ | |
803 | #define HAMMER2_THREAD_FREEZE 0x0020 /* force idle */ | |
804 | #define HAMMER2_THREAD_FROZEN 0x0040 /* restart */ | |
805 | ||
3f01ebaa MD |
806 | /* |
807 | * Support structure for dedup heuristic. | |
808 | */ | |
809 | struct hammer2_dedup { | |
810 | hammer2_off_t data_off; | |
811 | uint32_t data_crc; | |
812 | uint32_t ticks; | |
813 | }; | |
814 | ||
815 | typedef struct hammer2_dedup hammer2_dedup_t; | |
2ed4fece MD |
816 | |
817 | /* | |
c847e838 | 818 | * hammer2_xop - container for VOP/XOP operation (allocated, not on stack). |
2ed4fece MD |
819 | * |
820 | * This structure is used to distribute a VOP operation across multiple | |
821 | * nodes. It provides a rendezvous for concurrent node execution and | |
822 | * can be detached from the frontend operation to allow the frontend to | |
823 | * return early. | |
21a90458 MD |
824 | * |
825 | * This structure also sequences operations on up to three inodes. | |
2ed4fece | 826 | */ |
c847e838 MD |
827 | typedef void (*hammer2_xop_func_t)(union hammer2_xop *xop, int clidx); |
828 | ||
3f01ebaa | 829 | struct hammer2_xop_fifo { |
c847e838 MD |
830 | TAILQ_ENTRY(hammer2_xop_head) entry; |
831 | hammer2_chain_t *array[HAMMER2_XOPFIFO]; | |
832 | int errors[HAMMER2_XOPFIFO]; | |
833 | int ri; | |
834 | int wi; | |
21a90458 | 835 | int flags; |
3f01ebaa MD |
836 | }; |
837 | ||
838 | typedef struct hammer2_xop_fifo hammer2_xop_fifo_t; | |
c847e838 | 839 | |
21a90458 | 840 | #define HAMMER2_XOP_FIFO_RUN 0x0001 |
2efe493b | 841 | #define HAMMER2_XOP_FIFO_STALL 0x0002 |
21a90458 | 842 | |
c847e838 MD |
843 | struct hammer2_xop_head { |
844 | hammer2_xop_func_t func; | |
e2163f5b | 845 | hammer2_tid_t mtid; |
21a90458 | 846 | struct hammer2_inode *ip1; |
e12ae3a5 MD |
847 | struct hammer2_inode *ip2; |
848 | struct hammer2_inode *ip3; | |
c847e838 MD |
849 | uint32_t check_counter; |
850 | uint32_t run_mask; | |
851 | uint32_t chk_mask; | |
852 | int state; | |
853 | int error; | |
01d71aa5 | 854 | hammer2_key_t collect_key; |
21a90458 MD |
855 | char *name1; |
856 | size_t name1_len; | |
e12ae3a5 MD |
857 | char *name2; |
858 | size_t name2_len; | |
c847e838 MD |
859 | hammer2_xop_fifo_t collect[HAMMER2_MAXCLUSTER]; |
860 | hammer2_cluster_t cluster; /* help collections */ | |
8db69c9f MD |
861 | }; |
862 | ||
c847e838 MD |
863 | typedef struct hammer2_xop_head hammer2_xop_head_t; |
864 | ||
01d71aa5 | 865 | struct hammer2_xop_ipcluster { |
b7add675 MD |
866 | hammer2_xop_head_t head; |
867 | }; | |
868 | ||
c603b86b MD |
869 | struct hammer2_xop_strategy { |
870 | hammer2_xop_head_t head; | |
871 | hammer2_key_t lbase; | |
872 | int finished; | |
21a90458 | 873 | hammer2_mtx_t lock; |
c603b86b MD |
874 | struct bio *bio; |
875 | }; | |
876 | ||
c847e838 MD |
877 | struct hammer2_xop_readdir { |
878 | hammer2_xop_head_t head; | |
01d71aa5 | 879 | hammer2_key_t lkey; |
c847e838 MD |
880 | }; |
881 | ||
c603b86b MD |
882 | struct hammer2_xop_nresolve { |
883 | hammer2_xop_head_t head; | |
b7add675 | 884 | hammer2_key_t lhc; /* if name is NULL used lhc */ |
c603b86b MD |
885 | }; |
886 | ||
e12ae3a5 MD |
887 | struct hammer2_xop_nlink { |
888 | hammer2_xop_head_t head; | |
76f85faa | 889 | int nlinks_delta; |
e12ae3a5 MD |
890 | }; |
891 | ||
892 | struct hammer2_xop_unlink { | |
893 | hammer2_xop_head_t head; | |
894 | int isdir; | |
895 | int dopermanent; | |
896 | }; | |
897 | ||
898 | struct hammer2_xop_nrename { | |
899 | hammer2_xop_head_t head; | |
900 | hammer2_tid_t lhc; | |
901 | int ip_key; | |
902 | }; | |
903 | ||
c603b86b MD |
904 | struct hammer2_xop_scanlhc { |
905 | hammer2_xop_head_t head; | |
906 | hammer2_key_t lhc; | |
907 | }; | |
908 | ||
01d71aa5 MD |
909 | struct hammer2_xop_scanall { |
910 | hammer2_xop_head_t head; | |
911 | hammer2_key_t key_beg; /* inclusive */ | |
912 | hammer2_key_t key_end; /* inclusive */ | |
b02c0ae6 MD |
913 | int resolve_flags; |
914 | int lookup_flags; | |
01d71aa5 MD |
915 | }; |
916 | ||
b7add675 MD |
917 | struct hammer2_xop_lookup { |
918 | hammer2_xop_head_t head; | |
919 | hammer2_key_t lhc; | |
920 | }; | |
921 | ||
c603b86b MD |
922 | struct hammer2_xop_create { |
923 | hammer2_xop_head_t head; | |
924 | hammer2_inode_meta_t meta; /* initial metadata */ | |
925 | hammer2_key_t lhc; | |
926 | int flags; | |
c603b86b MD |
927 | }; |
928 | ||
b7add675 | 929 | struct hammer2_xop_destroy { |
e12ae3a5 | 930 | hammer2_xop_head_t head; |
e12ae3a5 MD |
931 | }; |
932 | ||
01d71aa5 MD |
933 | struct hammer2_xop_fsync { |
934 | hammer2_xop_head_t head; | |
935 | hammer2_inode_meta_t meta; | |
936 | hammer2_off_t osize; | |
937 | u_int ipflags; | |
938 | int clear_directdata; | |
939 | }; | |
940 | ||
b7add675 MD |
941 | struct hammer2_xop_unlinkall { |
942 | hammer2_xop_head_t head; | |
01d71aa5 MD |
943 | hammer2_key_t key_beg; |
944 | hammer2_key_t key_end; | |
b7add675 MD |
945 | }; |
946 | ||
947 | struct hammer2_xop_connect { | |
c603b86b MD |
948 | hammer2_xop_head_t head; |
949 | hammer2_key_t lhc; | |
c603b86b MD |
950 | }; |
951 | ||
12ff971c MD |
952 | struct hammer2_xop_flush { |
953 | hammer2_xop_head_t head; | |
954 | }; | |
955 | ||
c847e838 | 956 | typedef struct hammer2_xop_readdir hammer2_xop_readdir_t; |
c603b86b | 957 | typedef struct hammer2_xop_nresolve hammer2_xop_nresolve_t; |
e12ae3a5 MD |
958 | typedef struct hammer2_xop_nlink hammer2_xop_nlink_t; |
959 | typedef struct hammer2_xop_unlink hammer2_xop_unlink_t; | |
960 | typedef struct hammer2_xop_nrename hammer2_xop_nrename_t; | |
01d71aa5 | 961 | typedef struct hammer2_xop_ipcluster hammer2_xop_ipcluster_t; |
c603b86b MD |
962 | typedef struct hammer2_xop_strategy hammer2_xop_strategy_t; |
963 | typedef struct hammer2_xop_create hammer2_xop_create_t; | |
964 | typedef struct hammer2_xop_destroy hammer2_xop_destroy_t; | |
01d71aa5 | 965 | typedef struct hammer2_xop_fsync hammer2_xop_fsync_t; |
b7add675 | 966 | typedef struct hammer2_xop_unlinkall hammer2_xop_unlinkall_t; |
c603b86b | 967 | typedef struct hammer2_xop_scanlhc hammer2_xop_scanlhc_t; |
01d71aa5 | 968 | typedef struct hammer2_xop_scanall hammer2_xop_scanall_t; |
b7add675 | 969 | typedef struct hammer2_xop_lookup hammer2_xop_lookup_t; |
e12ae3a5 | 970 | typedef struct hammer2_xop_connect hammer2_xop_connect_t; |
12ff971c | 971 | typedef struct hammer2_xop_flush hammer2_xop_flush_t; |
c847e838 MD |
972 | |
973 | union hammer2_xop { | |
974 | hammer2_xop_head_t head; | |
01d71aa5 | 975 | hammer2_xop_ipcluster_t xop_ipcluster; |
c847e838 | 976 | hammer2_xop_readdir_t xop_readdir; |
c603b86b | 977 | hammer2_xop_nresolve_t xop_nresolve; |
e12ae3a5 MD |
978 | hammer2_xop_nlink_t xop_nlink; |
979 | hammer2_xop_unlink_t xop_unlink; | |
980 | hammer2_xop_nrename_t xop_nrename; | |
c603b86b MD |
981 | hammer2_xop_strategy_t xop_strategy; |
982 | hammer2_xop_create_t xop_create; | |
983 | hammer2_xop_destroy_t xop_destroy; | |
01d71aa5 | 984 | hammer2_xop_fsync_t xop_fsync; |
b7add675 | 985 | hammer2_xop_unlinkall_t xop_unlinkall; |
c603b86b | 986 | hammer2_xop_scanlhc_t xop_scanlhc; |
01d71aa5 | 987 | hammer2_xop_scanall_t xop_scanall; |
b7add675 | 988 | hammer2_xop_lookup_t xop_lookup; |
12ff971c | 989 | hammer2_xop_flush_t xop_flush; |
e12ae3a5 | 990 | hammer2_xop_connect_t xop_connect; |
c847e838 | 991 | }; |
2ed4fece | 992 | |
c847e838 | 993 | typedef union hammer2_xop hammer2_xop_t; |
8db69c9f | 994 | |
2ed4fece MD |
995 | /* |
996 | * hammer2_xop_group - Manage XOP support threads. | |
997 | */ | |
998 | struct hammer2_xop_group { | |
999 | hammer2_thread_t thrs[HAMMER2_MAXCLUSTER]; | |
2ed4fece | 1000 | }; |
8db69c9f | 1001 | |
2ed4fece | 1002 | typedef struct hammer2_xop_group hammer2_xop_group_t; |
8db69c9f | 1003 | |
c603b86b MD |
1004 | /* |
1005 | * flags to hammer2_xop_collect() | |
1006 | */ | |
1007 | #define HAMMER2_XOP_COLLECT_NOWAIT 0x00000001 | |
12ff971c | 1008 | #define HAMMER2_XOP_COLLECT_WAITALL 0x00000002 |
c603b86b MD |
1009 | |
1010 | /* | |
1011 | * flags to hammer2_xop_alloc() | |
1012 | * | |
e2163f5b | 1013 | * MODIFYING - This is a modifying transaction, allocate a mtid. |
c603b86b | 1014 | */ |
e2163f5b | 1015 | #define HAMMER2_XOP_MODIFYING 0x00000001 |
c603b86b | 1016 | |
50456506 | 1017 | /* |
506bd6d1 MD |
1018 | * Global (per partition) management structure, represents a hard block |
1019 | * device. Typically referenced by hammer2_chain structures when applicable. | |
1020 | * Typically not used for network-managed elements. | |
1021 | * | |
1022 | * Note that a single hammer2_dev can be indirectly tied to multiple system | |
1023 | * mount points. There is no direct relationship. System mounts are | |
1024 | * per-cluster-id, not per-block-device, and a single hard mount might contain | |
1025 | * many PFSs and those PFSs might combine together in various ways to form | |
1026 | * the set of available clusters. | |
50456506 | 1027 | */ |
506bd6d1 | 1028 | struct hammer2_dev { |
50e4f8f4 | 1029 | struct vnode *devvp; /* device vnode */ |
50e4f8f4 | 1030 | int ronly; /* read-only mount */ |
f7712c43 | 1031 | int mount_count; /* number of actively mounted PFSs */ |
506bd6d1 | 1032 | TAILQ_ENTRY(hammer2_dev) mntentry; /* hammer2_mntlist */ |
703720e4 | 1033 | |
5c23d7f1 | 1034 | struct malloc_type *mchain; |
54eb943b MD |
1035 | int nipstacks; |
1036 | int maxipstacks; | |
063639ba | 1037 | kdmsg_iocom_t iocom; /* volume-level dmsg interface */ |
fdf62707 MD |
1038 | struct spinlock io_spin; /* iotree access */ |
1039 | struct hammer2_io_tree iotree; | |
1040 | int iofree_count; | |
7bed8d7e MD |
1041 | hammer2_chain_t vchain; /* anchor chain (topology) */ |
1042 | hammer2_chain_t fchain; /* anchor chain (freemap) */ | |
da6f36f4 MD |
1043 | struct spinlock list_spin; |
1044 | struct h2_flush_list flushq; /* flush seeds */ | |
506bd6d1 | 1045 | struct hammer2_pfs *spmp; /* super-root pmp for transactions */ |
21a90458 | 1046 | struct lock bulklk; /* bulkfree lock */ |
50456506 | 1047 | struct lock vollk; /* lockmgr lock */ |
3f01ebaa MD |
1048 | hammer2_off_t heur_freemap[HAMMER2_FREEMAP_HEUR_SIZE]; |
1049 | hammer2_dedup_t heur_dedup[HAMMER2_DEDUP_HEUR_SIZE]; | |
3fc4c63d | 1050 | int volhdrno; /* last volhdrno written */ |
b02c0ae6 | 1051 | int hflags; /* HMNT2 flags applicable to device */ |
e513e77e | 1052 | char devrepname[64]; /* for kprintf */ |
54eb943b | 1053 | hammer2_volume_data_t voldata; |
3fc4c63d | 1054 | hammer2_volume_data_t volsync; /* synchronized voldata */ |
703720e4 MD |
1055 | }; |
1056 | ||
506bd6d1 | 1057 | typedef struct hammer2_dev hammer2_dev_t; |
54eb943b | 1058 | |
23c7c7dd MD |
1059 | /* |
1060 | * Helper functions (cluster must be locked for flags to be valid). | |
1061 | */ | |
1062 | static __inline | |
1063 | int | |
1064 | hammer2_chain_rdok(hammer2_chain_t *chain) | |
1065 | { | |
1066 | return (chain->error == 0); | |
1067 | } | |
1068 | ||
1069 | static __inline | |
1070 | int | |
1071 | hammer2_chain_wrok(hammer2_chain_t *chain) | |
1072 | { | |
1073 | return (chain->error == 0 && chain->hmp->ronly == 0); | |
1074 | } | |
1075 | ||
e4e20f48 | 1076 | /* |
506bd6d1 MD |
1077 | * Per-cluster management structure. This structure will be tied to a |
1078 | * system mount point if the system is mounting the PFS, but is also used | |
1079 | * to manage clusters encountered during the super-root scan or received | |
1080 | * via LNK_SPANs that might not be mounted. | |
7750fd72 | 1081 | * |
506bd6d1 MD |
1082 | * This structure is also used to represent the super-root that hangs off |
1083 | * of a hard mount point. The super-root is not really a cluster element. | |
1084 | * In this case the spmp_hmp field will be non-NULL. It's just easier to do | |
1085 | * this than to special case super-root manipulation in the hammer2_chain* | |
1086 | * code as being only hammer2_dev-related. | |
7750fd72 | 1087 | * |
506bd6d1 MD |
1088 | * pfs_mode and pfs_nmasters are rollup fields which critically describes |
1089 | * how elements of the cluster act on the cluster. pfs_mode is only applicable | |
1090 | * when a PFS is mounted by the system. pfs_nmasters is our best guess as to | |
1091 | * how many masters have been configured for a cluster and is always | |
22211834 MD |
1092 | * applicable. pfs_types[] is an array with 1:1 correspondance to the |
1093 | * iroot cluster and describes the PFS types of the nodes making up the | |
1094 | * cluster. | |
7750fd72 | 1095 | * |
506bd6d1 MD |
1096 | * WARNING! Portions of this structure have deferred initialization. In |
1097 | * particular, if not mounted there will be no ihidden or wthread. | |
1098 | * umounted network PFSs will also be missing iroot and numerous | |
1099 | * other fields will not be initialized prior to mount. | |
7750fd72 | 1100 | * |
506bd6d1 MD |
1101 | * Synchronization threads are chain-specific and only applicable |
1102 | * to local hard PFS entries. A hammer2_pfs structure may contain | |
1103 | * more than one when multiple hard PFSs are present on the local | |
1104 | * machine which require synchronization monitoring. Most PFSs | |
1105 | * (such as snapshots) are 1xMASTER PFSs which do not need a | |
1106 | * synchronization thread. | |
7750fd72 | 1107 | * |
506bd6d1 | 1108 | * WARNING! The chains making up pfs->iroot's cluster are accounted for in |
f7712c43 | 1109 | * hammer2_dev->mount_count when the pfs is associated with a mount |
506bd6d1 | 1110 | * point. |
e4e20f48 | 1111 | */ |
506bd6d1 | 1112 | struct hammer2_pfs { |
7bed8d7e | 1113 | struct mount *mp; |
506bd6d1 | 1114 | TAILQ_ENTRY(hammer2_pfs) mntentry; /* hammer2_pfslist */ |
58e43599 | 1115 | uuid_t pfs_clid; |
506bd6d1 | 1116 | hammer2_dev_t *spmp_hmp; /* only if super-root pmp */ |
b02c0ae6 | 1117 | hammer2_dev_t *force_local; /* only if 'local' mount */ |
e4e20f48 | 1118 | hammer2_inode_t *iroot; /* PFS root inode */ |
044541cd | 1119 | hammer2_inode_t *ihidden; /* PFS hidden directory */ |
22211834 | 1120 | uint8_t pfs_types[HAMMER2_MAXCLUSTER]; |
c7916d0b | 1121 | char *pfs_names[HAMMER2_MAXCLUSTER]; |
01d71aa5 | 1122 | hammer2_dev_t *pfs_hmps[HAMMER2_MAXCLUSTER]; |
c603b86b | 1123 | hammer2_trans_t trans; |
044541cd | 1124 | struct lock lock; /* PFS lock for certain ops */ |
76f85faa | 1125 | struct lock lock_nlink; /* rename and nlink lock */ |
e4e20f48 MD |
1126 | struct netexport export; /* nfs export */ |
1127 | int ronly; /* read-only mount */ | |
b02c0ae6 | 1128 | int hflags; /* pfs-specific mount flags */ |
99da41ea | 1129 | struct malloc_type *minode; |
3a5aa68f | 1130 | struct malloc_type *mmsg; |
9797e933 | 1131 | struct spinlock inum_spin; /* inumber lookup */ |
50456506 | 1132 | struct hammer2_inode_tree inum_tree; /* (not applicable to spmp) */ |
e513e77e MD |
1133 | hammer2_tid_t modify_tid; /* modify transaction id */ |
1134 | hammer2_tid_t inode_tid; /* inode allocator */ | |
7750fd72 MD |
1135 | uint8_t pfs_nmasters; /* total masters */ |
1136 | uint8_t pfs_mode; /* operating mode PFSMODE */ | |
1137 | uint8_t unused01; | |
1138 | uint8_t unused02; | |
c847e838 | 1139 | int xop_iterator; |
355d67fc | 1140 | long inmem_inodes; |
da6f36f4 | 1141 | uint32_t inmem_dirty_chains; |
3f5b8b3b | 1142 | int count_lwinprog; /* logical write in prog */ |
da6f36f4 | 1143 | struct spinlock list_spin; |
b5b45574 | 1144 | struct h2_sideq_list sideq; /* last-close dirty/unlink */ |
2ed4fece | 1145 | hammer2_thread_t sync_thrs[HAMMER2_MAXCLUSTER]; |
01d71aa5 | 1146 | uint32_t cluster_flags; /* cached cluster flags */ |
8cd26e36 | 1147 | int has_xop_threads; |
21a90458 | 1148 | struct spinlock xop_spin; /* xop sequencer */ |
2ed4fece | 1149 | hammer2_xop_group_t xop_groups[HAMMER2_XOPGROUPS]; |
21a90458 | 1150 | hammer2_xop_list_t xopq[HAMMER2_MAXCLUSTER]; |
e4e20f48 MD |
1151 | }; |
1152 | ||
506bd6d1 | 1153 | typedef struct hammer2_pfs hammer2_pfs_t; |
e4e20f48 | 1154 | |
0924b3f8 MD |
1155 | #define HAMMER2_DIRTYCHAIN_WAITING 0x80000000 |
1156 | #define HAMMER2_DIRTYCHAIN_MASK 0x7FFFFFFF | |
1157 | ||
3f5b8b3b | 1158 | #define HAMMER2_LWINPROG_WAITING 0x80000000 |
d34788ef MD |
1159 | #define HAMMER2_LWINPROG_WAITING0 0x40000000 |
1160 | #define HAMMER2_LWINPROG_MASK 0x3FFFFFFF | |
3f5b8b3b | 1161 | |
c847e838 MD |
1162 | /* |
1163 | * hammer2_cluster_check | |
1164 | */ | |
1165 | #define HAMMER2_CHECK_NULL 0x00000001 | |
1166 | ||
3148f677 MD |
1167 | /* |
1168 | * Bulkscan | |
1169 | */ | |
1170 | #define HAMMER2_BULK_ABORT 0x00000001 | |
1171 | ||
1172 | /* | |
1173 | * Misc | |
1174 | */ | |
703720e4 MD |
1175 | #if defined(_KERNEL) |
1176 | ||
1177 | MALLOC_DECLARE(M_HAMMER2); | |
1178 | ||
e4e20f48 MD |
1179 | #define VTOI(vp) ((hammer2_inode_t *)(vp)->v_data) |
1180 | #define ITOV(ip) ((ip)->vp) | |
1181 | ||
91abd410 MD |
1182 | /* |
1183 | * Currently locked chains retain the locked buffer cache buffer for | |
1184 | * indirect blocks, and indirect blocks can be one of two sizes. The | |
1185 | * device buffer has to match the case to avoid deadlocking recursive | |
1186 | * chains that might otherwise try to access different offsets within | |
1187 | * the same device buffer. | |
1188 | */ | |
a98aa0b0 MD |
1189 | static __inline |
1190 | int | |
1191 | hammer2_devblkradix(int radix) | |
1192 | { | |
f89b6495 | 1193 | #if 0 |
91abd410 MD |
1194 | if (radix <= HAMMER2_LBUFRADIX) { |
1195 | return (HAMMER2_LBUFRADIX); | |
1196 | } else { | |
1197 | return (HAMMER2_PBUFRADIX); | |
1198 | } | |
f89b6495 MD |
1199 | #endif |
1200 | return (HAMMER2_PBUFRADIX); | |
a98aa0b0 MD |
1201 | } |
1202 | ||
71008001 MD |
1203 | /* |
1204 | * XXX almost time to remove this. DIO uses PBUFSIZE exclusively now. | |
1205 | */ | |
a98aa0b0 MD |
1206 | static __inline |
1207 | size_t | |
1208 | hammer2_devblksize(size_t bytes) | |
1209 | { | |
71008001 | 1210 | #if 0 |
a5913bdf | 1211 | if (bytes <= HAMMER2_LBUFSIZE) { |
a98aa0b0 | 1212 | return(HAMMER2_LBUFSIZE); |
a5913bdf MD |
1213 | } else { |
1214 | KKASSERT(bytes <= HAMMER2_PBUFSIZE && | |
1215 | (bytes ^ (bytes - 1)) == ((bytes << 1) - 1)); | |
91abd410 | 1216 | return (HAMMER2_PBUFSIZE); |
a5913bdf | 1217 | } |
71008001 MD |
1218 | #endif |
1219 | return (HAMMER2_PBUFSIZE); | |
a98aa0b0 MD |
1220 | } |
1221 | ||
1222 | ||
e118c14f | 1223 | static __inline |
506bd6d1 | 1224 | hammer2_pfs_t * |
e4e20f48 | 1225 | MPTOPMP(struct mount *mp) |
703720e4 | 1226 | { |
506bd6d1 | 1227 | return ((hammer2_pfs_t *)mp->mnt_data); |
703720e4 MD |
1228 | } |
1229 | ||
05dd26e4 MD |
1230 | #define LOCKSTART int __nlocks = curthread->td_locks |
1231 | #define LOCKENTER (++curthread->td_locks) | |
1232 | #define LOCKEXIT (--curthread->td_locks) | |
1233 | #define LOCKSTOP KKASSERT(curthread->td_locks == __nlocks) | |
1234 | ||
703720e4 MD |
1235 | extern struct vop_ops hammer2_vnode_vops; |
1236 | extern struct vop_ops hammer2_spec_vops; | |
1237 | extern struct vop_ops hammer2_fifo_vops; | |
1238 | ||
37aa19df | 1239 | extern int hammer2_debug; |
01eabad4 | 1240 | extern int hammer2_cluster_enable; |
e708f8b9 | 1241 | extern int hammer2_hardlink_enable; |
3f5b8b3b | 1242 | extern int hammer2_flush_pipe; |
8138a154 | 1243 | extern int hammer2_synchronous_flush; |
837bd39b | 1244 | extern int hammer2_dio_count; |
0924b3f8 | 1245 | extern long hammer2_limit_dirty_chains; |
f9f4459e | 1246 | extern long hammer2_count_modified_chains; |
01eabad4 MD |
1247 | extern long hammer2_iod_file_read; |
1248 | extern long hammer2_iod_meta_read; | |
1249 | extern long hammer2_iod_indr_read; | |
a98aa0b0 MD |
1250 | extern long hammer2_iod_fmap_read; |
1251 | extern long hammer2_iod_volu_read; | |
01eabad4 | 1252 | extern long hammer2_iod_file_write; |
3f01ebaa MD |
1253 | extern long hammer2_iod_file_wembed; |
1254 | extern long hammer2_iod_file_wzero; | |
1255 | extern long hammer2_iod_file_wdedup; | |
01eabad4 MD |
1256 | extern long hammer2_iod_meta_write; |
1257 | extern long hammer2_iod_indr_write; | |
9061bde5 | 1258 | extern long hammer2_iod_fmap_write; |
01eabad4 MD |
1259 | extern long hammer2_iod_volu_write; |
1260 | extern long hammer2_ioa_file_read; | |
1261 | extern long hammer2_ioa_meta_read; | |
1262 | extern long hammer2_ioa_indr_read; | |
a98aa0b0 MD |
1263 | extern long hammer2_ioa_fmap_read; |
1264 | extern long hammer2_ioa_volu_read; | |
01eabad4 MD |
1265 | extern long hammer2_ioa_file_write; |
1266 | extern long hammer2_ioa_meta_write; | |
1267 | extern long hammer2_ioa_indr_write; | |
9061bde5 | 1268 | extern long hammer2_ioa_fmap_write; |
01eabad4 | 1269 | extern long hammer2_ioa_volu_write; |
37aa19df | 1270 | |
355d67fc MD |
1271 | extern struct objcache *cache_buffer_read; |
1272 | extern struct objcache *cache_buffer_write; | |
2ed4fece | 1273 | extern struct objcache *cache_xops; |
355d67fc | 1274 | |
7cfa8da5 MD |
1275 | /* |
1276 | * hammer2_subr.c | |
1277 | */ | |
3a5aa68f MD |
1278 | #define hammer2_icrc32(buf, size) iscsi_crc32((buf), (size)) |
1279 | #define hammer2_icrc32c(buf, size, crc) iscsi_crc32_ext((buf), (size), (crc)) | |
0c3a8cd0 | 1280 | |
d662271e | 1281 | int hammer2_signal_check(time_t *timep); |
b93cc2e0 MD |
1282 | const char *hammer2_error_str(int error); |
1283 | ||
159c3ca2 | 1284 | void hammer2_inode_lock(hammer2_inode_t *ip, int how); |
b7add675 | 1285 | void hammer2_inode_unlock(hammer2_inode_t *ip); |
c847e838 | 1286 | hammer2_chain_t *hammer2_inode_chain(hammer2_inode_t *ip, int clindex, int how); |
01d71aa5 MD |
1287 | hammer2_chain_t *hammer2_inode_chain_and_parent(hammer2_inode_t *ip, |
1288 | int clindex, hammer2_chain_t **parentp, int how); | |
94491fa0 MD |
1289 | hammer2_mtx_state_t hammer2_inode_lock_temp_release(hammer2_inode_t *ip); |
1290 | void hammer2_inode_lock_temp_restore(hammer2_inode_t *ip, | |
1291 | hammer2_mtx_state_t ostate); | |
1292 | int hammer2_inode_lock_upgrade(hammer2_inode_t *ip); | |
1293 | void hammer2_inode_lock_downgrade(hammer2_inode_t *ip, int); | |
e118c14f | 1294 | |
506bd6d1 MD |
1295 | void hammer2_dev_exlock(hammer2_dev_t *hmp); |
1296 | void hammer2_dev_shlock(hammer2_dev_t *hmp); | |
1297 | void hammer2_dev_unlock(hammer2_dev_t *hmp); | |
703720e4 | 1298 | |
6a5f4fe6 | 1299 | int hammer2_get_dtype(const hammer2_inode_data_t *ipdata); |
159c3ca2 | 1300 | int hammer2_get_vtype(uint8_t type); |
37494cab | 1301 | u_int8_t hammer2_get_obj_type(enum vtype vtype); |
cd4b3d92 | 1302 | void hammer2_time_to_timespec(u_int64_t xtime, struct timespec *ts); |
6a5f4fe6 MD |
1303 | u_int64_t hammer2_timespec_to_time(const struct timespec *ts); |
1304 | u_int32_t hammer2_to_unix_xid(const uuid_t *uuid); | |
b2b78aaa | 1305 | void hammer2_guid_to_uuid(uuid_t *uuid, u_int32_t guid); |
c603b86b | 1306 | void hammer2_trans_manage_init(hammer2_pfs_t *pmp); |
e028fa74 | 1307 | |
7cfa8da5 | 1308 | hammer2_key_t hammer2_dirhash(const unsigned char *name, size_t len); |
1a7cfe5a | 1309 | int hammer2_getradix(size_t bytes); |
7cfa8da5 | 1310 | |
8cce658d | 1311 | int hammer2_calc_logical(hammer2_inode_t *ip, hammer2_off_t uoff, |
1897c66e | 1312 | hammer2_key_t *lbasep, hammer2_key_t *leofp); |
7a9b14a0 | 1313 | int hammer2_calc_physical(hammer2_inode_t *ip, hammer2_key_t lbase); |
b2b78aaa | 1314 | void hammer2_update_time(uint64_t *timep); |
278ab2b2 | 1315 | void hammer2_adjreadcounter(hammer2_blockref_t *bref, size_t bytes); |
8cce658d | 1316 | |
7cfa8da5 MD |
1317 | /* |
1318 | * hammer2_inode.c | |
1319 | */ | |
c603b86b | 1320 | struct vnode *hammer2_igetv(hammer2_inode_t *ip, int *errorp); |
506bd6d1 | 1321 | hammer2_inode_t *hammer2_inode_lookup(hammer2_pfs_t *pmp, |
9797e933 | 1322 | hammer2_tid_t inum); |
8cd26e36 MD |
1323 | hammer2_inode_t *hammer2_inode_get(hammer2_pfs_t *pmp, hammer2_inode_t *dip, |
1324 | hammer2_cluster_t *cluster, int idx); | |
7cfa8da5 MD |
1325 | void hammer2_inode_free(hammer2_inode_t *ip); |
1326 | void hammer2_inode_ref(hammer2_inode_t *ip); | |
1327 | void hammer2_inode_drop(hammer2_inode_t *ip); | |
ea155208 | 1328 | void hammer2_inode_repoint(hammer2_inode_t *ip, hammer2_inode_t *pip, |
278ab2b2 | 1329 | hammer2_cluster_t *cluster); |
a6cf1052 MD |
1330 | void hammer2_inode_repoint_one(hammer2_inode_t *ip, hammer2_cluster_t *cluster, |
1331 | int idx); | |
c603b86b | 1332 | void hammer2_inode_modify(hammer2_inode_t *ip); |
b5b45574 | 1333 | void hammer2_inode_run_sideq(hammer2_pfs_t *pmp); |
6934ae32 | 1334 | |
c603b86b | 1335 | hammer2_inode_t *hammer2_inode_create(hammer2_inode_t *dip, |
e708f8b9 | 1336 | struct vattr *vap, struct ucred *cred, |
b7add675 | 1337 | const uint8_t *name, size_t name_len, hammer2_key_t lhc, |
e12ae3a5 | 1338 | hammer2_key_t inum, uint8_t type, uint8_t target_type, |
506bd6d1 | 1339 | int flags, int *errorp); |
01d71aa5 | 1340 | int hammer2_inode_connect(hammer2_inode_t *dip, hammer2_inode_t *ip, |
e12ae3a5 MD |
1341 | const char *name, size_t name_len, |
1342 | hammer2_key_t lhc); | |
0dea3156 | 1343 | hammer2_inode_t *hammer2_inode_common_parent(hammer2_inode_t *fdip, |
2efe493b | 1344 | hammer2_inode_t *tdip, int *errorp, int ishardlink); |
53f84d31 | 1345 | void hammer2_inode_chain_sync(hammer2_inode_t *ip); |
e12ae3a5 | 1346 | int hammer2_inode_unlink_finisher(hammer2_inode_t *ip, int isopen); |
506bd6d1 | 1347 | void hammer2_inode_install_hidden(hammer2_pfs_t *pmp); |
ae183399 | 1348 | |
7cfa8da5 MD |
1349 | /* |
1350 | * hammer2_chain.c | |
1351 | */ | |
506bd6d1 MD |
1352 | void hammer2_voldata_lock(hammer2_dev_t *hmp); |
1353 | void hammer2_voldata_unlock(hammer2_dev_t *hmp); | |
1354 | void hammer2_voldata_modify(hammer2_dev_t *hmp); | |
1355 | hammer2_chain_t *hammer2_chain_alloc(hammer2_dev_t *hmp, | |
1356 | hammer2_pfs_t *pmp, | |
fdf62707 | 1357 | hammer2_blockref_t *bref); |
23c7c7dd | 1358 | void hammer2_chain_core_init(hammer2_chain_t *chain); |
0dea3156 MD |
1359 | void hammer2_chain_ref(hammer2_chain_t *chain); |
1360 | void hammer2_chain_drop(hammer2_chain_t *chain); | |
23c7c7dd | 1361 | void hammer2_chain_lock(hammer2_chain_t *chain, int how); |
2efe493b | 1362 | void hammer2_chain_lock_downgrade(hammer2_chain_t *chain); |
f9f4459e MD |
1363 | void hammer2_chain_push_shared_lock(hammer2_chain_t *chain); |
1364 | void hammer2_chain_pull_shared_lock(hammer2_chain_t *chain); | |
f1c7c224 | 1365 | void hammer2_chain_load_data(hammer2_chain_t *chain); |
bca9f8e6 MD |
1366 | const hammer2_media_data_t *hammer2_chain_rdata(hammer2_chain_t *chain); |
1367 | hammer2_media_data_t *hammer2_chain_wdata(hammer2_chain_t *chain); | |
e2163f5b MD |
1368 | int hammer2_chain_snapshot(hammer2_chain_t *chain, hammer2_ioc_pfs_t *pmp, |
1369 | hammer2_tid_t mtid); | |
bca9f8e6 | 1370 | |
c603b86b MD |
1371 | int hammer2_chain_hardlink_find(hammer2_inode_t *dip, |
1372 | hammer2_chain_t **parentp, | |
e12ae3a5 MD |
1373 | hammer2_chain_t **chainp, |
1374 | int flags); | |
3f01ebaa MD |
1375 | void hammer2_chain_modify(hammer2_chain_t *chain, hammer2_tid_t mtid, |
1376 | hammer2_off_t dedup_off, int flags); | |
d34788ef | 1377 | void hammer2_chain_modify_ip(hammer2_inode_t *ip, hammer2_chain_t *chain, |
e2163f5b | 1378 | hammer2_tid_t mtid, int flags); |
c603b86b | 1379 | void hammer2_chain_resize(hammer2_inode_t *ip, hammer2_chain_t *parent, |
e2163f5b | 1380 | hammer2_chain_t *chain, |
3f01ebaa MD |
1381 | hammer2_tid_t mtid, hammer2_off_t dedup_off, |
1382 | int nradix, int flags); | |
0dea3156 MD |
1383 | void hammer2_chain_unlock(hammer2_chain_t *chain); |
1384 | void hammer2_chain_wait(hammer2_chain_t *chain); | |
8138a154 MD |
1385 | hammer2_chain_t *hammer2_chain_get(hammer2_chain_t *parent, int generation, |
1386 | hammer2_blockref_t *bref); | |
0dea3156 MD |
1387 | hammer2_chain_t *hammer2_chain_lookup_init(hammer2_chain_t *parent, int flags); |
1388 | void hammer2_chain_lookup_done(hammer2_chain_t *parent); | |
e12ae3a5 | 1389 | hammer2_chain_t *hammer2_chain_getparent(hammer2_chain_t **parentp, int how); |
0dea3156 | 1390 | hammer2_chain_t *hammer2_chain_lookup(hammer2_chain_t **parentp, |
1897c66e | 1391 | hammer2_key_t *key_nextp, |
c667909f | 1392 | hammer2_key_t key_beg, hammer2_key_t key_end, |
b8ba9690 | 1393 | int *cache_indexp, int flags); |
0dea3156 | 1394 | hammer2_chain_t *hammer2_chain_next(hammer2_chain_t **parentp, |
5c23d7f1 | 1395 | hammer2_chain_t *chain, |
1897c66e | 1396 | hammer2_key_t *key_nextp, |
c667909f | 1397 | hammer2_key_t key_beg, hammer2_key_t key_end, |
1897c66e | 1398 | int *cache_indexp, int flags); |
125966e8 MD |
1399 | hammer2_blockref_t *hammer2_chain_scan(hammer2_chain_t *parent, |
1400 | hammer2_chain_t **chainp, | |
1401 | hammer2_blockref_t *bref, | |
1402 | int *firstp, int *cache_indexp, int flags); | |
91abd410 | 1403 | |
c603b86b | 1404 | int hammer2_chain_create(hammer2_chain_t **parentp, |
e2163f5b | 1405 | hammer2_chain_t **chainp, hammer2_pfs_t *pmp, |
5c23d7f1 | 1406 | hammer2_key_t key, int keybits, |
3f01ebaa MD |
1407 | int type, size_t bytes, hammer2_tid_t mtid, |
1408 | hammer2_off_t dedup_off, int flags); | |
c603b86b | 1409 | void hammer2_chain_rename(hammer2_blockref_t *bref, |
da6f36f4 | 1410 | hammer2_chain_t **parentp, |
e2163f5b MD |
1411 | hammer2_chain_t *chain, |
1412 | hammer2_tid_t mtid, int flags); | |
1413 | void hammer2_chain_delete(hammer2_chain_t *parent, hammer2_chain_t *chain, | |
1414 | hammer2_tid_t mtid, int flags); | |
c603b86b | 1415 | void hammer2_chain_setflush(hammer2_chain_t *chain); |
51a0d27c | 1416 | void hammer2_chain_countbrefs(hammer2_chain_t *chain, |
1897c66e | 1417 | hammer2_blockref_t *base, int count); |
21a90458 MD |
1418 | hammer2_chain_t *hammer2_chain_bulksnap(hammer2_chain_t *chain); |
1419 | void hammer2_chain_bulkdrop(hammer2_chain_t *copy); | |
1897c66e | 1420 | |
a71db85d MD |
1421 | void hammer2_chain_setcheck(hammer2_chain_t *chain, void *bdata); |
1422 | int hammer2_chain_testcheck(hammer2_chain_t *chain, void *bdata); | |
1423 | ||
1424 | ||
506bd6d1 MD |
1425 | void hammer2_pfs_memory_wait(hammer2_pfs_t *pmp); |
1426 | void hammer2_pfs_memory_inc(hammer2_pfs_t *pmp); | |
1427 | void hammer2_pfs_memory_wakeup(hammer2_pfs_t *pmp); | |
278ab2b2 | 1428 | |
c603b86b | 1429 | void hammer2_base_delete(hammer2_chain_t *chain, |
51a0d27c | 1430 | hammer2_blockref_t *base, int count, |
a7720be7 | 1431 | int *cache_indexp, hammer2_chain_t *child); |
c603b86b | 1432 | void hammer2_base_insert(hammer2_chain_t *chain, |
51a0d27c | 1433 | hammer2_blockref_t *base, int count, |
a7720be7 | 1434 | int *cache_indexp, hammer2_chain_t *child); |
0dea3156 | 1435 | |
53f84d31 MD |
1436 | /* |
1437 | * hammer2_flush.c | |
1438 | */ | |
1439 | void hammer2_flush(hammer2_chain_t *chain, int istop); | |
1440 | void hammer2_flush_quick(hammer2_dev_t *hmp); | |
1441 | void hammer2_delayed_flush(hammer2_chain_t *chain); | |
1442 | ||
0dea3156 MD |
1443 | /* |
1444 | * hammer2_trans.c | |
1445 | */ | |
c603b86b | 1446 | void hammer2_trans_init(hammer2_pfs_t *pmp, uint32_t flags); |
e2163f5b MD |
1447 | hammer2_tid_t hammer2_trans_sub(hammer2_pfs_t *pmp); |
1448 | void hammer2_trans_clear_preflush(hammer2_pfs_t *pmp); | |
c603b86b MD |
1449 | void hammer2_trans_done(hammer2_pfs_t *pmp); |
1450 | hammer2_tid_t hammer2_trans_newinum(hammer2_pfs_t *pmp); | |
c7916d0b | 1451 | void hammer2_trans_assert_strategy(hammer2_pfs_t *pmp); |
50e4f8f4 | 1452 | |
2910a90c MD |
1453 | /* |
1454 | * hammer2_ioctl.c | |
1455 | */ | |
1456 | int hammer2_ioctl(hammer2_inode_t *ip, u_long com, void *data, | |
1457 | int fflag, struct ucred *cred); | |
1458 | ||
fdf62707 MD |
1459 | /* |
1460 | * hammer2_io.c | |
1461 | */ | |
fdf62707 | 1462 | void hammer2_io_putblk(hammer2_io_t **diop); |
506bd6d1 | 1463 | void hammer2_io_cleanup(hammer2_dev_t *hmp, struct hammer2_io_tree *tree); |
fdf62707 | 1464 | char *hammer2_io_data(hammer2_io_t *dio, off_t lbase); |
3f01ebaa | 1465 | hammer2_io_t *hammer2_io_getquick(hammer2_dev_t *hmp, off_t lbase, int lsize); |
506bd6d1 | 1466 | void hammer2_io_getblk(hammer2_dev_t *hmp, off_t lbase, int lsize, |
bca9f8e6 MD |
1467 | hammer2_iocb_t *iocb); |
1468 | void hammer2_io_complete(hammer2_iocb_t *iocb); | |
1469 | void hammer2_io_callback(struct bio *bio); | |
1470 | void hammer2_iocb_wait(hammer2_iocb_t *iocb); | |
506bd6d1 | 1471 | int hammer2_io_new(hammer2_dev_t *hmp, off_t lbase, int lsize, |
fdf62707 | 1472 | hammer2_io_t **diop); |
506bd6d1 | 1473 | int hammer2_io_newnz(hammer2_dev_t *hmp, off_t lbase, int lsize, |
fdf62707 | 1474 | hammer2_io_t **diop); |
506bd6d1 | 1475 | int hammer2_io_newq(hammer2_dev_t *hmp, off_t lbase, int lsize, |
fdf62707 | 1476 | hammer2_io_t **diop); |
506bd6d1 | 1477 | int hammer2_io_bread(hammer2_dev_t *hmp, off_t lbase, int lsize, |
fdf62707 | 1478 | hammer2_io_t **diop); |
fdf62707 MD |
1479 | void hammer2_io_bawrite(hammer2_io_t **diop); |
1480 | void hammer2_io_bdwrite(hammer2_io_t **diop); | |
1481 | int hammer2_io_bwrite(hammer2_io_t **diop); | |
8138a154 | 1482 | int hammer2_io_isdirty(hammer2_io_t *dio); |
fdf62707 MD |
1483 | void hammer2_io_setdirty(hammer2_io_t *dio); |
1484 | void hammer2_io_setinval(hammer2_io_t *dio, u_int bytes); | |
1485 | void hammer2_io_brelse(hammer2_io_t **diop); | |
1486 | void hammer2_io_bqrelse(hammer2_io_t **diop); | |
fdf62707 | 1487 | |
2ed4fece | 1488 | /* |
3f01ebaa MD |
1489 | * hammer2_thread.c |
1490 | */ | |
1491 | void hammer2_thr_create(hammer2_thread_t *thr, hammer2_pfs_t *pmp, | |
1492 | const char *id, int clindex, int repidx, | |
1493 | void (*func)(void *arg)); | |
1494 | void hammer2_thr_delete(hammer2_thread_t *thr); | |
1495 | void hammer2_thr_remaster(hammer2_thread_t *thr); | |
1496 | void hammer2_thr_freeze_async(hammer2_thread_t *thr); | |
1497 | void hammer2_thr_freeze(hammer2_thread_t *thr); | |
1498 | void hammer2_thr_unfreeze(hammer2_thread_t *thr); | |
1499 | int hammer2_thr_break(hammer2_thread_t *thr); | |
1500 | void hammer2_primary_xops_thread(void *arg); | |
1501 | ||
1502 | /* | |
1503 | * hammer2_thread.c (XOP API) | |
2ed4fece | 1504 | */ |
c847e838 | 1505 | void hammer2_xop_group_init(hammer2_pfs_t *pmp, hammer2_xop_group_t *xgrp); |
e2163f5b | 1506 | void *hammer2_xop_alloc(hammer2_inode_t *ip, int flags); |
e12ae3a5 MD |
1507 | void hammer2_xop_setname(hammer2_xop_head_t *xop, |
1508 | const char *name, size_t name_len); | |
1509 | void hammer2_xop_setname2(hammer2_xop_head_t *xop, | |
1510 | const char *name, size_t name_len); | |
1511 | void hammer2_xop_setip2(hammer2_xop_head_t *xop, hammer2_inode_t *ip2); | |
1512 | void hammer2_xop_setip3(hammer2_xop_head_t *xop, hammer2_inode_t *ip3); | |
c603b86b | 1513 | void hammer2_xop_reinit(hammer2_xop_head_t *xop); |
c847e838 MD |
1514 | void hammer2_xop_helper_create(hammer2_pfs_t *pmp); |
1515 | void hammer2_xop_helper_cleanup(hammer2_pfs_t *pmp); | |
c603b86b | 1516 | void hammer2_xop_start(hammer2_xop_head_t *xop, hammer2_xop_func_t func); |
01d71aa5 MD |
1517 | void hammer2_xop_start_except(hammer2_xop_head_t *xop, hammer2_xop_func_t func, |
1518 | int notidx); | |
c603b86b | 1519 | int hammer2_xop_collect(hammer2_xop_head_t *xop, int flags); |
c847e838 MD |
1520 | void hammer2_xop_retire(hammer2_xop_head_t *xop, uint32_t mask); |
1521 | int hammer2_xop_active(hammer2_xop_head_t *xop); | |
1522 | int hammer2_xop_feed(hammer2_xop_head_t *xop, hammer2_chain_t *chain, | |
1523 | int clindex, int error); | |
1524 | ||
b7add675 | 1525 | /* |
3f01ebaa MD |
1526 | * hammer2_synchro.c |
1527 | */ | |
1528 | void hammer2_primary_sync_thread(void *arg); | |
1529 | ||
1530 | /* | |
1531 | * XOP backends in hammer2_xops.c, primarily for VNOPS. Other XOP backends | |
1532 | * may be integrated into other source files. | |
b7add675 | 1533 | */ |
01d71aa5 | 1534 | void hammer2_xop_ipcluster(hammer2_xop_t *xop, int clidx); |
c847e838 | 1535 | void hammer2_xop_readdir(hammer2_xop_t *xop, int clidx); |
c603b86b | 1536 | void hammer2_xop_nresolve(hammer2_xop_t *xop, int clidx); |
e12ae3a5 MD |
1537 | void hammer2_xop_unlink(hammer2_xop_t *xop, int clidx); |
1538 | void hammer2_xop_nrename(hammer2_xop_t *xop, int clidx); | |
1539 | void hammer2_xop_nlink(hammer2_xop_t *xop, int clidx); | |
b7add675 | 1540 | void hammer2_xop_scanlhc(hammer2_xop_t *xop, int clidx); |
01d71aa5 | 1541 | void hammer2_xop_scanall(hammer2_xop_t *xop, int clidx); |
b7add675 | 1542 | void hammer2_xop_lookup(hammer2_xop_t *xop, int clidx); |
c603b86b MD |
1543 | void hammer2_inode_xop_create(hammer2_xop_t *xop, int clidx); |
1544 | void hammer2_inode_xop_destroy(hammer2_xop_t *xop, int clidx); | |
53f84d31 | 1545 | void hammer2_inode_xop_chain_sync(hammer2_xop_t *xop, int clidx); |
b7add675 | 1546 | void hammer2_inode_xop_unlinkall(hammer2_xop_t *xop, int clidx); |
e12ae3a5 | 1547 | void hammer2_inode_xop_connect(hammer2_xop_t *xop, int clidx); |
12ff971c | 1548 | void hammer2_inode_xop_flush(hammer2_xop_t *xop, int clidx); |
2ed4fece | 1549 | |
9b8b748f MD |
1550 | /* |
1551 | * hammer2_msgops.c | |
1552 | */ | |
3a5aa68f MD |
1553 | int hammer2_msg_dbg_rcvmsg(kdmsg_msg_t *msg); |
1554 | int hammer2_msg_adhoc_input(kdmsg_msg_t *msg); | |
26bf1a36 | 1555 | |
1a34728c MD |
1556 | /* |
1557 | * hammer2_vfsops.c | |
1558 | */ | |
506bd6d1 | 1559 | void hammer2_volconf_update(hammer2_dev_t *hmp, int index); |
8138a154 | 1560 | void hammer2_dump_chain(hammer2_chain_t *chain, int tab, int *countp, char pfx); |
a7720be7 | 1561 | int hammer2_vfs_sync(struct mount *mp, int waitflags); |
b7add675 | 1562 | hammer2_pfs_t *hammer2_pfsalloc(hammer2_chain_t *chain, |
506bd6d1 | 1563 | const hammer2_inode_data_t *ripdata, |
b02c0ae6 MD |
1564 | hammer2_tid_t modify_tid, |
1565 | hammer2_dev_t *force_local); | |
506bd6d1 MD |
1566 | |
1567 | void hammer2_lwinprog_ref(hammer2_pfs_t *pmp); | |
1568 | void hammer2_lwinprog_drop(hammer2_pfs_t *pmp); | |
d34788ef | 1569 | void hammer2_lwinprog_wait(hammer2_pfs_t *pmp, int pipe); |
1a34728c | 1570 | |
df9ea374 MD |
1571 | /* |
1572 | * hammer2_freemap.c | |
1573 | */ | |
c603b86b MD |
1574 | int hammer2_freemap_alloc(hammer2_chain_t *chain, size_t bytes); |
1575 | void hammer2_freemap_adjust(hammer2_dev_t *hmp, | |
91abd410 MD |
1576 | hammer2_blockref_t *bref, int how); |
1577 | ||
278ab2b2 MD |
1578 | /* |
1579 | * hammer2_cluster.c | |
1580 | */ | |
278ab2b2 | 1581 | uint8_t hammer2_cluster_type(hammer2_cluster_t *cluster); |
bca9f8e6 | 1582 | const hammer2_media_data_t *hammer2_cluster_rdata(hammer2_cluster_t *cluster); |
6a5f4fe6 | 1583 | hammer2_media_data_t *hammer2_cluster_wdata(hammer2_cluster_t *cluster); |
278ab2b2 | 1584 | hammer2_cluster_t *hammer2_cluster_from_chain(hammer2_chain_t *chain); |
278ab2b2 | 1585 | void hammer2_cluster_bref(hammer2_cluster_t *cluster, hammer2_blockref_t *bref); |
506bd6d1 | 1586 | hammer2_cluster_t *hammer2_cluster_alloc(hammer2_pfs_t *pmp, |
c603b86b | 1587 | hammer2_blockref_t *bref); |
278ab2b2 MD |
1588 | void hammer2_cluster_ref(hammer2_cluster_t *cluster); |
1589 | void hammer2_cluster_drop(hammer2_cluster_t *cluster); | |
23c7c7dd | 1590 | void hammer2_cluster_lock(hammer2_cluster_t *cluster, int how); |
c847e838 MD |
1591 | int hammer2_cluster_check(hammer2_cluster_t *cluster, hammer2_key_t lokey, |
1592 | int flags); | |
23c7c7dd | 1593 | void hammer2_cluster_resolve(hammer2_cluster_t *cluster); |
0057d3b8 | 1594 | void hammer2_cluster_forcegood(hammer2_cluster_t *cluster); |
fe73aa5d | 1595 | hammer2_cluster_t *hammer2_cluster_copy(hammer2_cluster_t *ocluster); |
278ab2b2 | 1596 | void hammer2_cluster_unlock(hammer2_cluster_t *cluster); |
da6f36f4 | 1597 | |
506bd6d1 | 1598 | int hammer2_bulkfree_pass(hammer2_dev_t *hmp, |
3148f677 | 1599 | struct hammer2_ioc_bulkfree *bfi); |
df9ea374 | 1600 | |
d157d4dc MD |
1601 | /* |
1602 | * hammer2_iocom.c | |
1603 | */ | |
506bd6d1 MD |
1604 | void hammer2_iocom_init(hammer2_dev_t *hmp); |
1605 | void hammer2_iocom_uninit(hammer2_dev_t *hmp); | |
1606 | void hammer2_cluster_reconnect(hammer2_dev_t *hmp, struct file *fp); | |
d157d4dc | 1607 | |
b2900845 MD |
1608 | /* |
1609 | * hammer2_strategy.c | |
1610 | */ | |
1611 | int hammer2_vop_strategy(struct vop_strategy_args *ap); | |
1612 | int hammer2_vop_bmap(struct vop_bmap_args *ap); | |
3c8b994d | 1613 | void hammer2_write_thread(void *arg); |
2ed4fece | 1614 | void hammer2_bioq_sync(hammer2_pfs_t *pmp); |
125966e8 | 1615 | void hammer2_dedup_clear(hammer2_dev_t *hmp); |
b2900845 | 1616 | |
47902fef VS |
1617 | #endif /* !_KERNEL */ |
1618 | #endif /* !_VFS_HAMMER2_HAMMER2_H_ */ |