2 * linux/fs/hfsplus/bitmap.c
5 * Brad Boyer (flar@allandria.com)
6 * (C) 2003 Ardis Technologies <roman@ardistech.com>
8 * Handling of allocation file
11 #include <linux/pagemap.h>
13 #include "hfsplus_fs.h"
14 #include "hfsplus_raw.h"
16 #define PAGE_CACHE_BITS (PAGE_CACHE_SIZE * 8)
18 int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *max)
21 struct address_space *mapping;
22 __be32 *pptr, *curr, *end;
23 u32 mask, start, len, n;
31 dprint(DBG_BITMAP, "block_allocate: %u,%u,%u\n", size, offset, len);
32 mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
33 mapping = HFSPLUS_SB(sb).alloc_file->i_mapping;
34 page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, NULL);
40 curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32;
42 offset &= ~(PAGE_CACHE_BITS - 1);
43 if ((size ^ offset) / PAGE_CACHE_BITS)
44 end = pptr + PAGE_CACHE_BITS / 32;
46 end = pptr + ((size + 31) & (PAGE_CACHE_BITS - 1)) / 32;
48 /* scan the first partial u32 for zero bits */
52 mask = (1U << 31) >> i;
53 for (; i < 32; mask >>= 1, i++) {
60 /* scan complete u32s for the first zero bit */
67 for (i = 0; i < 32; mask >>= 1, i++) {
75 offset += PAGE_CACHE_BITS;
78 page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS,
84 curr = pptr = kmap(page);
85 if ((size ^ offset) / PAGE_CACHE_BITS)
86 end = pptr + PAGE_CACHE_BITS / 32;
88 end = pptr + ((size + 31) & (PAGE_CACHE_BITS - 1)) / 32;
90 dprint(DBG_BITMAP, "bitmap full\n");
95 start = offset + (curr - pptr) * 32 + i;
97 dprint(DBG_BITMAP, "bitmap full\n");
100 /* do any partial u32 at the start */
101 len = min(size - start, len);
107 if (!--len || n & mask)
112 *curr++ = cpu_to_be32(n);
116 n = be32_to_cpu(*curr);
123 *curr++ = cpu_to_be32(0xffffffff);
126 set_page_dirty(page);
128 offset += PAGE_CACHE_BITS;
129 page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS,
137 end = pptr + PAGE_CACHE_BITS / 32;
140 /* do any partial u32 at end */
142 for (i = 0; i < len; i++) {
149 *curr = cpu_to_be32(n);
150 set_page_dirty(page);
152 *max = offset + (curr - pptr) * 32 + i - start;
153 HFSPLUS_SB(sb).free_blocks -= *max;
155 dprint(DBG_BITMAP, "-> %u,%u\n", start, *max);
157 mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
161 int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
164 struct address_space *mapping;
165 __be32 *pptr, *curr, *end;
169 /* is there any actual work to be done? */
173 dprint(DBG_BITMAP, "block_free: %u,%u\n", offset, count);
174 /* are all of the bits in range? */
175 if ((offset + count) > HFSPLUS_SB(sb).total_blocks)
178 mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
179 mapping = HFSPLUS_SB(sb).alloc_file->i_mapping;
180 pnr = offset / PAGE_CACHE_BITS;
181 page = read_mapping_page(mapping, pnr, NULL);
183 curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32;
184 end = pptr + PAGE_CACHE_BITS / 32;
187 /* do any partial u32 at the start */
191 mask = 0xffffffffU << j;
193 mask |= 0xffffffffU >> (i + count);
194 *curr++ &= cpu_to_be32(mask);
197 *curr++ &= cpu_to_be32(mask);
211 set_page_dirty(page);
213 page = read_mapping_page(mapping, ++pnr, NULL);
216 end = pptr + PAGE_CACHE_BITS / 32;
219 /* do any partial u32 at end */
221 mask = 0xffffffffU >> count;
222 *curr &= cpu_to_be32(mask);
225 set_page_dirty(page);
227 HFSPLUS_SB(sb).free_blocks += len;
229 mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex);