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_SPACE_MAP_H | |
8 | #define _LINUX_DM_SPACE_MAP_H | |
9 | ||
10 | #include "dm-block-manager.h" | |
11 | ||
7c3d3f2a JT |
12 | typedef void (*dm_sm_threshold_fn)(void *context); |
13 | ||
3241b1d3 JT |
14 | /* |
15 | * struct dm_space_map keeps a record of how many times each block in a device | |
16 | * is referenced. It needs to be fixed on disk as part of the transaction. | |
17 | */ | |
18 | struct dm_space_map { | |
19 | void (*destroy)(struct dm_space_map *sm); | |
20 | ||
21 | /* | |
22 | * You must commit before allocating the newly added space. | |
23 | */ | |
24 | int (*extend)(struct dm_space_map *sm, dm_block_t extra_blocks); | |
25 | ||
26 | /* | |
27 | * Extensions do not appear in this count until after commit has | |
28 | * been called. | |
29 | */ | |
30 | int (*get_nr_blocks)(struct dm_space_map *sm, dm_block_t *count); | |
31 | ||
32 | /* | |
33 | * Space maps must never allocate a block from the previous | |
34 | * transaction, in case we need to rollback. This complicates the | |
35 | * semantics of get_nr_free(), it should return the number of blocks | |
36 | * that are available for allocation _now_. For instance you may | |
37 | * have blocks with a zero reference count that will not be | |
38 | * available for allocation until after the next commit. | |
39 | */ | |
40 | int (*get_nr_free)(struct dm_space_map *sm, dm_block_t *count); | |
41 | ||
42 | int (*get_count)(struct dm_space_map *sm, dm_block_t b, uint32_t *result); | |
43 | int (*count_is_more_than_one)(struct dm_space_map *sm, dm_block_t b, | |
44 | int *result); | |
45 | int (*set_count)(struct dm_space_map *sm, dm_block_t b, uint32_t count); | |
46 | ||
47 | int (*commit)(struct dm_space_map *sm); | |
48 | ||
49 | int (*inc_block)(struct dm_space_map *sm, dm_block_t b); | |
50 | int (*dec_block)(struct dm_space_map *sm, dm_block_t b); | |
51 | ||
52 | /* | |
53 | * new_block will increment the returned block. | |
54 | */ | |
55 | int (*new_block)(struct dm_space_map *sm, dm_block_t *b); | |
56 | ||
57 | /* | |
58 | * The root contains all the information needed to fix the space map. | |
59 | * Generally this info is small, so squirrel it away in a disk block | |
60 | * along with other info. | |
61 | */ | |
62 | int (*root_size)(struct dm_space_map *sm, size_t *result); | |
63 | int (*copy_root)(struct dm_space_map *sm, void *copy_to_here_le, size_t len); | |
7c3d3f2a JT |
64 | |
65 | /* | |
66 | * You can register one threshold callback which is edge-triggered | |
67 | * when the free space in the space map drops below the threshold. | |
68 | */ | |
69 | int (*register_threshold_callback)(struct dm_space_map *sm, | |
70 | dm_block_t threshold, | |
71 | dm_sm_threshold_fn fn, | |
72 | void *context); | |
3241b1d3 JT |
73 | }; |
74 | ||
75 | /*----------------------------------------------------------------*/ | |
76 | ||
77 | static inline void dm_sm_destroy(struct dm_space_map *sm) | |
78 | { | |
79 | sm->destroy(sm); | |
80 | } | |
81 | ||
82 | static inline int dm_sm_extend(struct dm_space_map *sm, dm_block_t extra_blocks) | |
83 | { | |
84 | return sm->extend(sm, extra_blocks); | |
85 | } | |
86 | ||
87 | static inline int dm_sm_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count) | |
88 | { | |
89 | return sm->get_nr_blocks(sm, count); | |
90 | } | |
91 | ||
92 | static inline int dm_sm_get_nr_free(struct dm_space_map *sm, dm_block_t *count) | |
93 | { | |
94 | return sm->get_nr_free(sm, count); | |
95 | } | |
96 | ||
97 | static inline int dm_sm_get_count(struct dm_space_map *sm, dm_block_t b, | |
98 | uint32_t *result) | |
99 | { | |
100 | return sm->get_count(sm, b, result); | |
101 | } | |
102 | ||
103 | static inline int dm_sm_count_is_more_than_one(struct dm_space_map *sm, | |
104 | dm_block_t b, int *result) | |
105 | { | |
106 | return sm->count_is_more_than_one(sm, b, result); | |
107 | } | |
108 | ||
109 | static inline int dm_sm_set_count(struct dm_space_map *sm, dm_block_t b, | |
110 | uint32_t count) | |
111 | { | |
112 | return sm->set_count(sm, b, count); | |
113 | } | |
114 | ||
115 | static inline int dm_sm_commit(struct dm_space_map *sm) | |
116 | { | |
117 | return sm->commit(sm); | |
118 | } | |
119 | ||
120 | static inline int dm_sm_inc_block(struct dm_space_map *sm, dm_block_t b) | |
121 | { | |
122 | return sm->inc_block(sm, b); | |
123 | } | |
124 | ||
125 | static inline int dm_sm_dec_block(struct dm_space_map *sm, dm_block_t b) | |
126 | { | |
127 | return sm->dec_block(sm, b); | |
128 | } | |
129 | ||
130 | static inline int dm_sm_new_block(struct dm_space_map *sm, dm_block_t *b) | |
131 | { | |
132 | return sm->new_block(sm, b); | |
133 | } | |
134 | ||
135 | static inline int dm_sm_root_size(struct dm_space_map *sm, size_t *result) | |
136 | { | |
137 | return sm->root_size(sm, result); | |
138 | } | |
139 | ||
140 | static inline int dm_sm_copy_root(struct dm_space_map *sm, void *copy_to_here_le, size_t len) | |
141 | { | |
142 | return sm->copy_root(sm, copy_to_here_le, len); | |
143 | } | |
144 | ||
7c3d3f2a JT |
145 | static inline int dm_sm_register_threshold_callback(struct dm_space_map *sm, |
146 | dm_block_t threshold, | |
147 | dm_sm_threshold_fn fn, | |
148 | void *context) | |
149 | { | |
150 | if (sm->register_threshold_callback) | |
151 | return sm->register_threshold_callback(sm, threshold, fn, context); | |
152 | ||
153 | return -EINVAL; | |
154 | } | |
155 | ||
156 | ||
3241b1d3 | 157 | #endif /* _LINUX_DM_SPACE_MAP_H */ |