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

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

Performace optimization:

Use zsearch and isearch to store the index of the first free bit of the bitmap, not of the first block
where the free bit is found.

  • Property mode set to 100644
File size: 3.1 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, BLOCK_FLAGS_NONE);
97
98 if (r != EOK)
99 goto out;
100
101 freebit = find_free_bit_and_set(b->data, sbi->block_size,
102 sbi->native, *search);
103 if (freebit == -1) {
104 /*No free bit in this block*/
105 block_put(b);
106 continue;
107 }
108
109 /*Free bit found, compute real index*/
110 *idx = (freebit + sbi->block_size * 8 * i);
111 if (*idx > limit) {
112 /*Index is beyond the limit, it is invalid*/
113 block_put(b);
114 break;
115 }
116
117 *search = i * bits_per_block + *idx;
118 b->dirty = true;
119 block_put(b);
120 goto found;
121 }
122
123 if (*search > 0) {
124 /*Repeat the search from the first bitmap block*/
125 *search = 0;
126 goto retry;
127 }
128
129 /*Free bit not found, return error*/
130 return ENOSPC;
131
132found:
133 r = EOK;
134
135out:
136 return r;
137}
138
139static int
140find_free_bit_and_set(bitchunk_t *b, const int bsize,
141 const bool native, unsigned start_bit)
142{
143 int r = -1;
144 unsigned i, j;
145 bitchunk_t chunk;
146
147 for (i = start_bit; i < bsize / sizeof(uint32_t); ++i) {
148 if (~b[i]) {
149 /*No free bit in this chunk*/
150 continue;
151 }
152
153 chunk = conv32(native, b[i]);
154
155 for (j = 0; j < 32; ++j) {
156 if (chunk & (1 << j)) {
157 r = i * 32 + j;
158 chunk |= 1 << j;
159 b[i] = conv32(native, chunk);
160 goto found;
161 }
162 }
163 }
164found:
165 return r;
166}
167
Note: See TracBrowser for help on using the repository browser.