source: mainline/uspace/srv/fs/mfs/mfs_balloc.c@ cc8044e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since cc8044e was b2c96093, checked in by Maurizio Lombardi <m.lombardi85@…>, 12 years ago

mfs: add functions to get the number of free entries in the bitmaps.

  • Property mode set to 100644
File size: 9.4 KB
Line 
1/*
2 * Copyright (c) 2011 Maurizio Lombardi
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup fs
30 * @{
31 */
32
33#include <stdlib.h>
34#include "mfs.h"
35
36static int
37find_free_bit_and_set(bitchunk_t *b, const int bsize,
38 const bool native, unsigned start_bit);
39
40static int
41mfs_free_bit(struct mfs_instance *inst, uint32_t idx, bmap_id_t bid);
42
43static int
44mfs_alloc_bit(struct mfs_instance *inst, uint32_t *idx, bmap_id_t bid);
45
46static int
47mfs_count_free_bits(struct mfs_instance *inst, bmap_id_t bid, uint32_t *free);
48
49
50/**Allocate a new inode.
51 *
52 * @param inst Pointer to the filesystem instance.
53 * @param inum Pointer to a 32 bit number where the index of
54 * the new inode will be saved.
55 *
56 * @return EOK on success or a negative error code.
57 */
58int
59mfs_alloc_inode(struct mfs_instance *inst, uint32_t *inum)
60{
61 int r = mfs_alloc_bit(inst, inum, BMAP_INODE);
62 return r;
63}
64
65/**Free an inode.
66 *
67 * @param inst Pointer to the filesystem instance.
68 * @param inum Number of the inode to free.
69 *
70 * @return EOK on success or a negative error code.
71 */
72int
73mfs_free_inode(struct mfs_instance *inst, uint32_t inum)
74{
75 return mfs_free_bit(inst, inum, BMAP_INODE);
76}
77
78/**Allocate a new zone.
79 *
80 * @param inst Pointer to the filesystem instance.
81 * @param zone Pointer to a 32 bit number where the index
82 * of the zone will be saved.
83 *
84 * @return EOK on success or a negative error code.
85 */
86int
87mfs_alloc_zone(struct mfs_instance *inst, uint32_t *zone)
88{
89 int r = mfs_alloc_bit(inst, zone, BMAP_ZONE);
90
91 *zone += inst->sbi->firstdatazone - 1;
92 return r;
93}
94
95/**Free a zone.
96 *
97 * @param inst Pointer to the filesystem instance.
98 * @param zone Index of the zone to free.
99 *
100 * @return EOK on success or a negative error code.
101 */
102int
103mfs_free_zone(struct mfs_instance *inst, uint32_t zone)
104{
105 zone -= inst->sbi->firstdatazone - 1;
106
107 return mfs_free_bit(inst, zone, BMAP_ZONE);
108}
109
110/** Count the number of free zones
111 *
112 * @param inst Pointer to the instance structure.
113 * @param zones Pointer to the memory location where the result
114 * will be stored.
115 *
116 * @return EOK on success or a negative error code.
117 */
118int
119mfs_count_free_zones(struct mfs_instance *inst, uint32_t *zones)
120{
121 return mfs_count_free_bits(inst, BMAP_ZONE, zones);
122}
123
124/** Count the number of free inodes
125 *
126 * @param inst Pointer to the instance structure.
127 * @param zones Pointer to the memory location where the result
128 * will be stored.
129 *
130 * @return EOK on success or a negative error code.
131 */
132
133int
134mfs_count_free_inodes(struct mfs_instance *inst, uint32_t *inodes)
135{
136 return mfs_count_free_bits(inst, BMAP_INODE, inodes);
137}
138
139/** Count the number of free bits in a bitmap
140 *
141 * @param inst Pointer to the instance structure.
142 * @param bid Type of the bitmap (inode or zone).
143 * @param free Pointer to the memory location where the result
144 * will be stores.
145 *
146 * @return EOK on success or a negative error code.
147 */
148static int
149mfs_count_free_bits(struct mfs_instance *inst, bmap_id_t bid, uint32_t *free)
150{
151 int r;
152 unsigned start_block;
153 unsigned long nblocks;
154 unsigned long nbits;
155 unsigned long block;
156 unsigned long free_bits = 0;
157 bitchunk_t chunk;
158 size_t const bitchunk_bits = sizeof(bitchunk_t) * 8;
159 block_t *b;
160 struct mfs_sb_info *sbi = inst->sbi;
161
162 start_block = MFS_BMAP_START_BLOCK(sbi, bid);
163 nblocks = MFS_BMAP_SIZE_BLOCKS(sbi, bid);
164 nbits = MFS_BMAP_SIZE_BITS(sbi, bid);
165
166 for (block = 0; block < nblocks; ++block) {
167 r = block_get(&b, inst->service_id, block + start_block,
168 BLOCK_FLAGS_NONE);
169 if (r != EOK)
170 return r;
171
172 size_t i;
173 bitchunk_t *data = (bitchunk_t *) b->data;
174
175 /* Read the bitmap block, chunk per chunk,
176 * counting the zero bits.
177 */
178 for (i = 0; i < sbi->block_size / sizeof(bitchunk_t); ++i) {
179 chunk = conv32(sbi->native, data[i]);
180
181 size_t bit;
182 for (bit = 0; bit < bitchunk_bits && nbits > 0;
183 ++bit, --nbits) {
184 if (!(chunk & (1 << bit)))
185 free_bits++;
186 }
187
188 if (nbits == 0)
189 break;
190 }
191
192 r = block_put(b);
193 if (r != EOK)
194 return r;
195 }
196
197 *free = free_bits;
198 assert(nbits == 0);
199
200 return EOK;
201}
202
203/**Clear a bit in a bitmap.
204 *
205 * @param inst Pointer to the filesystem instance.
206 * @param idx Index of the bit to clear.
207 * @param bid BMAP_ZONE if operating on the zone's bitmap,
208 * BMAP_INODE if operating on the inode's bitmap.
209 *
210 * @return EOK on success or a negative error code.
211 */
212static int
213mfs_free_bit(struct mfs_instance *inst, uint32_t idx, bmap_id_t bid)
214{
215 struct mfs_sb_info *sbi;
216 int r;
217 unsigned start_block;
218 unsigned *search;
219 block_t *b;
220
221 sbi = inst->sbi;
222
223 start_block = MFS_BMAP_START_BLOCK(sbi, bid);
224
225 if (bid == BMAP_ZONE) {
226 search = &sbi->zsearch;
227 if (idx > sbi->nzones) {
228 printf(NAME ": Error! Trying to free beyond the "
229 "bitmap max size\n");
230 return -1;
231 }
232 } else {
233 /* bid == BMAP_INODE */
234 search = &sbi->isearch;
235 if (idx > sbi->ninodes) {
236 printf(NAME ": Error! Trying to free beyond the "
237 "bitmap max size\n");
238 return -1;
239 }
240 }
241
242 /* Compute the bitmap block */
243 uint32_t block = idx / (sbi->block_size * 8) + start_block;
244
245 r = block_get(&b, inst->service_id, block, BLOCK_FLAGS_NONE);
246 if (r != EOK)
247 goto out_err;
248
249 /* Compute the bit index in the block */
250 idx %= (sbi->block_size * 8);
251 bitchunk_t *ptr = b->data;
252 bitchunk_t chunk;
253 const size_t chunk_bits = sizeof(bitchunk_t) * 8;
254
255 chunk = conv32(sbi->native, ptr[idx / chunk_bits]);
256 chunk &= ~(1 << (idx % chunk_bits));
257 ptr[idx / chunk_bits] = conv32(sbi->native, chunk);
258
259 b->dirty = true;
260 r = block_put(b);
261
262 if (*search > idx)
263 *search = idx;
264
265out_err:
266 return r;
267}
268
269/**Search a free bit in a bitmap and mark it as used.
270 *
271 * @param inst Pointer to the filesystem instance.
272 * @param idx Pointer of a 32 bit number where the index
273 * of the found bit will be stored.
274 * @param bid BMAP_ZONE if operating on the zone's bitmap,
275 * BMAP_INODE if operating on the inode's bitmap.
276 *
277 * @return EOK on success or a negative error code.
278 */
279static int
280mfs_alloc_bit(struct mfs_instance *inst, uint32_t *idx, bmap_id_t bid)
281{
282 struct mfs_sb_info *sbi;
283 uint32_t limit;
284 unsigned long nblocks;
285 unsigned *search, i, start_block;
286 unsigned bits_per_block;
287 int r, freebit;
288
289 sbi = inst->sbi;
290
291 start_block = MFS_BMAP_START_BLOCK(sbi, bid);
292 limit = MFS_BMAP_SIZE_BITS(sbi, bid);
293 nblocks = MFS_BMAP_SIZE_BLOCKS(sbi, bid);
294
295 if (bid == BMAP_ZONE) {
296 search = &sbi->zsearch;
297 } else {
298 /* bid == BMAP_INODE */
299 search = &sbi->isearch;
300 }
301 bits_per_block = sbi->block_size * 8;
302
303 block_t *b;
304
305retry:
306
307 for (i = *search / bits_per_block; i < nblocks; ++i) {
308 r = block_get(&b, inst->service_id, i + start_block,
309 BLOCK_FLAGS_NONE);
310
311 if (r != EOK)
312 goto out;
313
314 unsigned tmp = *search % bits_per_block;
315
316 freebit = find_free_bit_and_set(b->data, sbi->block_size,
317 sbi->native, tmp);
318 if (freebit == -1) {
319 /* No free bit in this block */
320 r = block_put(b);
321 if (r != EOK)
322 goto out;
323 continue;
324 }
325
326 /* Free bit found in this block, compute the real index */
327 *idx = freebit + bits_per_block * i;
328 if (*idx > limit) {
329 /* Index is beyond the limit, it is invalid */
330 r = block_put(b);
331 if (r != EOK)
332 goto out;
333 break;
334 }
335
336 *search = *idx;
337 b->dirty = true;
338 r = block_put(b);
339 goto out;
340 }
341
342 if (*search > 0) {
343 /* Repeat the search from the first bitmap block */
344 *search = 0;
345 goto retry;
346 }
347
348 /* Free bit not found, return error */
349 return ENOSPC;
350
351out:
352 return r;
353}
354
355static int
356find_free_bit_and_set(bitchunk_t *b, const int bsize,
357 const bool native, unsigned start_bit)
358{
359 int r = -1;
360 unsigned i, j;
361 bitchunk_t chunk;
362 const size_t chunk_bits = sizeof(bitchunk_t) * 8;
363
364 for (i = start_bit / chunk_bits;
365 i < bsize / sizeof(bitchunk_t); ++i) {
366
367 if (!(~b[i])) {
368 /* No free bit in this chunk */
369 continue;
370 }
371
372 chunk = conv32(native, b[i]);
373
374 for (j = 0; j < chunk_bits; ++j) {
375 if (!(chunk & (1 << j))) {
376 r = i * chunk_bits + j;
377 chunk |= 1 << j;
378 b[i] = conv32(native, chunk);
379 goto found;
380 }
381 }
382 }
383found:
384 return r;
385}
386
387/**
388 * @}
389 */
390
Note: See TracBrowser for help on using the repository browser.