source: mainline/uspace/srv/fs/minixfs/mfs_balloc.c@ e80c2ff

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

add wrapper functions to mfs_alloc_bit and mfs_free_bit to improve the code readability

  • Property mode set to 100644
File size: 5.6 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#include "mfs_utils.h"
36
37static int
38find_free_bit_and_set(bitchunk_t *b, const int bsize,
39 const bool native, unsigned start_bit);
40
41static int
42mfs_free_bit(struct mfs_instance *inst, uint32_t idx, bmap_id_t bid);
43
44static int
45mfs_alloc_bit(struct mfs_instance *inst, uint32_t *idx, bmap_id_t bid);
46
47
48int
49mfs_alloc_inode(struct mfs_instance *inst, uint32_t *inum)
50{
51 return mfs_alloc_bit(inst, inum, BMAP_INODE);
52}
53
54int
55mfs_free_inode(struct mfs_instance *inst, uint32_t inum)
56{
57 return mfs_free_bit(inst, inum, BMAP_INODE);
58}
59
60int
61mfs_alloc_zone(struct mfs_instance *inst, uint32_t *zone)
62{
63 int r = mfs_alloc_bit(inst, zone, BMAP_ZONE);
64
65 *zone += inst->sbi->firstdatazone;
66 return r;
67}
68
69int
70mfs_free_zone(struct mfs_instance *inst, uint32_t zone)
71{
72 zone -= inst->sbi->firstdatazone;
73
74 return mfs_free_bit(inst, zone, BMAP_ZONE);
75}
76
77static int
78mfs_free_bit(struct mfs_instance *inst, uint32_t idx, bmap_id_t bid)
79{
80 struct mfs_sb_info *sbi;
81 int r;
82 unsigned start_block;
83 block_t *b;
84
85 assert(inst != NULL);
86 sbi = inst->sbi;
87 assert(sbi != NULL);
88
89 if (bid == BMAP_ZONE) {
90 start_block = 2 + sbi->ibmap_blocks;
91 if (idx > sbi->nzones) {
92 printf(NAME ": Error! Trying to free beyond the" \
93 "bitmap max size\n");
94 return -1;
95 }
96 } else {
97 /*bid == BMAP_INODE*/
98 start_block = 2;
99 if (idx > sbi->ninodes) {
100 printf(NAME ": Error! Trying to free beyond the" \
101 "bitmap max size\n");
102 return -1;
103 }
104 }
105
106 /*Compute the bitmap block*/
107 uint32_t block = idx / (sbi->block_size * 8) + start_block;
108
109 r = block_get(&b, inst->handle, block, BLOCK_FLAGS_NONE);
110 on_error(r, goto out_err);
111
112 /*Compute the bit index in the block*/
113 idx %= (sbi->block_size * 8);
114 bitchunk_t *ptr = b->data;
115 bitchunk_t chunk;
116 const size_t chunk_bits = sizeof(bitchunk_t) * 8;
117
118 chunk = conv32(sbi->native, ptr[idx / chunk_bits]);
119 chunk &= ~(1 << (idx % chunk_bits));
120 ptr[idx / chunk_bits] = conv32(sbi->native, chunk);
121 b->dirty = true;
122 r = block_put(b);
123 mfsdebug("free index %u\n", idx);
124
125out_err:
126 return r;
127}
128
129static int
130mfs_alloc_bit(struct mfs_instance *inst, uint32_t *idx, bmap_id_t bid)
131{
132 struct mfs_sb_info *sbi;
133 uint32_t limit;
134 unsigned long nblocks;
135 unsigned *search, i, start_block;
136 unsigned bits_per_block;
137 int r, freebit;
138
139 assert(inst != NULL);
140 sbi = inst->sbi;
141 assert(sbi != NULL);
142
143 if (bid == BMAP_ZONE) {
144 search = &sbi->zsearch;
145 start_block = 2 + sbi->ibmap_blocks;
146 nblocks = sbi->zbmap_blocks;
147 limit = sbi->nzones;
148 } else {
149 /*bid == BMAP_INODE*/
150 search = &sbi->isearch;
151 start_block = 2;
152 nblocks = sbi->ibmap_blocks;
153 limit = sbi->ninodes;
154 }
155 bits_per_block = sbi->block_size * 8;
156
157 block_t *b;
158
159retry:
160
161 for (i = *search / bits_per_block; i < nblocks; ++i) {
162 r = block_get(&b, inst->handle, i + start_block,
163 BLOCK_FLAGS_NONE);
164
165 on_error(r, goto out);
166
167 unsigned tmp = *search % bits_per_block;
168
169 freebit = find_free_bit_and_set(b->data, sbi->block_size,
170 sbi->native, tmp);
171 if (freebit == -1) {
172 /*No free bit in this block*/
173 block_put(b);
174 continue;
175 }
176
177 /*Free bit found in this block, compute the real index*/
178 *idx = freebit + bits_per_block * i;
179 *idx += (bid == BMAP_INODE) ? 1 : 0;
180 mfsdebug("alloc index %d %d\n", (int) *idx, i);
181 if (*idx > limit) {
182 /*Index is beyond the limit, it is invalid*/
183 r = block_put(b);
184 on_error(r, goto out);
185 break;
186 }
187
188 *search = *idx;
189 b->dirty = true;
190 r = block_put(b);
191 goto out;
192 }
193
194 if (*search > 0) {
195 /*Repeat the search from the first bitmap block*/
196 *search = 0;
197 goto retry;
198 }
199
200 /*Free bit not found, return error*/
201 return ENOSPC;
202
203out:
204 return r;
205}
206
207static int
208find_free_bit_and_set(bitchunk_t *b, const int bsize,
209 const bool native, unsigned start_bit)
210{
211 int r = -1;
212 unsigned i, j;
213 bitchunk_t chunk;
214 const size_t chunk_bits = sizeof(bitchunk_t) * 8;
215
216 for (i = start_bit / chunk_bits;
217 i < bsize / sizeof(bitchunk_t); ++i) {
218 if (!(~b[i])) {
219 /*No free bit in this chunk*/
220 continue;
221 }
222
223 chunk = conv32(native, b[i]);
224
225 for (j = 0; j < chunk_bits; ++j) {
226 if (!(chunk & (1 << j))) {
227 r = i * chunk_bits + j;
228 chunk |= 1 << j;
229 b[i] = conv32(native, chunk);
230 goto found;
231 }
232 }
233 }
234found:
235 return r;
236}
237
238/**
239 * @}
240 */
241
Note: See TracBrowser for help on using the repository browser.