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 | * |
Joe Thornber | a9d4539 | 2014-03-27 14:13:20 +0000 | [diff] [blame] | 41 | * i) Make all changes for the transaction *except* for the superblock. |
| 42 | * Then call dm_tm_pre_commit() to flush them to disk. |
Joe Thornber | 3241b1d | 2011-10-31 20:19:11 +0000 | [diff] [blame] | 43 | * |
Joe Thornber | a9d4539 | 2014-03-27 14:13:20 +0000 | [diff] [blame] | 44 | * ii) Lock your superblock. Update. Then call dm_tm_commit() which will |
| 45 | * unlock the superblock and flush it. No other blocks should be updated |
| 46 | * during this period. Care should be taken to never unlock a partially |
| 47 | * updated superblock; perform any operations that could fail *before* you |
| 48 | * take the superblock lock. |
Joe Thornber | 3241b1d | 2011-10-31 20:19:11 +0000 | [diff] [blame] | 49 | */ |
| 50 | int dm_tm_pre_commit(struct dm_transaction_manager *tm); |
Joe Thornber | a9d4539 | 2014-03-27 14:13:20 +0000 | [diff] [blame] | 51 | int dm_tm_commit(struct dm_transaction_manager *tm, struct dm_block *superblock); |
Joe Thornber | 3241b1d | 2011-10-31 20:19:11 +0000 | [diff] [blame] | 52 | |
| 53 | /* |
| 54 | * These methods are the only way to get hold of a writeable block. |
| 55 | */ |
| 56 | |
| 57 | /* |
| 58 | * dm_tm_new_block() is pretty self-explanatory. Make sure you do actually |
| 59 | * write to the whole of @data before you unlock, otherwise you could get |
| 60 | * a data leak. (The other option is for tm_new_block() to zero new blocks |
| 61 | * before handing them out, which will be redundant in most, if not all, |
| 62 | * cases). |
| 63 | * Zeroes the new block and returns with write lock held. |
| 64 | */ |
| 65 | int dm_tm_new_block(struct dm_transaction_manager *tm, |
| 66 | struct dm_block_validator *v, |
| 67 | struct dm_block **result); |
| 68 | |
| 69 | /* |
| 70 | * dm_tm_shadow_block() allocates a new block and copies the data from @orig |
| 71 | * to it. It then decrements the reference count on original block. Use |
| 72 | * this to update the contents of a block in a data structure, don't |
| 73 | * confuse this with a clone - you shouldn't access the orig block after |
| 74 | * this operation. Because the tm knows the scope of the transaction it |
| 75 | * can optimise requests for a shadow of a shadow to a no-op. Don't forget |
| 76 | * to unlock when you've finished with the shadow. |
| 77 | * |
| 78 | * The @inc_children flag is used to tell the caller whether it needs to |
| 79 | * adjust reference counts for children. (Data in the block may refer to |
| 80 | * other blocks.) |
| 81 | * |
| 82 | * Shadowing implicitly drops a reference on @orig so you must not have |
| 83 | * it locked when you call this. |
| 84 | */ |
| 85 | int dm_tm_shadow_block(struct dm_transaction_manager *tm, dm_block_t orig, |
| 86 | struct dm_block_validator *v, |
| 87 | struct dm_block **result, int *inc_children); |
| 88 | |
| 89 | /* |
| 90 | * Read access. You can lock any block you want. If there's a write lock |
| 91 | * on it outstanding then it'll block. |
| 92 | */ |
| 93 | int dm_tm_read_lock(struct dm_transaction_manager *tm, dm_block_t b, |
| 94 | struct dm_block_validator *v, |
| 95 | struct dm_block **result); |
| 96 | |
| 97 | int dm_tm_unlock(struct dm_transaction_manager *tm, struct dm_block *b); |
| 98 | |
| 99 | /* |
| 100 | * Functions for altering the reference count of a block directly. |
| 101 | */ |
| 102 | void dm_tm_inc(struct dm_transaction_manager *tm, dm_block_t b); |
| 103 | |
| 104 | void dm_tm_dec(struct dm_transaction_manager *tm, dm_block_t b); |
| 105 | |
| 106 | int dm_tm_ref(struct dm_transaction_manager *tm, dm_block_t b, |
| 107 | uint32_t *result); |
| 108 | |
| 109 | struct dm_block_manager *dm_tm_get_bm(struct dm_transaction_manager *tm); |
| 110 | |
| 111 | /* |
| 112 | * A little utility that ties the knot by producing a transaction manager |
| 113 | * that has a space map managed by the transaction manager... |
| 114 | * |
| 115 | * Returns a tm that has an open transaction to write the new disk sm. |
| 116 | * Caller should store the new sm root and commit. |
Joe Thornber | 384ef0e | 2012-07-27 15:08:09 +0100 | [diff] [blame] | 117 | * |
| 118 | * The superblock location is passed so the metadata space map knows it |
| 119 | * shouldn't be used. |
Joe Thornber | 3241b1d | 2011-10-31 20:19:11 +0000 | [diff] [blame] | 120 | */ |
| 121 | int dm_tm_create_with_sm(struct dm_block_manager *bm, dm_block_t sb_location, |
Joe Thornber | 3241b1d | 2011-10-31 20:19:11 +0000 | [diff] [blame] | 122 | struct dm_transaction_manager **tm, |
Joe Thornber | 384ef0e | 2012-07-27 15:08:09 +0100 | [diff] [blame] | 123 | struct dm_space_map **sm); |
Joe Thornber | 3241b1d | 2011-10-31 20:19:11 +0000 | [diff] [blame] | 124 | |
| 125 | int dm_tm_open_with_sm(struct dm_block_manager *bm, dm_block_t sb_location, |
Joe Thornber | 384ef0e | 2012-07-27 15:08:09 +0100 | [diff] [blame] | 126 | void *sm_root, size_t root_len, |
Joe Thornber | 3241b1d | 2011-10-31 20:19:11 +0000 | [diff] [blame] | 127 | struct dm_transaction_manager **tm, |
Joe Thornber | 384ef0e | 2012-07-27 15:08:09 +0100 | [diff] [blame] | 128 | struct dm_space_map **sm); |
Joe Thornber | 3241b1d | 2011-10-31 20:19:11 +0000 | [diff] [blame] | 129 | |
| 130 | #endif /* _LINUX_DM_TRANSACTION_MANAGER_H */ |