xref: /openbmc/linux/fs/hfsplus/bitmap.c (revision 1fa6ac37)
1 /*
2  *  linux/fs/hfsplus/bitmap.c
3  *
4  * Copyright (C) 2001
5  * Brad Boyer (flar@allandria.com)
6  * (C) 2003 Ardis Technologies <roman@ardistech.com>
7  *
8  * Handling of allocation file
9  */
10 
11 #include <linux/pagemap.h>
12 
13 #include "hfsplus_fs.h"
14 #include "hfsplus_raw.h"
15 
16 #define PAGE_CACHE_BITS	(PAGE_CACHE_SIZE * 8)
17 
18 int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *max)
19 {
20 	struct page *page;
21 	struct address_space *mapping;
22 	__be32 *pptr, *curr, *end;
23 	u32 mask, start, len, n;
24 	__be32 val;
25 	int i;
26 
27 	len = *max;
28 	if (!len)
29 		return size;
30 
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);
35 	if (IS_ERR(page)) {
36 		start = size;
37 		goto out;
38 	}
39 	pptr = kmap(page);
40 	curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32;
41 	i = offset % 32;
42 	offset &= ~(PAGE_CACHE_BITS - 1);
43 	if ((size ^ offset) / PAGE_CACHE_BITS)
44 		end = pptr + PAGE_CACHE_BITS / 32;
45 	else
46 		end = pptr + ((size + 31) & (PAGE_CACHE_BITS - 1)) / 32;
47 
48 	/* scan the first partial u32 for zero bits */
49 	val = *curr;
50 	if (~val) {
51 		n = be32_to_cpu(val);
52 		mask = (1U << 31) >> i;
53 		for (; i < 32; mask >>= 1, i++) {
54 			if (!(n & mask))
55 				goto found;
56 		}
57 	}
58 	curr++;
59 
60 	/* scan complete u32s for the first zero bit */
61 	while (1) {
62 		while (curr < end) {
63 			val = *curr;
64 			if (~val) {
65 				n = be32_to_cpu(val);
66 				mask = 1 << 31;
67 				for (i = 0; i < 32; mask >>= 1, i++) {
68 					if (!(n & mask))
69 						goto found;
70 				}
71 			}
72 			curr++;
73 		}
74 		kunmap(page);
75 		offset += PAGE_CACHE_BITS;
76 		if (offset >= size)
77 			break;
78 		page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS,
79 					 NULL);
80 		if (IS_ERR(page)) {
81 			start = size;
82 			goto out;
83 		}
84 		curr = pptr = kmap(page);
85 		if ((size ^ offset) / PAGE_CACHE_BITS)
86 			end = pptr + PAGE_CACHE_BITS / 32;
87 		else
88 			end = pptr + ((size + 31) & (PAGE_CACHE_BITS - 1)) / 32;
89 	}
90 	dprint(DBG_BITMAP, "bitmap full\n");
91 	start = size;
92 	goto out;
93 
94 found:
95 	start = offset + (curr - pptr) * 32 + i;
96 	if (start >= size) {
97 		dprint(DBG_BITMAP, "bitmap full\n");
98 		goto out;
99 	}
100 	/* do any partial u32 at the start */
101 	len = min(size - start, len);
102 	while (1) {
103 		n |= mask;
104 		if (++i >= 32)
105 			break;
106 		mask >>= 1;
107 		if (!--len || n & mask)
108 			goto done;
109 	}
110 	if (!--len)
111 		goto done;
112 	*curr++ = cpu_to_be32(n);
113 	/* do full u32s */
114 	while (1) {
115 		while (curr < end) {
116 			n = be32_to_cpu(*curr);
117 			if (len < 32)
118 				goto last;
119 			if (n) {
120 				len = 32;
121 				goto last;
122 			}
123 			*curr++ = cpu_to_be32(0xffffffff);
124 			len -= 32;
125 		}
126 		set_page_dirty(page);
127 		kunmap(page);
128 		offset += PAGE_CACHE_BITS;
129 		page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS,
130 					 NULL);
131 		if (IS_ERR(page)) {
132 			start = size;
133 			goto out;
134 		}
135 		pptr = kmap(page);
136 		curr = pptr;
137 		end = pptr + PAGE_CACHE_BITS / 32;
138 	}
139 last:
140 	/* do any partial u32 at end */
141 	mask = 1U << 31;
142 	for (i = 0; i < len; i++) {
143 		if (n & mask)
144 			break;
145 		n |= mask;
146 		mask >>= 1;
147 	}
148 done:
149 	*curr = cpu_to_be32(n);
150 	set_page_dirty(page);
151 	kunmap(page);
152 	*max = offset + (curr - pptr) * 32 + i - start;
153 	HFSPLUS_SB(sb).free_blocks -= *max;
154 	sb->s_dirt = 1;
155 	dprint(DBG_BITMAP, "-> %u,%u\n", start, *max);
156 out:
157 	mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
158 	return start;
159 }
160 
161 int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
162 {
163 	struct page *page;
164 	struct address_space *mapping;
165 	__be32 *pptr, *curr, *end;
166 	u32 mask, len, pnr;
167 	int i;
168 
169 	/* is there any actual work to be done? */
170 	if (!count)
171 		return 0;
172 
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)
176 		return -2;
177 
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);
182 	pptr = kmap(page);
183 	curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32;
184 	end = pptr + PAGE_CACHE_BITS / 32;
185 	len = count;
186 
187 	/* do any partial u32 at the start */
188 	i = offset % 32;
189 	if (i) {
190 		int j = 32 - i;
191 		mask = 0xffffffffU << j;
192 		if (j > count) {
193 			mask |= 0xffffffffU >> (i + count);
194 			*curr++ &= cpu_to_be32(mask);
195 			goto out;
196 		}
197 		*curr++ &= cpu_to_be32(mask);
198 		count -= j;
199 	}
200 
201 	/* do full u32s */
202 	while (1) {
203 		while (curr < end) {
204 			if (count < 32)
205 				goto done;
206 			*curr++ = 0;
207 			count -= 32;
208 		}
209 		if (!count)
210 			break;
211 		set_page_dirty(page);
212 		kunmap(page);
213 		page = read_mapping_page(mapping, ++pnr, NULL);
214 		pptr = kmap(page);
215 		curr = pptr;
216 		end = pptr + PAGE_CACHE_BITS / 32;
217 	}
218 done:
219 	/* do any partial u32 at end */
220 	if (count) {
221 		mask = 0xffffffffU >> count;
222 		*curr &= cpu_to_be32(mask);
223 	}
224 out:
225 	set_page_dirty(page);
226 	kunmap(page);
227 	HFSPLUS_SB(sb).free_blocks += len;
228 	sb->s_dirt = 1;
229 	mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
230 
231 	return 0;
232 }
233