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

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

Fix bug in the bitmap code path

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