1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* |
3 | * Copyright (C) 2011 Red Hat, Inc. |
4 | * |
5 | * This file is released under the GPL. |
6 | */ |
7 | |
8 | #ifndef _LINUX_DM_TRANSACTION_MANAGER_H |
9 | #define _LINUX_DM_TRANSACTION_MANAGER_H |
10 | |
11 | #include "dm-block-manager.h" |
12 | |
13 | struct dm_transaction_manager; |
14 | struct dm_space_map; |
15 | |
16 | /*----------------------------------------------------------------*/ |
17 | |
18 | /* |
19 | * This manages the scope of a transaction. It also enforces immutability |
20 | * of the on-disk data structures by limiting access to writeable blocks. |
21 | * |
22 | * Clients should not fiddle with the block manager directly. |
23 | */ |
24 | |
25 | void dm_tm_destroy(struct dm_transaction_manager *tm); |
26 | |
27 | /* |
28 | * The non-blocking version of a transaction manager is intended for use in |
29 | * fast path code that needs to do lookups e.g. a dm mapping function. |
30 | * You create the non-blocking variant from a normal tm. The interface is |
31 | * the same, except that most functions will just return -EWOULDBLOCK. |
32 | * Methods that return void yet may block should not be called on a clone |
33 | * viz. dm_tm_inc, dm_tm_dec. Call dm_tm_destroy() as you would with a normal |
34 | * tm when you've finished with it. You may not destroy the original prior |
35 | * to clones. |
36 | */ |
37 | struct dm_transaction_manager *dm_tm_create_non_blocking_clone(struct dm_transaction_manager *real); |
38 | |
39 | /* |
40 | * We use a 2-phase commit here. |
41 | * |
42 | * i) Make all changes for the transaction *except* for the superblock. |
43 | * Then call dm_tm_pre_commit() to flush them to disk. |
44 | * |
45 | * ii) Lock your superblock. Update. Then call dm_tm_commit() which will |
46 | * unlock the superblock and flush it. No other blocks should be updated |
47 | * during this period. Care should be taken to never unlock a partially |
48 | * updated superblock; perform any operations that could fail *before* you |
49 | * take the superblock lock. |
50 | */ |
51 | int dm_tm_pre_commit(struct dm_transaction_manager *tm); |
52 | int dm_tm_commit(struct dm_transaction_manager *tm, struct dm_block *superblock); |
53 | |
54 | /* |
55 | * These methods are the only way to get hold of a writeable block. |
56 | */ |
57 | |
58 | /* |
59 | * dm_tm_new_block() is pretty self-explanatory. Make sure you do actually |
60 | * write to the whole of @data before you unlock, otherwise you could get |
61 | * a data leak. (The other option is for tm_new_block() to zero new blocks |
62 | * before handing them out, which will be redundant in most, if not all, |
63 | * cases). |
64 | * Zeroes the new block and returns with write lock held. |
65 | */ |
66 | int dm_tm_new_block(struct dm_transaction_manager *tm, |
67 | struct dm_block_validator *v, |
68 | struct dm_block **result); |
69 | |
70 | /* |
71 | * dm_tm_shadow_block() allocates a new block and copies the data from @orig |
72 | * to it. It then decrements the reference count on original block. Use |
73 | * this to update the contents of a block in a data structure, don't |
74 | * confuse this with a clone - you shouldn't access the orig block after |
75 | * this operation. Because the tm knows the scope of the transaction it |
76 | * can optimise requests for a shadow of a shadow to a no-op. Don't forget |
77 | * to unlock when you've finished with the shadow. |
78 | * |
79 | * The @inc_children flag is used to tell the caller whether it needs to |
80 | * adjust reference counts for children. (Data in the block may refer to |
81 | * other blocks.) |
82 | * |
83 | * Shadowing implicitly drops a reference on @orig so you must not have |
84 | * it locked when you call this. |
85 | */ |
86 | int dm_tm_shadow_block(struct dm_transaction_manager *tm, dm_block_t orig, |
87 | struct dm_block_validator *v, |
88 | struct dm_block **result, int *inc_children); |
89 | |
90 | /* |
91 | * Read access. You can lock any block you want. If there's a write lock |
92 | * on it outstanding then it'll block. |
93 | */ |
94 | int dm_tm_read_lock(struct dm_transaction_manager *tm, dm_block_t b, |
95 | struct dm_block_validator *v, |
96 | struct dm_block **result); |
97 | |
98 | void dm_tm_unlock(struct dm_transaction_manager *tm, struct dm_block *b); |
99 | |
100 | /* |
101 | * Functions for altering the reference count of a block directly. |
102 | */ |
103 | void dm_tm_inc(struct dm_transaction_manager *tm, dm_block_t b); |
104 | void dm_tm_inc_range(struct dm_transaction_manager *tm, dm_block_t b, dm_block_t e); |
105 | void dm_tm_dec(struct dm_transaction_manager *tm, dm_block_t b); |
106 | void dm_tm_dec_range(struct dm_transaction_manager *tm, dm_block_t b, dm_block_t e); |
107 | |
108 | /* |
109 | * Builds up runs of adjacent blocks, and then calls the given fn |
110 | * (typically dm_tm_inc/dec). Very useful when you have to perform |
111 | * the same tm operation on all values in a btree leaf. |
112 | */ |
113 | typedef void (*dm_tm_run_fn)(struct dm_transaction_manager *, dm_block_t, dm_block_t); |
114 | void dm_tm_with_runs(struct dm_transaction_manager *tm, |
115 | const __le64 *value_le, unsigned int count, dm_tm_run_fn fn); |
116 | |
117 | int dm_tm_ref(struct dm_transaction_manager *tm, dm_block_t b, uint32_t *result); |
118 | |
119 | /* |
120 | * Finds out if a given block is shared (ie. has a reference count higher |
121 | * than one). |
122 | */ |
123 | int dm_tm_block_is_shared(struct dm_transaction_manager *tm, dm_block_t b, |
124 | int *result); |
125 | |
126 | struct dm_block_manager *dm_tm_get_bm(struct dm_transaction_manager *tm); |
127 | |
128 | /* |
129 | * If you're using a non-blocking clone the tm will build up a list of |
130 | * requested blocks that weren't in core. This call will request those |
131 | * blocks to be prefetched. |
132 | */ |
133 | void dm_tm_issue_prefetches(struct dm_transaction_manager *tm); |
134 | |
135 | /* |
136 | * A little utility that ties the knot by producing a transaction manager |
137 | * that has a space map managed by the transaction manager... |
138 | * |
139 | * Returns a tm that has an open transaction to write the new disk sm. |
140 | * Caller should store the new sm root and commit. |
141 | * |
142 | * The superblock location is passed so the metadata space map knows it |
143 | * shouldn't be used. |
144 | */ |
145 | int dm_tm_create_with_sm(struct dm_block_manager *bm, dm_block_t sb_location, |
146 | struct dm_transaction_manager **tm, |
147 | struct dm_space_map **sm); |
148 | |
149 | int dm_tm_open_with_sm(struct dm_block_manager *bm, dm_block_t sb_location, |
150 | void *sm_root, size_t root_len, |
151 | struct dm_transaction_manager **tm, |
152 | struct dm_space_map **sm); |
153 | |
154 | #endif /* _LINUX_DM_TRANSACTION_MANAGER_H */ |
155 | |