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