Joe Thornber | 3241b1d | 2011-10-31 20:19:11 +0000 | [diff] [blame] | 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 */ |