1 /*
2 bitmap.c -- bitmap functions.
3 Copyright (C) 1996-2002 Hans Reiser.
4 Author Yury Umanets.
5 */
6
7 #include <stdlib.h>
8 #include <string.h>
9
10 #include <reiserfs/debug.h>
11 #include <reiserfs/reiserfs.h>
12
13 #define reiserfs_bitmap_range_check(bitmap, blk, action) \
14 do { \
15 if (blk >= bitmap->total_blocks) { \
16 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_CANCEL, \
17 "Block %lu is out of range (0-%lu)", blk, bitmap->total_blocks); \
18 action; \
19 } \
20 } while (0); \
21
22
reiserfs_bitmap_use_block(reiserfs_bitmap_t * bitmap,blk_t blk)23 void reiserfs_bitmap_use_block(reiserfs_bitmap_t *bitmap, blk_t blk) {
24 ASSERT(bitmap != NULL, return);
25
26 reiserfs_bitmap_range_check(bitmap, blk, return);
27 if (reiserfs_tools_test_bit(blk, bitmap->map))
28 return;
29
30 reiserfs_tools_set_bit(blk, bitmap->map);
31 bitmap->used_blocks++;
32 }
33
reiserfs_bitmap_unuse_block(reiserfs_bitmap_t * bitmap,blk_t blk)34 void reiserfs_bitmap_unuse_block(reiserfs_bitmap_t *bitmap, blk_t blk) {
35 ASSERT(bitmap != NULL, return);
36
37 reiserfs_bitmap_range_check(bitmap, blk, return);
38 if (!reiserfs_tools_test_bit(blk, bitmap->map))
39 return;
40
41 reiserfs_tools_clear_bit(blk, bitmap->map);
42 bitmap->used_blocks--;
43 }
44
reiserfs_bitmap_test_block(reiserfs_bitmap_t * bitmap,blk_t blk)45 int reiserfs_bitmap_test_block(reiserfs_bitmap_t *bitmap, blk_t blk) {
46 ASSERT(bitmap != NULL, return 0);
47
48 reiserfs_bitmap_range_check(bitmap, blk, return 0);
49 return reiserfs_tools_test_bit(blk, bitmap->map);
50 }
51
reiserfs_bitmap_find_free(reiserfs_bitmap_t * bitmap,blk_t start)52 blk_t reiserfs_bitmap_find_free(reiserfs_bitmap_t *bitmap, blk_t start) {
53 blk_t blk;
54
55 ASSERT(bitmap != NULL, return 0);
56
57 reiserfs_bitmap_range_check(bitmap, start, return 0);
58 if ((blk = reiserfs_tools_find_next_zero_bit(bitmap->map,
59 bitmap->total_blocks, start)) >= bitmap->total_blocks)
60 return 0;
61
62 return blk;
63 }
64
reiserfs_bitmap_calc(reiserfs_bitmap_t * bitmap,blk_t start,blk_t end,int is_free)65 static blk_t reiserfs_bitmap_calc(reiserfs_bitmap_t *bitmap,
66 blk_t start, blk_t end, int is_free)
67 {
68 blk_t i, blocks = 0;
69
70 ASSERT(bitmap != NULL, return 0);
71
72 reiserfs_bitmap_range_check(bitmap, start, return 0);
73 reiserfs_bitmap_range_check(bitmap, end - 1, return 0);
74
75 for (i = start; i < end; ) {
76 #if !defined(__sparc__) && !defined(__sparcv9)
77 uint64_t *block64 = (uint64_t *)(bitmap->map + (i >> 0x3));
78 uint16_t bits = sizeof(uint64_t) * 8;
79
80 if (i + bits < end && i % 0x8 == 0 &&
81 *block64 == (is_free == 0 ? 0xffffffffffffffffLL : 0))
82 {
83 blocks += bits;
84 i += bits;
85 } else {
86 blocks += (reiserfs_bitmap_test_block(bitmap, i) ? is_free : !is_free);
87 i++;
88 }
89 #else
90 blocks += (reiserfs_bitmap_test_block(bitmap, i) ? is_free : !is_free);
91 i++;
92 #endif
93 }
94 return blocks;
95 }
96
reiserfs_bitmap_calc_used(reiserfs_bitmap_t * bitmap)97 blk_t reiserfs_bitmap_calc_used(reiserfs_bitmap_t *bitmap) {
98 return reiserfs_bitmap_calc(bitmap, 0, bitmap->total_blocks, 0);
99 }
100
reiserfs_bitmap_calc_unused(reiserfs_bitmap_t * bitmap)101 blk_t reiserfs_bitmap_calc_unused(reiserfs_bitmap_t *bitmap) {
102 return reiserfs_bitmap_calc(bitmap, 0, bitmap->total_blocks, 1);
103 }
104
reiserfs_bitmap_calc_used_in_area(reiserfs_bitmap_t * bitmap,blk_t start,blk_t end)105 blk_t reiserfs_bitmap_calc_used_in_area(reiserfs_bitmap_t *bitmap,
106 blk_t start, blk_t end)
107 {
108 ASSERT(bitmap != NULL, return 0);
109 return reiserfs_bitmap_calc(bitmap, start, end, 0);
110 }
111
reiserfs_bitmap_calc_unused_in_area(reiserfs_bitmap_t * bitmap,blk_t start,blk_t end)112 blk_t reiserfs_bitmap_calc_unused_in_area(reiserfs_bitmap_t *bitmap,
113 blk_t start, blk_t end)
114 {
115 ASSERT(bitmap != NULL, return 0);
116 return reiserfs_bitmap_calc(bitmap, start, end, 1);
117 }
118
reiserfs_bitmap_used(reiserfs_bitmap_t * bitmap)119 blk_t reiserfs_bitmap_used(reiserfs_bitmap_t *bitmap) {
120 ASSERT(bitmap != NULL, return 0);
121 return bitmap->used_blocks;
122 }
123
reiserfs_bitmap_unused(reiserfs_bitmap_t * bitmap)124 blk_t reiserfs_bitmap_unused(reiserfs_bitmap_t *bitmap) {
125 ASSERT(bitmap != NULL, return 0);
126
127 ASSERT(bitmap->total_blocks -
128 bitmap->used_blocks > 0, return 0);
129
130 return bitmap->total_blocks - bitmap->used_blocks;
131 }
132
reiserfs_bitmap_check(reiserfs_bitmap_t * bitmap)133 int reiserfs_bitmap_check(reiserfs_bitmap_t *bitmap) {
134 ASSERT(bitmap != NULL, return 0);
135
136 if (reiserfs_bitmap_calc_used(bitmap) != bitmap->used_blocks)
137 return 0;
138
139 return 1;
140 }
141
reiserfs_bitmap_alloc(blk_t len)142 reiserfs_bitmap_t *reiserfs_bitmap_alloc(blk_t len) {
143 reiserfs_bitmap_t *bitmap;
144
145 ASSERT(len > 0, goto error);
146
147 if (!(bitmap = (reiserfs_bitmap_t *)libreiserfs_calloc(sizeof(*bitmap), 0)))
148 goto error;
149
150 bitmap->used_blocks = 0;
151 bitmap->total_blocks = len;
152 bitmap->size = (len + 7) / 8;
153
154 if (!(bitmap->map = (char *)libreiserfs_calloc(bitmap->size, 0)))
155 goto error_free_bitmap;
156
157 return bitmap;
158
159 error_free_bitmap:
160 reiserfs_bitmap_close(bitmap);
161 error:
162 return NULL;
163 }
164
callback_bitmap_flush(dal_t * dal,blk_t blk,char * map,uint32_t chunk,void * data)165 static int callback_bitmap_flush(dal_t *dal,
166 blk_t blk, char *map, uint32_t chunk, void *data)
167 {
168 reiserfs_block_t *block;
169 reiserfs_bitmap_t *bitmap = (reiserfs_bitmap_t *)data;
170
171 if (!(block = reiserfs_block_alloc(dal, blk, 0xff)))
172 goto error;
173
174 memcpy(block->data, map, chunk);
175
176 /* Marking the rest of last byte of the bitmap as used */
177 if ((map + chunk) - bitmap->map >= (long)bitmap->size) {
178 uint32_t i, unused_bits = bitmap->size * 8 - bitmap->total_blocks;
179 for (i = 0; i < unused_bits; i++) {
180 reiserfs_tools_set_bit((bitmap->total_blocks %
181 (dal_get_blocksize(dal) * 8)) + i, block->data);
182 }
183 }
184
185 if (!reiserfs_block_write(dal, block)) {
186 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_OK,
187 "Can't write bitmap block to %lu. %s.", blk, dal_error(dal));
188 goto error_free_block;
189 }
190 reiserfs_block_free(block);
191
192 return 1;
193
194 error_free_block:
195 reiserfs_block_free(block);
196 error:
197 return 0;
198 }
199
callback_bitmap_fetch(dal_t * dal,blk_t blk,char * map,uint32_t chunk,void * data)200 static int callback_bitmap_fetch(dal_t *dal,
201 blk_t blk, char *map, uint32_t chunk, void *data)
202 {
203 reiserfs_block_t *block;
204 if (!(block = reiserfs_block_read(dal, blk))) {
205 libreiserfs_exception_throw(EXCEPTION_ERROR, EXCEPTION_OK,
206 "Can't read bitmap block %lu. %s.", blk, dal_error(dal));
207 return 0;
208 }
209
210 memcpy(map, block->data, chunk);
211 reiserfs_block_free(block);
212
213 return 1;
214 }
215
reiserfs_bitmap_pipe(reiserfs_bitmap_t * bitmap,reiserfs_bitmap_pipe_func_t * pipe_func,void * data)216 int reiserfs_bitmap_pipe(reiserfs_bitmap_t *bitmap,
217 reiserfs_bitmap_pipe_func_t *pipe_func, void *data)
218 {
219 char *map;
220 blk_t blk;
221 uint32_t left, chunk;
222
223 ASSERT(bitmap != NULL, return 0);
224 ASSERT(bitmap->fs != NULL, return 0);
225
226 map = bitmap->map;
227 blk = bitmap->start;
228
229 for (left = bitmap->size; left > 0; ) {
230 chunk = (left < dal_get_blocksize(bitmap->fs->dal) ? left :
231 dal_get_blocksize(bitmap->fs->dal));
232
233 if (pipe_func && !pipe_func(bitmap->fs->dal, blk, map, chunk, data))
234 return 0;
235
236 blk = (blk / (dal_get_blocksize(bitmap->fs->dal) * 8) + 1) *
237 (dal_get_blocksize(bitmap->fs->dal) * 8);
238
239 map += chunk;
240 left -= chunk;
241 }
242
243 return 1;
244 }
245
reiserfs_bitmap_open(reiserfs_fs_t * fs,blk_t start,count_t len)246 reiserfs_bitmap_t *reiserfs_bitmap_open(reiserfs_fs_t *fs,
247 blk_t start, count_t len)
248 {
249 reiserfs_bitmap_t *bitmap;
250 uint32_t i, unused_bits;
251
252 ASSERT(fs != NULL, return NULL);
253
254 if(!(bitmap = reiserfs_bitmap_alloc(len)))
255 goto error;
256
257 bitmap->start = start;
258 bitmap->fs = fs;
259
260 if (!reiserfs_bitmap_pipe(bitmap, callback_bitmap_fetch, (void *)bitmap))
261 goto error_free_bitmap;
262
263 unused_bits = bitmap->size * 8 - bitmap->total_blocks;
264
265 for (i = 0; i < unused_bits; i++)
266 reiserfs_tools_clear_bit(bitmap->total_blocks + i, bitmap->map);
267
268 if (!(bitmap->used_blocks = reiserfs_bitmap_calc_used(bitmap)))
269 goto error_free_bitmap;
270
271 return bitmap;
272
273 error_free_bitmap:
274 reiserfs_bitmap_close(bitmap);
275 error:
276 return NULL;
277 }
278
reiserfs_bitmap_create(reiserfs_fs_t * fs,blk_t start,count_t len)279 reiserfs_bitmap_t *reiserfs_bitmap_create(reiserfs_fs_t *fs,
280 blk_t start, count_t len)
281 {
282 blk_t i, bmap_blknr;
283 reiserfs_bitmap_t *bitmap;
284
285 ASSERT(fs != NULL, return NULL);
286
287 if (!(bitmap = reiserfs_bitmap_alloc(len)))
288 return NULL;
289
290 bitmap->start = start;
291 bitmap->fs = fs;
292
293 /* Marking first bitmap block as used */
294 reiserfs_bitmap_use_block(bitmap, start);
295
296 /* Setting up other bitmap blocks */
297 bmap_blknr = (len - 1) / (dal_get_blocksize(fs->dal) * 8) + 1;
298
299 for (i = 1; i < bmap_blknr; i++)
300 reiserfs_bitmap_use_block(bitmap, i * dal_get_blocksize(fs->dal) * 8);
301
302 return bitmap;
303 }
304
reiserfs_bitmap_resize_map(reiserfs_bitmap_t * bitmap,long start,long end,uint16_t blocksize)305 static uint32_t reiserfs_bitmap_resize_map(reiserfs_bitmap_t *bitmap,
306 long start, long end, uint16_t blocksize)
307 {
308 char *map;
309 long i, right, journal_len, offset;
310 long size = ((end - start) + 7) / 8;
311
312 if (start == 0) {
313 int chunk;
314
315 if (size == (long)bitmap->size)
316 return bitmap->size;
317
318 if (!libreiserfs_realloc((void **)&bitmap->map, size))
319 return 0;
320
321 if ((chunk = size - bitmap->size) > 0)
322 memset(bitmap->map + bitmap->size, 0, chunk);
323
324 return size;
325 }
326
327 if (!(map = libreiserfs_calloc(size, 0)))
328 return 0;
329
330 journal_len = get_jp_len(get_sb_jp(bitmap->fs->super));
331 offset = bitmap->fs->super_off + 1 + journal_len;
332
333 memcpy(map, bitmap->map, (offset / 8) + 1);
334
335 right = end > (long)bitmap->total_blocks ?
336 (long)bitmap->total_blocks : end;
337
338 if (start < 0) {
339 for (i = right - 1; i >= offset + 1; i--) {
340 if (reiserfs_tools_test_bit(i, bitmap->map)) {
341 if (i + start > offset + 1)
342 reiserfs_tools_set_bit(i + start, map);
343 }
344 }
345 } else {
346 for (i = start + offset + 1; i < right; i++) {
347 if (reiserfs_tools_test_bit(i, bitmap->map))
348 reiserfs_tools_set_bit(i - start, map);
349 }
350 }
351
352 libreiserfs_free(bitmap->map);
353 bitmap->map = map;
354
355 return size;
356 }
357
reiserfs_bitmap_resize(reiserfs_bitmap_t * bitmap,long start,long end)358 int reiserfs_bitmap_resize(reiserfs_bitmap_t *bitmap,
359 long start, long end)
360 {
361 int size;
362 blk_t i, bmap_old_blknr, bmap_new_blknr;
363
364 ASSERT(bitmap != NULL, return 0);
365 ASSERT(end - start > 0, return 0);
366
367 if ((size = reiserfs_bitmap_resize_map(bitmap, start,
368 end, dal_get_blocksize(bitmap->fs->dal))) - bitmap->size == 0)
369 return 1;
370
371 bmap_old_blknr = bitmap->size / dal_get_blocksize(bitmap->fs->dal);
372
373 bmap_new_blknr = (end - start - 1) /
374 (dal_get_blocksize(bitmap->fs->dal) * 8) + 1;
375
376 bitmap->size = size;
377 bitmap->total_blocks = end - start;
378
379 /* Marking new bitmap blocks as used */
380 if (bmap_new_blknr - bmap_old_blknr > 0) {
381 for (i = bmap_old_blknr; i < bmap_new_blknr; i++)
382 reiserfs_bitmap_use_block(bitmap, i * dal_get_blocksize(bitmap->fs->dal) * 8);
383 }
384
385 return 1;
386 }
387
reiserfs_bitmap_copy(reiserfs_bitmap_t * dest_bitmap,reiserfs_bitmap_t * src_bitmap,blk_t len)388 blk_t reiserfs_bitmap_copy(reiserfs_bitmap_t *dest_bitmap,
389 reiserfs_bitmap_t *src_bitmap, blk_t len)
390 {
391
392 ASSERT(dest_bitmap != NULL, return 0);
393 ASSERT(src_bitmap != NULL, return 0);
394
395 if (!len)
396 return 0;
397
398 if (!reiserfs_bitmap_resize(dest_bitmap, 0, (len > src_bitmap->total_blocks ?
399 src_bitmap->total_blocks : len)))
400 return 0;
401
402 memcpy(dest_bitmap->map, src_bitmap->map, dest_bitmap->size);
403 dest_bitmap->used_blocks = reiserfs_bitmap_used(dest_bitmap);
404
405 return dest_bitmap->total_blocks;
406 }
407
reiserfs_bitmap_clone(reiserfs_bitmap_t * bitmap)408 reiserfs_bitmap_t *reiserfs_bitmap_clone(reiserfs_bitmap_t *bitmap) {
409 reiserfs_bitmap_t *clone;
410
411 ASSERT(bitmap != NULL, return 0);
412
413 if (!(clone = reiserfs_bitmap_alloc(bitmap->total_blocks)))
414 return NULL;
415
416 memcpy(clone->map, bitmap->map, clone->size);
417 clone->used_blocks = reiserfs_bitmap_used(clone);
418
419 return clone;
420 }
421
reiserfs_bitmap_sync(reiserfs_bitmap_t * bitmap)422 int reiserfs_bitmap_sync(reiserfs_bitmap_t *bitmap) {
423
424 if (!reiserfs_bitmap_pipe(bitmap, callback_bitmap_flush, (void *)bitmap))
425 return 0;
426
427 return 1;
428 }
429
reiserfs_bitmap_close(reiserfs_bitmap_t * bitmap)430 void reiserfs_bitmap_close(reiserfs_bitmap_t *bitmap) {
431 ASSERT(bitmap != NULL, return);
432
433 if (bitmap->map)
434 libreiserfs_free(bitmap->map);
435
436 libreiserfs_free(bitmap);
437 }
438
reiserfs_bitmap_reopen(reiserfs_bitmap_t * bitmap)439 reiserfs_bitmap_t *reiserfs_bitmap_reopen(reiserfs_bitmap_t *bitmap) {
440 blk_t start;
441 count_t len;
442 reiserfs_fs_t *fs;
443
444 ASSERT(bitmap != NULL, return NULL);
445
446 fs = bitmap->fs;
447 start = bitmap->start;
448 len = bitmap->total_blocks;
449
450 reiserfs_bitmap_close(bitmap);
451
452 return reiserfs_bitmap_open(fs, start, len);
453 }
454
reiserfs_bitmap_map(reiserfs_bitmap_t * bitmap)455 char *reiserfs_bitmap_map(reiserfs_bitmap_t *bitmap) {
456 ASSERT(bitmap != NULL, return NULL);
457 return bitmap->map;
458 }
459
460