Commit | Line | Data |
---|---|---|
3241b1d3 JT |
1 | /* |
2 | * Copyright (C) 2011 Red Hat, Inc. | |
3 | * | |
4 | * This file is released under the GPL. | |
5 | */ | |
6 | ||
7 | #ifndef _LINUX_DM_BLOCK_MANAGER_H | |
8 | #define _LINUX_DM_BLOCK_MANAGER_H | |
9 | ||
10 | #include <linux/types.h> | |
11 | #include <linux/blkdev.h> | |
12 | ||
13 | /*----------------------------------------------------------------*/ | |
14 | ||
15 | /* | |
16 | * Block number. | |
17 | */ | |
18 | typedef uint64_t dm_block_t; | |
19 | struct dm_block; | |
20 | ||
21 | dm_block_t dm_block_location(struct dm_block *b); | |
22 | void *dm_block_data(struct dm_block *b); | |
23 | ||
24 | /*----------------------------------------------------------------*/ | |
25 | ||
26 | /* | |
27 | * @name should be a unique identifier for the block manager, no longer | |
28 | * than 32 chars. | |
29 | * | |
30 | * @max_held_per_thread should be the maximum number of locks, read or | |
31 | * write, that an individual thread holds at any one time. | |
32 | */ | |
33 | struct dm_block_manager; | |
34 | struct dm_block_manager *dm_block_manager_create( | |
35 | struct block_device *bdev, unsigned block_size, | |
36 | unsigned cache_size, unsigned max_held_per_thread); | |
37 | void dm_block_manager_destroy(struct dm_block_manager *bm); | |
38 | ||
39 | unsigned dm_bm_block_size(struct dm_block_manager *bm); | |
40 | dm_block_t dm_bm_nr_blocks(struct dm_block_manager *bm); | |
41 | ||
42 | /*----------------------------------------------------------------*/ | |
43 | ||
44 | /* | |
45 | * The validator allows the caller to verify newly-read data and modify | |
46 | * the data just before writing, e.g. to calculate checksums. It's | |
47 | * important to be consistent with your use of validators. The only time | |
48 | * you can change validators is if you call dm_bm_write_lock_zero. | |
49 | */ | |
50 | struct dm_block_validator { | |
51 | const char *name; | |
52 | void (*prepare_for_write)(struct dm_block_validator *v, struct dm_block *b, size_t block_size); | |
53 | ||
54 | /* | |
55 | * Return 0 if the checksum is valid or < 0 on error. | |
56 | */ | |
57 | int (*check)(struct dm_block_validator *v, struct dm_block *b, size_t block_size); | |
58 | }; | |
59 | ||
60 | /*----------------------------------------------------------------*/ | |
61 | ||
62 | /* | |
63 | * You can have multiple concurrent readers or a single writer holding a | |
64 | * block lock. | |
65 | */ | |
66 | ||
67 | /* | |
68 | * dm_bm_lock() locks a block and returns through @result a pointer to | |
69 | * memory that holds a copy of that block. If you have write-locked the | |
70 | * block then any changes you make to memory pointed to by @result will be | |
71 | * written back to the disk sometime after dm_bm_unlock is called. | |
72 | */ | |
73 | int dm_bm_read_lock(struct dm_block_manager *bm, dm_block_t b, | |
74 | struct dm_block_validator *v, | |
75 | struct dm_block **result); | |
76 | ||
77 | int dm_bm_write_lock(struct dm_block_manager *bm, dm_block_t b, | |
78 | struct dm_block_validator *v, | |
79 | struct dm_block **result); | |
80 | ||
81 | /* | |
82 | * The *_try_lock variants return -EWOULDBLOCK if the block isn't | |
83 | * available immediately. | |
84 | */ | |
85 | int dm_bm_read_try_lock(struct dm_block_manager *bm, dm_block_t b, | |
86 | struct dm_block_validator *v, | |
87 | struct dm_block **result); | |
88 | ||
89 | /* | |
90 | * Use dm_bm_write_lock_zero() when you know you're going to | |
91 | * overwrite the block completely. It saves a disk read. | |
92 | */ | |
93 | int dm_bm_write_lock_zero(struct dm_block_manager *bm, dm_block_t b, | |
94 | struct dm_block_validator *v, | |
95 | struct dm_block **result); | |
96 | ||
97 | int dm_bm_unlock(struct dm_block *b); | |
98 | ||
3241b1d3 JT |
99 | /* |
100 | * It's a common idiom to have a superblock that should be committed last. | |
101 | * | |
102 | * @superblock should be write-locked on entry. It will be unlocked during | |
103 | * this function. All dirty blocks are guaranteed to be written and flushed | |
104 | * before the superblock. | |
105 | * | |
106 | * This method always blocks. | |
107 | */ | |
108 | int dm_bm_flush_and_unlock(struct dm_block_manager *bm, | |
109 | struct dm_block *superblock); | |
110 | ||
31097557 JT |
111 | /* |
112 | * Switches the bm to a read only mode. Once read-only mode | |
113 | * has been entered the following functions will return -EPERM. | |
114 | * | |
115 | * dm_bm_write_lock | |
116 | * dm_bm_write_lock_zero | |
117 | * dm_bm_flush_and_unlock | |
118 | * | |
119 | * Additionally you should not use dm_bm_unlock_move, however no error will | |
120 | * be returned if you do. | |
121 | */ | |
122 | void dm_bm_set_read_only(struct dm_block_manager *bm); | |
123 | ||
3241b1d3 JT |
124 | u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor); |
125 | ||
126 | /*----------------------------------------------------------------*/ | |
127 | ||
128 | #endif /* _LINUX_DM_BLOCK_MANAGER_H */ |