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

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

Fix bug in alloc_bit() function, wrong parameter passed to block_get()

  • Property mode set to 100644
File size: 3.2 KB
Line 
1#include <stdlib.h>
2#include <assert.h>
3#include <errno.h>
4#include "mfs.h"
5#include "mfs_utils.h"
6
7static int
8find_free_bit_and_set(bitchunk_t *b, const int bsize,
9 const bool native, unsigned start_bit);
10
11int
12mfs_free_bit(struct mfs_instance *inst, uint32_t idx, bmap_id_t bid)
13{
14 struct mfs_sb_info *sbi;
15 int r;
16 unsigned start_block;
17 block_t *b;
18
19 assert(inst != NULL);
20 sbi = inst->sbi;
21 assert(sbi != NULL);
22
23 if (bid == BMAP_ZONE) {
24 start_block = 2 + sbi->ibmap_blocks;
25 if (idx > sbi->nzones) {
26 printf(NAME ": Error! Trying to free beyond the" \
27 "bitmap max size\n");
28 return -1;
29 }
30 } else {
31 /*bid == BMAP_INODE*/
32 start_block = 2;
33 if (idx > sbi->ninodes) {
34 printf(NAME ": Error! Trying to free beyond the" \
35 "bitmap max size\n");
36 return -1;
37 }
38 }
39
40 /*Compute the bitmap block*/
41 uint32_t block = idx / (sbi->block_size * 8) + start_block;
42
43 r = block_get(&b, inst->handle, block, BLOCK_FLAGS_NONE);
44 if (r != EOK)
45 goto out_err;
46
47 /*Compute the bit index in the block*/
48 idx %= (sbi->block_size * 8);
49 bitchunk_t *ptr = b->data;
50 bitchunk_t chunk;
51
52 chunk = conv32(sbi->native, ptr[idx / 32]);
53 chunk &= ~(1 << (idx % 32));
54 ptr[idx / 32] = conv32(sbi->native, chunk);
55 b->dirty = true;
56 r = EOK;
57 block_put(b);
58
59out_err:
60 return r;
61}
62
63int
64mfs_alloc_bit(struct mfs_instance *inst, uint32_t *idx, bmap_id_t bid)
65{
66 struct mfs_sb_info *sbi;
67 uint32_t limit;
68 unsigned long nblocks;
69 unsigned *search, i, start_block;
70 unsigned bits_per_block;
71 int r, freebit;
72
73 assert(inst != NULL);
74 sbi = inst->sbi;
75 assert(sbi != NULL);
76
77 if (bid == BMAP_ZONE) {
78 search = &sbi->zsearch;
79 start_block = 2 + sbi->ibmap_blocks;
80 nblocks = sbi->zbmap_blocks;
81 limit = sbi->nzones;
82 } else {
83 /*bid == BMAP_INODE*/
84 search = &sbi->isearch;
85 start_block = 2;
86 nblocks = sbi->ibmap_blocks;
87 limit = sbi->ninodes;
88 }
89 bits_per_block = sbi->block_size * 8;
90
91 block_t *b;
92
93retry:
94
95 for (i = *search / bits_per_block; i < nblocks; ++i) {
96 r = block_get(&b, inst->handle, i + start_block,
97 BLOCK_FLAGS_NONE);
98
99 if (r != EOK)
100 goto out;
101
102 freebit = find_free_bit_and_set(b->data, sbi->block_size,
103 sbi->native, *search);
104 if (freebit == -1) {
105 /*No free bit in this block*/
106 block_put(b);
107 continue;
108 }
109
110 /*Free bit found, compute real index*/
111 *idx = (freebit + sbi->block_size * 8 * i);
112 if (*idx > limit) {
113 /*Index is beyond the limit, it is invalid*/
114 block_put(b);
115 break;
116 }
117
118 *search = i * bits_per_block + *idx;
119 b->dirty = true;
120 block_put(b);
121 goto found;
122 }
123
124 if (*search > 0) {
125 /*Repeat the search from the first bitmap block*/
126 *search = 0;
127 goto retry;
128 }
129
130 /*Free bit not found, return error*/
131 return ENOSPC;
132
133found:
134 r = EOK;
135
136out:
137 return r;
138}
139
140static int
141find_free_bit_and_set(bitchunk_t *b, const int bsize,
142 const bool native, unsigned start_bit)
143{
144 int r = -1;
145 unsigned i, j;
146 bitchunk_t chunk;
147
148 for (i = start_bit; i < bsize / sizeof(uint32_t); ++i) {
149 if (~b[i]) {
150 /*No free bit in this chunk*/
151 continue;
152 }
153
154 chunk = conv32(native, b[i]);
155
156 for (j = 0; j < 32; ++j) {
157 if (chunk & (1 << j)) {
158 r = i * 32 + j;
159 chunk |= 1 << j;
160 b[i] = conv32(native, chunk);
161 goto found;
162 }
163 }
164 }
165found:
166 return r;
167}
168
Note: See TracBrowser for help on using the repository browser.