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

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

cstyle

  • Property mode set to 100644
File size: 7.1 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
[70ac0af]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
[365e5e08]46/**Allocate a new inode.
47 *
48 * @param inst Pointer to the filesystem instance.
49 * @param inum Pointer to a 32 bit number where the index of
50 * the new inode will be saved.
51 *
52 * @return EOK on success or a negative error code.
53 */
[70ac0af]54int
55mfs_alloc_inode(struct mfs_instance *inst, uint32_t *inum)
56{
[76b7622]57 int r = mfs_alloc_bit(inst, inum, BMAP_INODE);
58 return r;
[70ac0af]59}
60
[365e5e08]61/**Free an inode.
62 *
63 * @param inst Pointer to the filesystem instance.
64 * @param inum Number of the inode to free.
65 *
66 * @return EOK on success or a negative error code.
67 */
[70ac0af]68int
69mfs_free_inode(struct mfs_instance *inst, uint32_t inum)
70{
[b5501d0]71 return mfs_free_bit(inst, inum, BMAP_INODE);
[70ac0af]72}
73
[365e5e08]74/**Allocate a new zone.
75 *
76 * @param inst Pointer to the filesystem instance.
77 * @param zone Pointer to a 32 bit number where the index
78 * of the zone will be saved.
79 *
80 * @return EOK on success or a negative error code.
81 */
[70ac0af]82int
83mfs_alloc_zone(struct mfs_instance *inst, uint32_t *zone)
84{
85 int r = mfs_alloc_bit(inst, zone, BMAP_ZONE);
86
[38224615]87 *zone += inst->sbi->firstdatazone - 1;
[70ac0af]88 return r;
89}
90
[365e5e08]91/**Free a zone.
92 *
93 * @param inst Pointer to the filesystem instance.
94 * @param zone Index of the zone to free.
95 *
96 * @return EOK on success or a negative error code.
97 */
[2cf95e8]98int
[70ac0af]99mfs_free_zone(struct mfs_instance *inst, uint32_t zone)
100{
[38224615]101 zone -= inst->sbi->firstdatazone - 1;
[70ac0af]102
103 return mfs_free_bit(inst, zone, BMAP_ZONE);
104}
105
[365e5e08]106/**Clear a bit in a bitmap.
107 *
108 * @param inst Pointer to the filesystem instance.
109 * @param idx Index of the bit to clear.
110 * @param bid BMAP_ZONE if operating on the zone's bitmap,
111 * BMAP_INODE if operating on the inode's bitmap.
112 *
113 * @return EOK on success or a negative error code.
114 */
[70ac0af]115static int
[2cf95e8]116mfs_free_bit(struct mfs_instance *inst, uint32_t idx, bmap_id_t bid)
117{
118 struct mfs_sb_info *sbi;
119 int r;
120 unsigned start_block;
[b489f66]121 unsigned *search;
[2cf95e8]122 block_t *b;
123
124 sbi = inst->sbi;
125
126 if (bid == BMAP_ZONE) {
[b489f66]127 search = &sbi->zsearch;
[2cf95e8]128 start_block = 2 + sbi->ibmap_blocks;
129 if (idx > sbi->nzones) {
130 printf(NAME ": Error! Trying to free beyond the" \
[6d4d883]131 "bitmap max size\n");
[2cf95e8]132 return -1;
133 }
134 } else {
[6d4d883]135 /* bid == BMAP_INODE */
[b489f66]136 search = &sbi->isearch;
[2cf95e8]137 start_block = 2;
138 if (idx > sbi->ninodes) {
139 printf(NAME ": Error! Trying to free beyond the" \
[6d4d883]140 "bitmap max size\n");
[2cf95e8]141 return -1;
142 }
143 }
144
[6d4d883]145 /* Compute the bitmap block */
[2cf95e8]146 uint32_t block = idx / (sbi->block_size * 8) + start_block;
147
[03bc76a]148 r = block_get(&b, inst->service_id, block, BLOCK_FLAGS_NONE);
[c699b0c]149 if (r != EOK)
150 goto out_err;
[2cf95e8]151
[6d4d883]152 /* Compute the bit index in the block */
[2cf95e8]153 idx %= (sbi->block_size * 8);
154 bitchunk_t *ptr = b->data;
155 bitchunk_t chunk;
[8829e33]156 const size_t chunk_bits = sizeof(bitchunk_t) * 8;
[2cf95e8]157
[8829e33]158 chunk = conv32(sbi->native, ptr[idx / chunk_bits]);
159 chunk &= ~(1 << (idx % chunk_bits));
160 ptr[idx / chunk_bits] = conv32(sbi->native, chunk);
[76b7622]161
[2cf95e8]162 b->dirty = true;
[8a49fed]163 r = block_put(b);
[2cf95e8]164
[b489f66]165 if (*search > idx)
166 *search = idx;
167
[2cf95e8]168out_err:
169 return r;
170}
171
[365e5e08]172/**Search a free bit in a bitmap and mark it as used.
173 *
174 * @param inst Pointer to the filesystem instance.
175 * @param idx Pointer of a 32 bit number where the index
176 * of the found bit will be stored.
177 * @param bid BMAP_ZONE if operating on the zone's bitmap,
178 * BMAP_INODE if operating on the inode's bitmap.
179 *
180 * @return EOK on success or a negative error code.
181 */
[70ac0af]182static int
[ba5beaf]183mfs_alloc_bit(struct mfs_instance *inst, uint32_t *idx, bmap_id_t bid)
184{
185 struct mfs_sb_info *sbi;
[77a2d77]186 uint32_t limit;
[ba5beaf]187 unsigned long nblocks;
[77a2d77]188 unsigned *search, i, start_block;
[147c9f6]189 unsigned bits_per_block;
[ba5beaf]190 int r, freebit;
191
192 sbi = inst->sbi;
193
194 if (bid == BMAP_ZONE) {
195 search = &sbi->zsearch;
196 start_block = 2 + sbi->ibmap_blocks;
197 nblocks = sbi->zbmap_blocks;
[a4726cb]198 limit = sbi->nzones - sbi->firstdatazone - 1;
[ba5beaf]199 } else {
[c2e50d7]200 /* bid == BMAP_INODE */
[ba5beaf]201 search = &sbi->isearch;
202 start_block = 2;
203 nblocks = sbi->ibmap_blocks;
[77a2d77]204 limit = sbi->ninodes;
[ba5beaf]205 }
[147c9f6]206 bits_per_block = sbi->block_size * 8;
[ba5beaf]207
208 block_t *b;
209
210retry:
211
[147c9f6]212 for (i = *search / bits_per_block; i < nblocks; ++i) {
[03bc76a]213 r = block_get(&b, inst->service_id, i + start_block,
[c2e50d7]214 BLOCK_FLAGS_NONE);
[ba5beaf]215
[c699b0c]216 if (r != EOK)
217 goto out;
[ba5beaf]218
[40949d5]219 unsigned tmp = *search % bits_per_block;
220
[ba5beaf]221 freebit = find_free_bit_and_set(b->data, sbi->block_size,
[6d4d883]222 sbi->native, tmp);
[ba5beaf]223 if (freebit == -1) {
[6d4d883]224 /* No free bit in this block */
[9530d94]225 r = block_put(b);
[c699b0c]226 if (r != EOK)
227 goto out;
[ba5beaf]228 continue;
229 }
230
[6d4d883]231 /* Free bit found in this block, compute the real index */
[a900fb1]232 *idx = freebit + bits_per_block * i;
[77a2d77]233 if (*idx > limit) {
[6d4d883]234 /* Index is beyond the limit, it is invalid */
[8a49fed]235 r = block_put(b);
[c699b0c]236 if (r != EOK)
237 goto out;
[77a2d77]238 break;
239 }
240
[8829e33]241 *search = *idx;
[ba5beaf]242 b->dirty = true;
[8a49fed]243 r = block_put(b);
244 goto out;
[ba5beaf]245 }
246
247 if (*search > 0) {
[6d4d883]248 /* Repeat the search from the first bitmap block */
[ba5beaf]249 *search = 0;
250 goto retry;
251 }
252
[6d4d883]253 /* Free bit not found, return error */
[ba5beaf]254 return ENOSPC;
255
256out:
257 return r;
258}
259
260static int
[147c9f6]261find_free_bit_and_set(bitchunk_t *b, const int bsize,
[6d4d883]262 const bool native, unsigned start_bit)
[ba5beaf]263{
264 int r = -1;
265 unsigned i, j;
266 bitchunk_t chunk;
[8829e33]267 const size_t chunk_bits = sizeof(bitchunk_t) * 8;
[ba5beaf]268
[40949d5]269 for (i = start_bit / chunk_bits;
[6d4d883]270 i < bsize / sizeof(bitchunk_t); ++i) {
271
[6fcc03a]272 if (!(~b[i])) {
[6d4d883]273 /* No free bit in this chunk */
[ba5beaf]274 continue;
275 }
276
[147c9f6]277 chunk = conv32(native, b[i]);
[ba5beaf]278
[8829e33]279 for (j = 0; j < chunk_bits; ++j) {
[a900fb1]280 if (!(chunk & (1 << j))) {
[8829e33]281 r = i * chunk_bits + j;
[ba5beaf]282 chunk |= 1 << j;
[147c9f6]283 b[i] = conv32(native, chunk);
[ba5beaf]284 goto found;
285 }
286 }
287 }
288found:
289 return r;
290}
291
[77bb55b]292/**
293 * @}
[44c6091f]294 */
[77bb55b]295
Note: See TracBrowser for help on using the repository browser.