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

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

Rename mkminix —> mkmfs
Rename the directory minixfs —> mfs

  • Property mode set to 100644
File size: 7.2 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 assert(inst != NULL);
125 sbi = inst->sbi;
126 assert(sbi != NULL);
127
128 if (bid == BMAP_ZONE) {
129 search = &sbi->zsearch;
130 start_block = 2 + sbi->ibmap_blocks;
131 if (idx > sbi->nzones) {
132 printf(NAME ": Error! Trying to free beyond the" \
133 "bitmap max size\n");
134 return -1;
135 }
136 } else {
137 /*bid == BMAP_INODE*/
138 search = &sbi->isearch;
139 start_block = 2;
140 if (idx > sbi->ninodes) {
141 printf(NAME ": Error! Trying to free beyond the" \
142 "bitmap max size\n");
143 return -1;
144 }
145 }
146
147 /*Compute the bitmap block*/
148 uint32_t block = idx / (sbi->block_size * 8) + start_block;
149
150 r = block_get(&b, inst->service_id, block, BLOCK_FLAGS_NONE);
151 if (r != EOK)
152 goto out_err;
153
154 /*Compute the bit index in the block*/
155 idx %= (sbi->block_size * 8);
156 bitchunk_t *ptr = b->data;
157 bitchunk_t chunk;
158 const size_t chunk_bits = sizeof(bitchunk_t) * 8;
159
160 chunk = conv32(sbi->native, ptr[idx / chunk_bits]);
161 chunk &= ~(1 << (idx % chunk_bits));
162 ptr[idx / chunk_bits] = conv32(sbi->native, chunk);
163
164 b->dirty = true;
165 r = block_put(b);
166
167 if (*search > idx)
168 *search = idx;
169
170out_err:
171 return r;
172}
173
174/**Search a free bit in a bitmap and mark it as used.
175 *
176 * @param inst Pointer to the filesystem instance.
177 * @param idx Pointer of a 32 bit number where the index
178 * of the found bit will be stored.
179 * @param bid BMAP_ZONE if operating on the zone's bitmap,
180 * BMAP_INODE if operating on the inode's bitmap.
181 *
182 * @return EOK on success or a negative error code.
183 */
184static int
185mfs_alloc_bit(struct mfs_instance *inst, uint32_t *idx, bmap_id_t bid)
186{
187 struct mfs_sb_info *sbi;
188 uint32_t limit;
189 unsigned long nblocks;
190 unsigned *search, i, start_block;
191 unsigned bits_per_block;
192 int r, freebit;
193
194 assert(inst != NULL);
195 sbi = inst->sbi;
196 assert(sbi != NULL);
197
198 if (bid == BMAP_ZONE) {
199 search = &sbi->zsearch;
200 start_block = 2 + sbi->ibmap_blocks;
201 nblocks = sbi->zbmap_blocks;
202 limit = sbi->nzones - sbi->firstdatazone - 1;
203 } else {
204 /*bid == BMAP_INODE*/
205 search = &sbi->isearch;
206 start_block = 2;
207 nblocks = sbi->ibmap_blocks;
208 limit = sbi->ninodes;
209 }
210 bits_per_block = sbi->block_size * 8;
211
212 block_t *b;
213
214retry:
215
216 for (i = *search / bits_per_block; i < nblocks; ++i) {
217 r = block_get(&b, inst->service_id, i + start_block,
218 BLOCK_FLAGS_NONE);
219
220 if (r != EOK)
221 goto out;
222
223 unsigned tmp = *search % bits_per_block;
224
225 freebit = find_free_bit_and_set(b->data, sbi->block_size,
226 sbi->native, tmp);
227 if (freebit == -1) {
228 /*No free bit in this block*/
229 r = block_put(b);
230 if (r != EOK)
231 goto out;
232 continue;
233 }
234
235 /*Free bit found in this block, compute the real index*/
236 *idx = freebit + bits_per_block * i;
237 if (*idx > limit) {
238 /*Index is beyond the limit, it is invalid*/
239 r = block_put(b);
240 if (r != EOK)
241 goto out;
242 break;
243 }
244
245 *search = *idx;
246 b->dirty = true;
247 r = block_put(b);
248 goto out;
249 }
250
251 if (*search > 0) {
252 /*Repeat the search from the first bitmap block*/
253 *search = 0;
254 goto retry;
255 }
256
257 /*Free bit not found, return error*/
258 return ENOSPC;
259
260out:
261 return r;
262}
263
264static int
265find_free_bit_and_set(bitchunk_t *b, const int bsize,
266 const bool native, unsigned start_bit)
267{
268 int r = -1;
269 unsigned i, j;
270 bitchunk_t chunk;
271 const size_t chunk_bits = sizeof(bitchunk_t) * 8;
272
273 for (i = start_bit / chunk_bits;
274 i < bsize / sizeof(bitchunk_t); ++i) {
275 if (!(~b[i])) {
276 /*No free bit in this chunk*/
277 continue;
278 }
279
280 chunk = conv32(native, b[i]);
281
282 for (j = 0; j < chunk_bits; ++j) {
283 if (!(chunk & (1 << j))) {
284 r = i * chunk_bits + j;
285 chunk |= 1 << j;
286 b[i] = conv32(native, chunk);
287 goto found;
288 }
289 }
290 }
291found:
292 return r;
293}
294
295/**
296 * @}
297 */
298
Note: See TracBrowser for help on using the repository browser.