1
2
3
4
5
6#include "xfs.h"
7#include "xfs_fs.h"
8#include "xfs_shared.h"
9#include "xfs_format.h"
10#include "xfs_trans_resv.h"
11#include "xfs_mount.h"
12#include "xfs_btree.h"
13#include "scrub/bitmap.h"
14
15
16
17
18
19
20int
21xbitmap_set(
22 struct xbitmap *bitmap,
23 uint64_t start,
24 uint64_t len)
25{
26 struct xbitmap_range *bmr;
27
28 bmr = kmem_alloc(sizeof(struct xbitmap_range), KM_MAYFAIL);
29 if (!bmr)
30 return -ENOMEM;
31
32 INIT_LIST_HEAD(&bmr->list);
33 bmr->start = start;
34 bmr->len = len;
35 list_add_tail(&bmr->list, &bitmap->list);
36
37 return 0;
38}
39
40
41void
42xbitmap_destroy(
43 struct xbitmap *bitmap)
44{
45 struct xbitmap_range *bmr;
46 struct xbitmap_range *n;
47
48 for_each_xbitmap_extent(bmr, n, bitmap) {
49 list_del(&bmr->list);
50 kmem_free(bmr);
51 }
52}
53
54
55void
56xbitmap_init(
57 struct xbitmap *bitmap)
58{
59 INIT_LIST_HEAD(&bitmap->list);
60}
61
62
63static int
64xbitmap_range_cmp(
65 void *priv,
66 const struct list_head *a,
67 const struct list_head *b)
68{
69 struct xbitmap_range *ap;
70 struct xbitmap_range *bp;
71
72 ap = container_of(a, struct xbitmap_range, list);
73 bp = container_of(b, struct xbitmap_range, list);
74
75 if (ap->start > bp->start)
76 return 1;
77 if (ap->start < bp->start)
78 return -1;
79 return 0;
80}
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96#define LEFT_ALIGNED (1 << 0)
97#define RIGHT_ALIGNED (1 << 1)
98int
99xbitmap_disunion(
100 struct xbitmap *bitmap,
101 struct xbitmap *sub)
102{
103 struct list_head *lp;
104 struct xbitmap_range *br;
105 struct xbitmap_range *new_br;
106 struct xbitmap_range *sub_br;
107 uint64_t sub_start;
108 uint64_t sub_len;
109 int state;
110 int error = 0;
111
112 if (list_empty(&bitmap->list) || list_empty(&sub->list))
113 return 0;
114 ASSERT(!list_empty(&sub->list));
115
116 list_sort(NULL, &bitmap->list, xbitmap_range_cmp);
117 list_sort(NULL, &sub->list, xbitmap_range_cmp);
118
119
120
121
122
123
124
125
126
127 sub_br = list_first_entry(&sub->list, struct xbitmap_range,
128 list);
129 lp = bitmap->list.next;
130 while (lp != &bitmap->list) {
131 br = list_entry(lp, struct xbitmap_range, list);
132
133
134
135
136
137 while (sub_br->start + sub_br->len <= br->start) {
138 if (list_is_last(&sub_br->list, &sub->list))
139 goto out;
140 sub_br = list_next_entry(sub_br, list);
141 }
142 if (sub_br->start >= br->start + br->len) {
143 lp = lp->next;
144 continue;
145 }
146
147
148 sub_start = sub_br->start;
149 sub_len = sub_br->len;
150 if (sub_br->start < br->start) {
151 sub_len -= br->start - sub_br->start;
152 sub_start = br->start;
153 }
154 if (sub_len > br->len)
155 sub_len = br->len;
156
157 state = 0;
158 if (sub_start == br->start)
159 state |= LEFT_ALIGNED;
160 if (sub_start + sub_len == br->start + br->len)
161 state |= RIGHT_ALIGNED;
162 switch (state) {
163 case LEFT_ALIGNED:
164
165 br->start += sub_len;
166 br->len -= sub_len;
167 break;
168 case RIGHT_ALIGNED:
169
170 br->len -= sub_len;
171 lp = lp->next;
172 break;
173 case LEFT_ALIGNED | RIGHT_ALIGNED:
174
175 lp = lp->next;
176 list_del(&br->list);
177 kmem_free(br);
178 break;
179 case 0:
180
181
182
183
184 new_br = kmem_alloc(sizeof(struct xbitmap_range),
185 KM_MAYFAIL);
186 if (!new_br) {
187 error = -ENOMEM;
188 goto out;
189 }
190 INIT_LIST_HEAD(&new_br->list);
191 new_br->start = sub_start + sub_len;
192 new_br->len = br->start + br->len - new_br->start;
193 list_add(&new_br->list, &br->list);
194 br->len = sub_start - br->start;
195 lp = lp->next;
196 break;
197 default:
198 ASSERT(0);
199 break;
200 }
201 }
202
203out:
204 return error;
205}
206#undef LEFT_ALIGNED
207#undef RIGHT_ALIGNED
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249int
250xbitmap_set_btcur_path(
251 struct xbitmap *bitmap,
252 struct xfs_btree_cur *cur)
253{
254 struct xfs_buf *bp;
255 xfs_fsblock_t fsb;
256 int i;
257 int error;
258
259 for (i = 0; i < cur->bc_nlevels && cur->bc_ptrs[i] == 1; i++) {
260 xfs_btree_get_block(cur, i, &bp);
261 if (!bp)
262 continue;
263 fsb = XFS_DADDR_TO_FSB(cur->bc_mp, xfs_buf_daddr(bp));
264 error = xbitmap_set(bitmap, fsb, 1);
265 if (error)
266 return error;
267 }
268
269 return 0;
270}
271
272
273STATIC int
274xbitmap_collect_btblock(
275 struct xfs_btree_cur *cur,
276 int level,
277 void *priv)
278{
279 struct xbitmap *bitmap = priv;
280 struct xfs_buf *bp;
281 xfs_fsblock_t fsbno;
282
283 xfs_btree_get_block(cur, level, &bp);
284 if (!bp)
285 return 0;
286
287 fsbno = XFS_DADDR_TO_FSB(cur->bc_mp, xfs_buf_daddr(bp));
288 return xbitmap_set(bitmap, fsbno, 1);
289}
290
291
292int
293xbitmap_set_btblocks(
294 struct xbitmap *bitmap,
295 struct xfs_btree_cur *cur)
296{
297 return xfs_btree_visit_blocks(cur, xbitmap_collect_btblock,
298 XFS_BTREE_VISIT_ALL, bitmap);
299}
300
301
302uint64_t
303xbitmap_hweight(
304 struct xbitmap *bitmap)
305{
306 struct xbitmap_range *bmr;
307 struct xbitmap_range *n;
308 uint64_t ret = 0;
309
310 for_each_xbitmap_extent(bmr, n, bitmap)
311 ret += bmr->len;
312
313 return ret;
314}
315