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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since ee8c5ec was 7c3fb9b, checked in by Jiri Svoboda <jiri@…>, 8 years ago

Fix block comment formatting (ccheck).

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