diff options
author | Joe Thornber <thornber@redhat.com> | 2011-10-31 16:19:11 -0400 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2011-10-31 16:19:11 -0400 |
commit | 3241b1d3e0aaafbfcd320f4d71ade629728cc4f4 (patch) | |
tree | 499461f724d4db3d7118641f4a20f5be23549edd /drivers/md/persistent-data/dm-transaction-manager.h | |
parent | 95d402f057f2e208e4631893f6cd4a59c7c05e41 (diff) |
dm: add persistent data library
The persistent-data library offers a re-usable framework for the storage
and management of on-disk metadata in device-mapper targets.
It's used by the thin-provisioning target in the next patch and in an
upcoming hierarchical storage target.
For further information, please read
Documentation/device-mapper/persistent-data.txt
Signed-off-by: Joe Thornber <thornber@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md/persistent-data/dm-transaction-manager.h')
-rw-r--r-- | drivers/md/persistent-data/dm-transaction-manager.h | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/drivers/md/persistent-data/dm-transaction-manager.h b/drivers/md/persistent-data/dm-transaction-manager.h new file mode 100644 index 000000000000..6da784871db4 --- /dev/null +++ b/drivers/md/persistent-data/dm-transaction-manager.h | |||
@@ -0,0 +1,130 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Red Hat, Inc. | ||
3 | * | ||
4 | * This file is released under the GPL. | ||
5 | */ | ||
6 | |||
7 | #ifndef _LINUX_DM_TRANSACTION_MANAGER_H | ||
8 | #define _LINUX_DM_TRANSACTION_MANAGER_H | ||
9 | |||
10 | #include "dm-block-manager.h" | ||
11 | |||
12 | struct dm_transaction_manager; | ||
13 | struct dm_space_map; | ||
14 | |||
15 | /*----------------------------------------------------------------*/ | ||
16 | |||
17 | /* | ||
18 | * This manages the scope of a transaction. It also enforces immutability | ||
19 | * of the on-disk data structures by limiting access to writeable blocks. | ||
20 | * | ||
21 | * Clients should not fiddle with the block manager directly. | ||
22 | */ | ||
23 | |||
24 | void dm_tm_destroy(struct dm_transaction_manager *tm); | ||
25 | |||
26 | /* | ||
27 | * The non-blocking version of a transaction manager is intended for use in | ||
28 | * fast path code that needs to do lookups e.g. a dm mapping function. | ||
29 | * You create the non-blocking variant from a normal tm. The interface is | ||
30 | * the same, except that most functions will just return -EWOULDBLOCK. | ||
31 | * Methods that return void yet may block should not be called on a clone | ||
32 | * viz. dm_tm_inc, dm_tm_dec. Call dm_tm_destroy() as you would with a normal | ||
33 | * tm when you've finished with it. You may not destroy the original prior | ||
34 | * to clones. | ||
35 | */ | ||
36 | struct dm_transaction_manager *dm_tm_create_non_blocking_clone(struct dm_transaction_manager *real); | ||
37 | |||
38 | /* | ||
39 | * We use a 2-phase commit here. | ||
40 | * | ||
41 | * i) In the first phase the block manager is told to start flushing, and | ||
42 | * the changes to the space map are written to disk. You should interrogate | ||
43 | * your particular space map to get detail of its root node etc. to be | ||
44 | * included in your superblock. | ||
45 | * | ||
46 | * ii) @root will be committed last. You shouldn't use more than the | ||
47 | * first 512 bytes of @root if you wish the transaction to survive a power | ||
48 | * failure. You *must* have a write lock held on @root for both stage (i) | ||
49 | * and (ii). The commit will drop the write 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 *root); | ||
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 | int 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 | |||
105 | void dm_tm_dec(struct dm_transaction_manager *tm, dm_block_t b); | ||
106 | |||
107 | int dm_tm_ref(struct dm_transaction_manager *tm, dm_block_t b, | ||
108 | uint32_t *result); | ||
109 | |||
110 | struct dm_block_manager *dm_tm_get_bm(struct dm_transaction_manager *tm); | ||
111 | |||
112 | /* | ||
113 | * A little utility that ties the knot by producing a transaction manager | ||
114 | * that has a space map managed by the transaction manager... | ||
115 | * | ||
116 | * Returns a tm that has an open transaction to write the new disk sm. | ||
117 | * Caller should store the new sm root and commit. | ||
118 | */ | ||
119 | int dm_tm_create_with_sm(struct dm_block_manager *bm, dm_block_t sb_location, | ||
120 | struct dm_block_validator *sb_validator, | ||
121 | struct dm_transaction_manager **tm, | ||
122 | struct dm_space_map **sm, struct dm_block **sblock); | ||
123 | |||
124 | int dm_tm_open_with_sm(struct dm_block_manager *bm, dm_block_t sb_location, | ||
125 | struct dm_block_validator *sb_validator, | ||
126 | size_t root_offset, size_t root_max_len, | ||
127 | struct dm_transaction_manager **tm, | ||
128 | struct dm_space_map **sm, struct dm_block **sblock); | ||
129 | |||
130 | #endif /* _LINUX_DM_TRANSACTION_MANAGER_H */ | ||