2 * linux/fs/hfs/bitmap.c
4 * Copyright (C) 1996-1997 Paul H. Hargrove
5 * This file may be distributed under the terms of the GNU Public License.
7 * Based on GPLed code Copyright (C) 1995 Michael Dreher
9 * This file contains the code to modify the volume bitmap:
10 * search/set/clear bits.
12 * "XXX" in a comment is a note to myself to consider changing something.
14 * In function preconditions the term "valid" applied to a pointer to
15 * a structure means that the pointer is non-NULL and the structure it
16 * points to has all fields initialized to consistent values.
21 /*================ Global functions ================*/
24 * hfs_vbm_count_free()
27 * Count the number of consecutive cleared bits in the bitmap blocks of
28 * the hfs MDB starting at bit number 'start'. 'mdb' had better
29 * be locked or the indicated number of blocks may be no longer free,
30 * when this functions returns!
32 * struct hfs_mdb *mdb: Pointer to the hfs MDB
33 * hfs_u16 start: bit number to start at
37 * The number of consecutive cleared bits starting at bit 'start'
39 * 'mdb' points to a "valid" (struct hfs_mdb).
43 hfs_u16
hfs_vbm_count_free(const struct hfs_mdb
*mdb
, hfs_u16 start
)
45 hfs_u16 block_nr
; /* index of the current bitmap block */
46 hfs_u16 bit_nr
; /* index of the current bit in block */
47 hfs_u16 count
; /* number of bits found so far */
48 hfs_u16 len
; /* number of bits found in this block */
49 hfs_u16 max_block
; /* index of last bitmap block */
50 hfs_u16 max_bits
; /* index of last bit in block */
52 /* is this a valid HFS MDB? */
57 block_nr
= start
/ HFS_BM_BPB
;
58 bit_nr
= start
% HFS_BM_BPB
;
59 max_block
= (mdb
->fs_ablocks
+ HFS_BM_BPB
- 1) / HFS_BM_BPB
- 1;
62 while (block_nr
<= max_block
) {
63 if (block_nr
!= max_block
) {
64 max_bits
= HFS_BM_BPB
;
66 max_bits
= mdb
->fs_ablocks
% HFS_BM_BPB
;
69 len
=hfs_count_zero_bits(hfs_buffer_data(mdb
->bitmap
[block_nr
]),
73 /* see if we fell short of the end of this block */
74 if ((len
+ bit_nr
) < max_bits
) {
85 * hfs_vbm_search_free()
88 * Search for 'num_bits' consecutive cleared bits in the bitmap blocks of
89 * the hfs MDB. 'mdb' had better be locked or the returned range
90 * may be no longer free, when this functions returns!
91 * XXX Currently the search starts from bit 0, but it should start with
92 * the bit number stored in 's_alloc_ptr' of the MDB.
94 * struct hfs_mdb *mdb: Pointer to the hfs MDB
95 * hfs_u16 *num_bits: Pointer to the number of cleared bits
98 * hfs_u16 *num_bits: The number of consecutive clear bits of the
99 * returned range. If the bitmap is fragmented, this will be less than
100 * requested and it will be zero, when the disk is full.
102 * The number of the first bit of the range of cleared bits which has been
103 * found. When 'num_bits' is zero, this is invalid!
105 * 'mdb' points to a "valid" (struct hfs_mdb).
106 * 'num_bits' points to a variable of type (hfs_u16), which contains
107 * the number of cleared bits to find.
109 * 'num_bits' is set to the length of the found sequence.
111 hfs_u16
hfs_vbm_search_free(const struct hfs_mdb
*mdb
, hfs_u16
*num_bits
)
113 hfs_u16 block_nr
; /* index of the current bitmap block */
115 /* position and length of current portion of a run */
116 hfs_u16 cur_pos
, cur_len
;
118 /* position and length of current complete run */
119 hfs_u16 pos
=0, len
=0;
121 /* position and length of longest complete run */
122 hfs_u16 longest_pos
=0, longest_len
=0;
124 void *bitmap
; /* contents of the current bitmap block */
125 hfs_u16 max_block
; /* upper limit of outer loop */
126 hfs_u16 max_bits
; /* upper limit of inner loop */
128 /* is this a valid HFS MDB? */
131 hfs_warn("hfs_vbm_search_free: not a valid MDB\n");
135 /* make sure we have actual work to perform */
140 max_block
= (mdb
->fs_ablocks
+HFS_BM_BPB
-1) / HFS_BM_BPB
- 1;
142 /* search all bitmap blocks */
143 for (block_nr
= 0; block_nr
<= max_block
; block_nr
++) {
144 bitmap
= hfs_buffer_data(mdb
->bitmap
[block_nr
]);
146 if (block_nr
!= max_block
) {
147 max_bits
= HFS_BM_BPB
;
149 max_bits
= mdb
->fs_ablocks
% HFS_BM_BPB
;
154 cur_len
= hfs_count_zero_bits(bitmap
, max_bits
,
157 if (len
> longest_len
) {
160 if (len
>= *num_bits
) {
164 if ((cur_pos
+ cur_len
) == max_bits
) {
165 break; /* zeros may continue into next block */
168 /* find start of next run of zeros */
169 cur_pos
= hfs_find_zero_bit(bitmap
, max_bits
,
171 pos
= cur_pos
+ HFS_BM_BPB
*block_nr
;
173 } while (cur_pos
< max_bits
);
177 *num_bits
= longest_len
;
186 * Set the requested bits in the volume bitmap of the hfs filesystem
188 * struct hfs_mdb *mdb: Pointer to the hfs MDB
189 * hfs_u16 start: The offset of the first bit
190 * hfs_u16 count: The number of bits
191 * Output Variable(s):
195 * -1: One of the bits was already set. This is a strange
196 * error and when it happens, the filesystem must be repaired!
197 * -2: One or more of the bits are out of range of the bitmap.
198 * -3: The 's_magic' field of the MDB does not match
200 * 'mdb' points to a "valid" (struct hfs_mdb).
202 * Starting with bit number 'start', 'count' bits in the volume bitmap
203 * are set. The affected bitmap blocks are marked "dirty", the free
204 * block count of the MDB is updated and the MDB is marked dirty.
206 int hfs_set_vbm_bits(struct hfs_mdb
*mdb
, hfs_u16 start
, hfs_u16 count
)
208 hfs_u16 block_nr
; /* index of the current bitmap block */
209 hfs_u16 u32_nr
; /* index of the current hfs_u32 in block */
210 hfs_u16 bit_nr
; /* index of the current bit in hfs_u32 */
211 hfs_u16 left
= count
; /* number of bits left to be set */
212 hfs_u32
*bitmap
; /* the current bitmap block's contents */
214 /* is this a valid HFS MDB? */
219 /* is there any actual work to be done? */
224 /* are all of the bits in range? */
225 if ((start
+ count
) > mdb
->fs_ablocks
) {
229 block_nr
= start
/ HFS_BM_BPB
;
230 u32_nr
= (start
% HFS_BM_BPB
) / 32;
233 /* bitmap is always on a 32-bit boundary */
234 bitmap
= (hfs_u32
*)hfs_buffer_data(mdb
->bitmap
[block_nr
]);
236 /* do any partial hfs_u32 at the start */
238 while ((bit_nr
< 32) && left
) {
239 if (hfs_set_bit(bit_nr
, bitmap
+ u32_nr
)) {
240 hfs_buffer_dirty(mdb
->bitmap
[block_nr
]);
248 /* advance u32_nr and check for end of this block */
249 if (++u32_nr
> 127) {
251 hfs_buffer_dirty(mdb
->bitmap
[block_nr
]);
253 /* bitmap is always on a 32-bit boundary */
255 hfs_buffer_data(mdb
->bitmap
[block_nr
]);
259 /* do full hfs_u32s */
261 if (bitmap
[u32_nr
] != ((hfs_u32
)0)) {
262 hfs_buffer_dirty(mdb
->bitmap
[block_nr
]);
265 bitmap
[u32_nr
] = ~((hfs_u32
)0);
268 /* advance u32_nr and check for end of this block */
269 if (++u32_nr
> 127) {
271 hfs_buffer_dirty(mdb
->bitmap
[block_nr
]);
273 /* bitmap is always on a 32-bit boundary */
275 hfs_buffer_data(mdb
->bitmap
[block_nr
]);
280 /* do any partial hfs_u32 at end */
282 if (hfs_set_bit(bit_nr
, bitmap
+ u32_nr
)) {
283 hfs_buffer_dirty(mdb
->bitmap
[block_nr
]);
290 hfs_buffer_dirty(mdb
->bitmap
[block_nr
]);
291 mdb
->free_ablocks
-= count
;
293 /* successful completion */
294 hfs_mdb_dirty(mdb
->sys_mdb
);
299 * hfs_clear_vbm_bits()
302 * Clear the requested bits in the volume bitmap of the hfs filesystem
304 * struct hfs_mdb *mdb: Pointer to the hfs MDB
305 * hfs_u16 start: The offset of the first bit
306 * hfs_u16 count: The number of bits
307 * Output Variable(s):
311 * -1: One of the bits was already clear. This is a strange
312 * error and when it happens, the filesystem must be repaired!
313 * -2: One or more of the bits are out of range of the bitmap.
314 * -3: The 's_magic' field of the MDB does not match
316 * 'mdb' points to a "valid" (struct hfs_mdb).
318 * Starting with bit number 'start', 'count' bits in the volume bitmap
319 * are cleared. The affected bitmap blocks are marked "dirty", the free
320 * block count of the MDB is updated and the MDB is marked dirty.
322 int hfs_clear_vbm_bits(struct hfs_mdb
*mdb
, hfs_u16 start
, hfs_u16 count
)
324 hfs_u16 block_nr
; /* index of the current bitmap block */
325 hfs_u16 u32_nr
; /* index of the current hfs_u32 in block */
326 hfs_u16 bit_nr
; /* index of the current bit in hfs_u32 */
327 hfs_u16 left
= count
; /* number of bits left to be set */
328 hfs_u32
*bitmap
; /* the current bitmap block's contents */
330 /* is this a valid HFS MDB? */
335 /* is there any actual work to be done? */
340 /* are all of the bits in range? */
341 if ((start
+ count
) > mdb
->fs_ablocks
) {
345 block_nr
= start
/ HFS_BM_BPB
;
346 u32_nr
= (start
% HFS_BM_BPB
) / 32;
349 /* bitmap is always on a 32-bit boundary */
350 bitmap
= (hfs_u32
*)hfs_buffer_data(mdb
->bitmap
[block_nr
]);
352 /* do any partial hfs_u32 at the start */
354 while ((bit_nr
< 32) && left
) {
355 if (!hfs_clear_bit(bit_nr
, bitmap
+ u32_nr
)) {
356 hfs_buffer_dirty(mdb
->bitmap
[block_nr
]);
364 /* advance u32_nr and check for end of this block */
365 if (++u32_nr
> 127) {
367 hfs_buffer_dirty(mdb
->bitmap
[block_nr
]);
369 /* bitmap is always on a 32-bit boundary */
371 hfs_buffer_data(mdb
->bitmap
[block_nr
]);
375 /* do full hfs_u32s */
377 if (bitmap
[u32_nr
] != ~((hfs_u32
)0)) {
378 hfs_buffer_dirty(mdb
->bitmap
[block_nr
]);
381 bitmap
[u32_nr
] = ((hfs_u32
)0);
384 /* advance u32_nr and check for end of this block */
385 if (++u32_nr
> 127) {
387 hfs_buffer_dirty(mdb
->bitmap
[block_nr
]);
389 /* bitmap is always on a 32-bit boundary */
391 hfs_buffer_data(mdb
->bitmap
[block_nr
]);
396 /* do any partial hfs_u32 at end */
398 if (!hfs_clear_bit(bit_nr
, bitmap
+ u32_nr
)) {
399 hfs_buffer_dirty(mdb
->bitmap
[block_nr
]);
406 hfs_buffer_dirty(mdb
->bitmap
[block_nr
]);
407 mdb
->free_ablocks
+= count
;
409 /* successful completion */
410 hfs_mdb_dirty(mdb
->sys_mdb
);