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
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
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 */
54int
55mfs_alloc_inode(struct mfs_instance *inst, uint32_t *inum)
56{
57 int r = mfs_alloc_bit(inst, inum, BMAP_INODE);
58 return r;
59}
60
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 */
68int
69mfs_free_inode(struct mfs_instance *inst, uint32_t inum)
70{
71 return mfs_free_bit(inst, inum, BMAP_INODE);
72}
73
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 */
82int
83mfs_alloc_zone(struct mfs_instance *inst, uint32_t *zone)
84{
85 int r = mfs_alloc_bit(inst, zone, BMAP_ZONE);
86
87 *zone += inst->sbi->firstdatazone - 1;
88 return r;
89}
90
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 */
98int
99mfs_free_zone(struct mfs_instance *inst, uint32_t zone)
100{
101 zone -= inst->sbi->firstdatazone - 1;
102
103 return mfs_free_bit(inst, zone, BMAP_ZONE);
104}
105
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 */
115static int
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;
121 unsigned *search;
122 block_t *b;
123
124 sbi = inst->sbi;
125
126 if (bid == BMAP_ZONE) {
127 search = &sbi->zsearch;
128 start_block = 2 + sbi->ibmap_blocks;
129 if (idx > sbi->nzones) {
130 printf(NAME ": Error! Trying to free beyond the" \
131 "bitmap max size\n");
132 return -1;
133 }
134 } else {
135 /* bid == BMAP_INODE */
136 search = &sbi->isearch;
137 start_block = 2;
138 if (idx > sbi->ninodes) {
139 printf(NAME ": Error! Trying to free beyond the" \
140 "bitmap max size\n");
141 return -1;
142 }
143 }
144
145 /* Compute the bitmap block */
146 uint32_t block = idx / (sbi->block_size * 8) + start_block;
147
148 r = block_get(&b, inst->service_id, block, BLOCK_FLAGS_NONE);
149 if (r != EOK)
150 goto out_err;
151
152 /* Compute the bit index in the block */
153 idx %= (sbi->block_size * 8);
154 bitchunk_t *ptr = b->data;
155 bitchunk_t chunk;
156 const size_t chunk_bits = sizeof(bitchunk_t) * 8;
157
158 chunk = conv32(sbi->native, ptr[idx / chunk_bits]);
159 chunk &= ~(1 << (idx % chunk_bits));
160 ptr[idx / chunk_bits] = conv32(sbi->native, chunk);
161
162 b->dirty = true;
163 r = block_put(b);
164
165 if (*search > idx)
166 *search = idx;
167
168out_err:
169 return r;
170}
171
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 */
182static int
183mfs_alloc_bit(struct mfs_instance *inst, uint32_t *idx, bmap_id_t bid)
184{
185 struct mfs_sb_info *sbi;
186 uint32_t limit;
187 unsigned long nblocks;
188 unsigned *search, i, start_block;
189 unsigned bits_per_block;
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;
198 limit = sbi->nzones - sbi->firstdatazone - 1;
199 } else {
200 /* bid == BMAP_INODE */
201 search = &sbi->isearch;
202 start_block = 2;
203 nblocks = sbi->ibmap_blocks;
204 limit = sbi->ninodes;
205 }
206 bits_per_block = sbi->block_size * 8;
207
208 block_t *b;
209
210retry:
211
212 for (i = *search / bits_per_block; i < nblocks; ++i) {
213 r = block_get(&b, inst->service_id, i + start_block,
214 BLOCK_FLAGS_NONE);
215
216 if (r != EOK)
217 goto out;
218
219 unsigned tmp = *search % bits_per_block;
220
221 freebit = find_free_bit_and_set(b->data, sbi->block_size,
222 sbi->native, tmp);
223 if (freebit == -1) {
224 /* No free bit in this block */
225 r = block_put(b);
226 if (r != EOK)
227 goto out;
228 continue;
229 }
230
231 /* Free bit found in this block, compute the real index */
232 *idx = freebit + bits_per_block * i;
233 if (*idx > limit) {
234 /* Index is beyond the limit, it is invalid */
235 r = block_put(b);
236 if (r != EOK)
237 goto out;
238 break;
239 }
240
241 *search = *idx;
242 b->dirty = true;
243 r = block_put(b);
244 goto out;
245 }
246
247 if (*search > 0) {
248 /* Repeat the search from the first bitmap block */
249 *search = 0;
250 goto retry;
251 }
252
253 /* Free bit not found, return error */
254 return ENOSPC;
255
256out:
257 return r;
258}
259
260static int
261find_free_bit_and_set(bitchunk_t *b, const int bsize,
262 const bool native, unsigned start_bit)
263{
264 int r = -1;
265 unsigned i, j;
266 bitchunk_t chunk;
267 const size_t chunk_bits = sizeof(bitchunk_t) * 8;
268
269 for (i = start_bit / chunk_bits;
270 i < bsize / sizeof(bitchunk_t); ++i) {
271
272 if (!(~b[i])) {
273 /* No free bit in this chunk */
274 continue;
275 }
276
277 chunk = conv32(native, b[i]);
278
279 for (j = 0; j < chunk_bits; ++j) {
280 if (!(chunk & (1 << j))) {
281 r = i * chunk_bits + j;
282 chunk |= 1 << j;
283 b[i] = conv32(native, chunk);
284 goto found;
285 }
286 }
287 }
288found:
289 return r;
290}
291
292/**
293 * @}
294 */
295
Note: See TracBrowser for help on using the repository browser.