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

Last change on this file was 09ab0a9a, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Fix vertical spacing with new Ccheck revision.

  • Property mode set to 100644
File size: 9.7 KB
RevLine 
[77bb55b]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
[b1834a01]29/** @addtogroup mfs
[77bb55b]30 * @{
31 */
32
[ba5beaf]33#include <stdlib.h>
34#include "mfs.h"
35
36static int
[147c9f6]37find_free_bit_and_set(bitchunk_t *b, const int bsize,
[6d4d883]38 const bool native, unsigned start_bit);
[ba5beaf]39
[b7fd2a0]40static errno_t
[70ac0af]41mfs_free_bit(struct mfs_instance *inst, uint32_t idx, bmap_id_t bid);
42
[b7fd2a0]43static errno_t
[70ac0af]44mfs_alloc_bit(struct mfs_instance *inst, uint32_t *idx, bmap_id_t bid);
45
[b7fd2a0]46static errno_t
[b2c96093]47mfs_count_free_bits(struct mfs_instance *inst, bmap_id_t bid, uint32_t *free);
48
[365e5e08]49/**Allocate a new inode.
50 *
51 * @param inst Pointer to the filesystem instance.
52 * @param inum Pointer to a 32 bit number where the index of
53 * the new inode will be saved.
54 *
[cde999a]55 * @return EOK on success or an error code.
[365e5e08]56 */
[b7fd2a0]57errno_t
[70ac0af]58mfs_alloc_inode(struct mfs_instance *inst, uint32_t *inum)
59{
[b7fd2a0]60 errno_t r = mfs_alloc_bit(inst, inum, BMAP_INODE);
[76b7622]61 return r;
[70ac0af]62}
63
[365e5e08]64/**Free an inode.
65 *
66 * @param inst Pointer to the filesystem instance.
67 * @param inum Number of the inode to free.
68 *
[cde999a]69 * @return EOK on success or an error code.
[365e5e08]70 */
[b7fd2a0]71errno_t
[70ac0af]72mfs_free_inode(struct mfs_instance *inst, uint32_t inum)
73{
[b5501d0]74 return mfs_free_bit(inst, inum, BMAP_INODE);
[70ac0af]75}
76
[365e5e08]77/**Allocate a new zone.
78 *
79 * @param inst Pointer to the filesystem instance.
80 * @param zone Pointer to a 32 bit number where the index
81 * of the zone will be saved.
82 *
[cde999a]83 * @return EOK on success or an error code.
[365e5e08]84 */
[b7fd2a0]85errno_t
[70ac0af]86mfs_alloc_zone(struct mfs_instance *inst, uint32_t *zone)
87{
[b7fd2a0]88 errno_t r = mfs_alloc_bit(inst, zone, BMAP_ZONE);
[1eaa3cf]89 if (r != EOK)
90 return r;
91
92 /* Update the cached number of free zones */
93 struct mfs_sb_info *sbi = inst->sbi;
94 if (sbi->nfree_zones_valid)
95 sbi->nfree_zones--;
[70ac0af]96
[38224615]97 *zone += inst->sbi->firstdatazone - 1;
[70ac0af]98 return r;
99}
100
[365e5e08]101/**Free a zone.
102 *
103 * @param inst Pointer to the filesystem instance.
104 * @param zone Index of the zone to free.
105 *
[cde999a]106 * @return EOK on success or an error code.
[365e5e08]107 */
[b7fd2a0]108errno_t
[70ac0af]109mfs_free_zone(struct mfs_instance *inst, uint32_t zone)
110{
[b7fd2a0]111 errno_t r;
[1eaa3cf]112
[38224615]113 zone -= inst->sbi->firstdatazone - 1;
[70ac0af]114
[1eaa3cf]115 r = mfs_free_bit(inst, zone, BMAP_ZONE);
116 if (r != EOK)
117 return r;
118
119 /* Update the cached number of free zones */
120 struct mfs_sb_info *sbi = inst->sbi;
121 if (sbi->nfree_zones_valid)
122 sbi->nfree_zones++;
123
124 return r;
[70ac0af]125}
126
[b2c96093]127/** Count the number of free zones
128 *
129 * @param inst Pointer to the instance structure.
130 * @param zones Pointer to the memory location where the result
131 * will be stored.
132 *
[cde999a]133 * @return EOK on success or an error code.
[b2c96093]134 */
[b7fd2a0]135errno_t
[b2c96093]136mfs_count_free_zones(struct mfs_instance *inst, uint32_t *zones)
137{
138 return mfs_count_free_bits(inst, BMAP_ZONE, zones);
139}
140
141/** Count the number of free inodes
142 *
143 * @param inst Pointer to the instance structure.
144 * @param zones Pointer to the memory location where the result
145 * will be stored.
146 *
[cde999a]147 * @return EOK on success or an error code.
[b2c96093]148 */
149
[b7fd2a0]150errno_t
[b2c96093]151mfs_count_free_inodes(struct mfs_instance *inst, uint32_t *inodes)
152{
153 return mfs_count_free_bits(inst, BMAP_INODE, inodes);
154}
155
156/** Count the number of free bits in a bitmap
157 *
158 * @param inst Pointer to the instance structure.
159 * @param bid Type of the bitmap (inode or zone).
160 * @param free Pointer to the memory location where the result
161 * will be stores.
162 *
[cde999a]163 * @return EOK on success or an error code.
[b2c96093]164 */
[b7fd2a0]165static errno_t
[b2c96093]166mfs_count_free_bits(struct mfs_instance *inst, bmap_id_t bid, uint32_t *free)
167{
[b7fd2a0]168 errno_t r;
[b2c96093]169 unsigned start_block;
170 unsigned long nblocks;
171 unsigned long nbits;
172 unsigned long block;
173 unsigned long free_bits = 0;
174 bitchunk_t chunk;
175 size_t const bitchunk_bits = sizeof(bitchunk_t) * 8;
176 block_t *b;
177 struct mfs_sb_info *sbi = inst->sbi;
178
179 start_block = MFS_BMAP_START_BLOCK(sbi, bid);
180 nblocks = MFS_BMAP_SIZE_BLOCKS(sbi, bid);
181 nbits = MFS_BMAP_SIZE_BITS(sbi, bid);
182
183 for (block = 0; block < nblocks; ++block) {
184 r = block_get(&b, inst->service_id, block + start_block,
185 BLOCK_FLAGS_NONE);
186 if (r != EOK)
187 return r;
188
189 size_t i;
190 bitchunk_t *data = (bitchunk_t *) b->data;
191
[7c3fb9b]192 /*
193 * Read the bitmap block, chunk per chunk,
[b2c96093]194 * counting the zero bits.
195 */
196 for (i = 0; i < sbi->block_size / sizeof(bitchunk_t); ++i) {
197 chunk = conv32(sbi->native, data[i]);
198
199 size_t bit;
200 for (bit = 0; bit < bitchunk_bits && nbits > 0;
201 ++bit, --nbits) {
202 if (!(chunk & (1 << bit)))
203 free_bits++;
204 }
205
206 if (nbits == 0)
207 break;
208 }
209
210 r = block_put(b);
211 if (r != EOK)
212 return r;
213 }
214
215 *free = free_bits;
216 assert(nbits == 0);
217
218 return EOK;
219}
220
[365e5e08]221/**Clear a bit in a bitmap.
222 *
223 * @param inst Pointer to the filesystem instance.
224 * @param idx Index of the bit to clear.
225 * @param bid BMAP_ZONE if operating on the zone's bitmap,
226 * BMAP_INODE if operating on the inode's bitmap.
227 *
[cde999a]228 * @return EOK on success or an error code.
[365e5e08]229 */
[b7fd2a0]230static errno_t
[2cf95e8]231mfs_free_bit(struct mfs_instance *inst, uint32_t idx, bmap_id_t bid)
232{
233 struct mfs_sb_info *sbi;
[b7fd2a0]234 errno_t r;
[2cf95e8]235 unsigned start_block;
[b489f66]236 unsigned *search;
[2cf95e8]237 block_t *b;
238
239 sbi = inst->sbi;
240
[b2c96093]241 start_block = MFS_BMAP_START_BLOCK(sbi, bid);
242
[2cf95e8]243 if (bid == BMAP_ZONE) {
[b489f66]244 search = &sbi->zsearch;
[2cf95e8]245 if (idx > sbi->nzones) {
[80445cf]246 printf(NAME ": Error! Trying to free beyond the "
[6d4d883]247 "bitmap max size\n");
[1569a9b]248 return EIO;
[2cf95e8]249 }
250 } else {
[6d4d883]251 /* bid == BMAP_INODE */
[b489f66]252 search = &sbi->isearch;
[2cf95e8]253 if (idx > sbi->ninodes) {
[80445cf]254 printf(NAME ": Error! Trying to free beyond the "
[6d4d883]255 "bitmap max size\n");
[1569a9b]256 return EIO;
[2cf95e8]257 }
258 }
259
[6d4d883]260 /* Compute the bitmap block */
[2cf95e8]261 uint32_t block = idx / (sbi->block_size * 8) + start_block;
262
[03bc76a]263 r = block_get(&b, inst->service_id, block, BLOCK_FLAGS_NONE);
[c699b0c]264 if (r != EOK)
265 goto out_err;
[2cf95e8]266
[6d4d883]267 /* Compute the bit index in the block */
[2cf95e8]268 idx %= (sbi->block_size * 8);
269 bitchunk_t *ptr = b->data;
270 bitchunk_t chunk;
[8829e33]271 const size_t chunk_bits = sizeof(bitchunk_t) * 8;
[2cf95e8]272
[8829e33]273 chunk = conv32(sbi->native, ptr[idx / chunk_bits]);
274 chunk &= ~(1 << (idx % chunk_bits));
275 ptr[idx / chunk_bits] = conv32(sbi->native, chunk);
[76b7622]276
[2cf95e8]277 b->dirty = true;
[8a49fed]278 r = block_put(b);
[2cf95e8]279
[b489f66]280 if (*search > idx)
281 *search = idx;
282
[2cf95e8]283out_err:
284 return r;
285}
286
[365e5e08]287/**Search a free bit in a bitmap and mark it as used.
288 *
289 * @param inst Pointer to the filesystem instance.
290 * @param idx Pointer of a 32 bit number where the index
291 * of the found bit will be stored.
292 * @param bid BMAP_ZONE if operating on the zone's bitmap,
293 * BMAP_INODE if operating on the inode's bitmap.
294 *
[cde999a]295 * @return EOK on success or an error code.
[365e5e08]296 */
[b7fd2a0]297static errno_t
[ba5beaf]298mfs_alloc_bit(struct mfs_instance *inst, uint32_t *idx, bmap_id_t bid)
299{
300 struct mfs_sb_info *sbi;
[77a2d77]301 uint32_t limit;
[ba5beaf]302 unsigned long nblocks;
[77a2d77]303 unsigned *search, i, start_block;
[147c9f6]304 unsigned bits_per_block;
[b7fd2a0]305 errno_t r;
[1569a9b]306 int freebit;
[ba5beaf]307
308 sbi = inst->sbi;
309
[b2c96093]310 start_block = MFS_BMAP_START_BLOCK(sbi, bid);
311 limit = MFS_BMAP_SIZE_BITS(sbi, bid);
312 nblocks = MFS_BMAP_SIZE_BLOCKS(sbi, bid);
313
[ba5beaf]314 if (bid == BMAP_ZONE) {
315 search = &sbi->zsearch;
316 } else {
[c2e50d7]317 /* bid == BMAP_INODE */
[ba5beaf]318 search = &sbi->isearch;
319 }
[147c9f6]320 bits_per_block = sbi->block_size * 8;
[ba5beaf]321
322 block_t *b;
323
324retry:
325
[147c9f6]326 for (i = *search / bits_per_block; i < nblocks; ++i) {
[03bc76a]327 r = block_get(&b, inst->service_id, i + start_block,
[c2e50d7]328 BLOCK_FLAGS_NONE);
[ba5beaf]329
[c699b0c]330 if (r != EOK)
331 goto out;
[ba5beaf]332
[40949d5]333 unsigned tmp = *search % bits_per_block;
334
[ba5beaf]335 freebit = find_free_bit_and_set(b->data, sbi->block_size,
[6d4d883]336 sbi->native, tmp);
[ba5beaf]337 if (freebit == -1) {
[6d4d883]338 /* No free bit in this block */
[9530d94]339 r = block_put(b);
[c699b0c]340 if (r != EOK)
341 goto out;
[ba5beaf]342 continue;
343 }
344
[6d4d883]345 /* Free bit found in this block, compute the real index */
[a900fb1]346 *idx = freebit + bits_per_block * i;
[77a2d77]347 if (*idx > limit) {
[6d4d883]348 /* Index is beyond the limit, it is invalid */
[8a49fed]349 r = block_put(b);
[c699b0c]350 if (r != EOK)
351 goto out;
[77a2d77]352 break;
353 }
354
[8829e33]355 *search = *idx;
[ba5beaf]356 b->dirty = true;
[8a49fed]357 r = block_put(b);
358 goto out;
[ba5beaf]359 }
360
361 if (*search > 0) {
[6d4d883]362 /* Repeat the search from the first bitmap block */
[ba5beaf]363 *search = 0;
364 goto retry;
365 }
366
[6d4d883]367 /* Free bit not found, return error */
[ba5beaf]368 return ENOSPC;
369
370out:
371 return r;
372}
373
374static int
[147c9f6]375find_free_bit_and_set(bitchunk_t *b, const int bsize,
[6d4d883]376 const bool native, unsigned start_bit)
[ba5beaf]377{
378 int r = -1;
379 unsigned i, j;
380 bitchunk_t chunk;
[8829e33]381 const size_t chunk_bits = sizeof(bitchunk_t) * 8;
[ba5beaf]382
[40949d5]383 for (i = start_bit / chunk_bits;
[6d4d883]384 i < bsize / sizeof(bitchunk_t); ++i) {
385
[6fcc03a]386 if (!(~b[i])) {
[6d4d883]387 /* No free bit in this chunk */
[ba5beaf]388 continue;
389 }
390
[147c9f6]391 chunk = conv32(native, b[i]);
[ba5beaf]392
[8829e33]393 for (j = 0; j < chunk_bits; ++j) {
[a900fb1]394 if (!(chunk & (1 << j))) {
[8829e33]395 r = i * chunk_bits + j;
[ba5beaf]396 chunk |= 1 << j;
[147c9f6]397 b[i] = conv32(native, chunk);
[ba5beaf]398 goto found;
399 }
400 }
401 }
402found:
403 return r;
404}
405
[77bb55b]406/**
407 * @}
[44c6091f]408 */
Note: See TracBrowser for help on using the repository browser.