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