VM: make mapping types explicit
[minix.git] / servers / ext2 / balloc.c
blob1a93f54076b5f6440f5ee0fdecb66fb6fca17206
1 /* This files manages blocks allocation and deallocation.
3 * The entry points into this file are:
4 * discard_preallocated_blocks: Discard preallocated blocks.
5 * alloc_block: somebody wants to allocate a block; find one.
6 * free_block: indicate that a block is available for new allocation.
8 * Created:
9 * June 2010 (Evgeniy Ivanov)
12 #include "fs.h"
13 #include <string.h>
14 #include <stdlib.h>
15 #include <minix/com.h>
16 #include <minix/u64.h>
17 #include "buf.h"
18 #include "inode.h"
19 #include "super.h"
20 #include "const.h"
23 static block_t alloc_block_bit(struct super_block *sp, block_t origin,
24 struct inode *rip);
26 /*===========================================================================*
27 * discard_preallocated_blocks *
28 *===========================================================================*/
29 void discard_preallocated_blocks(struct inode *rip)
31 /* When called for rip, discard (free) blocks preallocated for rip,
32 * otherwise discard all preallocated blocks.
33 * Normally it should be called in following situations:
34 * 1. File is closed.
35 * 2. File is truncated.
36 * 3. Non-sequential write.
37 * 4. inode is "unloaded" from the memory.
38 * 5. No free blocks left (discard all preallocated blocks).
40 int i;
42 if (rip) {
43 rip->i_prealloc_count = rip->i_prealloc_index = 0;
44 for (i = 0; i < EXT2_PREALLOC_BLOCKS; i++) {
45 if (rip->i_prealloc_blocks[i] != NO_BLOCK) {
46 free_block(rip->i_sp, rip->i_prealloc_blocks[i]);
47 rip->i_prealloc_blocks[i] = NO_BLOCK;
50 return;
53 /* Discard all allocated blocks.
54 * Probably there are just few blocks on the disc, so forbid preallocation.*/
55 for(rip = &inode[0]; rip < &inode[NR_INODES]; rip++) {
56 rip->i_prealloc_count = rip->i_prealloc_index = 0;
57 rip->i_preallocation = 0; /* forbid preallocation */
58 for (i = 0; i < EXT2_PREALLOC_BLOCKS; i++) {
59 if (rip->i_prealloc_blocks[i] != NO_BLOCK) {
60 free_block(rip->i_sp, rip->i_prealloc_blocks[i]);
61 rip->i_prealloc_blocks[i] = NO_BLOCK;
68 /*===========================================================================*
69 * alloc_block *
70 *===========================================================================*/
71 block_t alloc_block(struct inode *rip, block_t block)
73 /* Allocate a block for inode. If block is provided, then use it as a goal:
74 * try to allocate this block or his neghbors.
75 * If block is not provided then goal is group, where inode lives.
77 block_t goal;
78 block_t b;
79 struct super_block *sp = rip->i_sp;
81 if (sp->s_rd_only)
82 panic("can't alloc block on read-only filesys.");
84 /* Check for free blocks. First time discard preallocation,
85 * next time return NO_BLOCK
87 if (!opt.use_reserved_blocks &&
88 sp->s_free_blocks_count <= sp->s_r_blocks_count) {
89 discard_preallocated_blocks(NULL);
90 } else if (sp->s_free_blocks_count <= EXT2_PREALLOC_BLOCKS) {
91 discard_preallocated_blocks(NULL);
94 if (!opt.use_reserved_blocks &&
95 sp->s_free_blocks_count <= sp->s_r_blocks_count) {
96 return(NO_BLOCK);
97 } else if (sp->s_free_blocks_count == 0) {
98 return(NO_BLOCK);
101 if (block != NO_BLOCK) {
102 goal = block;
103 if (rip->i_preallocation && rip->i_prealloc_count > 0) {
104 /* check if goal is preallocated */
105 b = rip->i_prealloc_blocks[rip->i_prealloc_index];
106 if (block == b || (block + 1) == b) {
107 /* use preallocated block */
108 rip->i_prealloc_blocks[rip->i_prealloc_index] = NO_BLOCK;
109 rip->i_prealloc_count--;
110 rip->i_prealloc_index++;
111 if (rip->i_prealloc_index >= EXT2_PREALLOC_BLOCKS) {
112 rip->i_prealloc_index = 0;
113 ASSERT(rip->i_prealloc_count == 0);
115 rip->i_bsearch = b;
116 return b;
117 } else {
118 /* probably non-sequential write operation,
119 * disable preallocation for this inode.
121 rip->i_preallocation = 0;
122 discard_preallocated_blocks(rip);
125 } else {
126 int group = (rip->i_num - 1) / sp->s_inodes_per_group;
127 goal = sp->s_blocks_per_group*group + sp->s_first_data_block;
130 if (rip->i_preallocation && rip->i_prealloc_count) {
131 ext2_debug("There're preallocated blocks, but they're\
132 neither used or freed!");
135 b = alloc_block_bit(sp, goal, rip);
137 if (b != NO_BLOCK)
138 rip->i_bsearch = b;
140 return b;
144 static void check_block_number(block_t block, struct super_block *sp,
145 struct group_desc *gd);
147 /*===========================================================================*
148 * alloc_block_bit *
149 *===========================================================================*/
150 static block_t alloc_block_bit(sp, goal, rip)
151 struct super_block *sp; /* the filesystem to allocate from */
152 block_t goal; /* try to allocate near this block */
153 struct inode *rip; /* used for preallocation */
155 block_t block = NO_BLOCK; /* allocated block */
156 int word; /* word in block bitmap */
157 bit_t bit = -1;
158 int group;
159 char update_bsearch = FALSE;
160 int i;
162 if (goal >= sp->s_blocks_count ||
163 (goal < sp->s_first_data_block && goal != 0)) {
164 goal = sp->s_bsearch;
167 if (goal <= sp->s_bsearch) {
168 /* No reason to search in a place with no free blocks */
169 goal = sp->s_bsearch;
170 update_bsearch = TRUE;
173 /* Figure out where to start the bit search. */
174 word = ((goal - sp->s_first_data_block) % sp->s_blocks_per_group)
175 / FS_BITCHUNK_BITS;
177 /* Try to allocate block at any group starting from the goal's group.
178 * First time goal's group is checked from the word=goal, after all
179 * groups checked, it's checked again from word=0, that's why "i <=".
181 group = (goal - sp->s_first_data_block) / sp->s_blocks_per_group;
182 for (i = 0; i <= sp->s_groups_count; i++, group++) {
183 struct buf *bp;
184 struct group_desc *gd;
186 if (group >= sp->s_groups_count)
187 group = 0;
189 gd = get_group_desc(group);
190 if (gd == NULL)
191 panic("can't get group_desc to alloc block");
193 if (gd->free_blocks_count == 0) {
194 word = 0;
195 continue;
198 bp = get_block(sp->s_dev, gd->block_bitmap, NORMAL);
200 if (rip->i_preallocation &&
201 gd->free_blocks_count >= (EXT2_PREALLOC_BLOCKS * 4) ) {
202 /* Try to preallocate blocks */
203 if (rip->i_prealloc_count != 0) {
204 /* kind of glitch... */
205 discard_preallocated_blocks(rip);
206 ext2_debug("warning, discarding previously preallocated\
207 blocks! It had to be done by another code.");
209 ASSERT(rip->i_prealloc_count == 0);
210 /* we preallocate bytes only */
211 ASSERT(EXT2_PREALLOC_BLOCKS == sizeof(char)*CHAR_BIT);
213 bit = setbyte(bp->b_bitmap, sp->s_blocks_per_group);
214 if (bit != -1) {
215 block = bit + sp->s_first_data_block +
216 group * sp->s_blocks_per_group;
217 check_block_number(block, sp, gd);
219 /* We preallocate a byte starting from block.
220 * First preallocated block will be returned as
221 * normally allocated block.
223 for (i = 1; i < EXT2_PREALLOC_BLOCKS; i++) {
224 check_block_number(block + i, sp, gd);
225 rip->i_prealloc_blocks[i-1] = block + i;
227 rip->i_prealloc_index = 0;
228 rip->i_prealloc_count = EXT2_PREALLOC_BLOCKS - 1;
230 bp->b_dirt = DIRTY; /* by setbyte */
231 put_block(bp, MAP_BLOCK);
233 gd->free_blocks_count -= EXT2_PREALLOC_BLOCKS;
234 sp->s_free_blocks_count -= EXT2_PREALLOC_BLOCKS;
235 group_descriptors_dirty = DIRTY;
236 return block;
240 bit = setbit(bp->b_bitmap, sp->s_blocks_per_group, word);
241 if (bit == -1) {
242 if (word == 0) {
243 panic("ext2: allocator failed to allocate a bit in bitmap\
244 with free bits.");
245 } else {
246 word = 0;
247 continue;
251 block = sp->s_first_data_block + group * sp->s_blocks_per_group + bit;
252 check_block_number(block, sp, gd);
254 bp->b_dirt = DIRTY; /* Now it's safe to mark it as dirty */
255 put_block(bp, MAP_BLOCK);
257 gd->free_blocks_count--;
258 sp->s_free_blocks_count--;
259 group_descriptors_dirty = DIRTY;
261 if (update_bsearch && block != -1 && block != NO_BLOCK) {
262 /* We searched from the beginning, update bsearch. */
263 sp->s_bsearch = block;
266 return block;
269 return block;
273 /*===========================================================================*
274 * free_block *
275 *===========================================================================*/
276 void free_block(struct super_block *sp, bit_t bit_returned)
278 /* Return a block by turning off its bitmap bit. */
279 int group; /* group number of bit_returned */
280 int bit; /* bit_returned number within its group */
281 struct buf *bp;
282 struct group_desc *gd;
284 if (sp->s_rd_only)
285 panic("can't free bit on read-only filesys.");
287 if (bit_returned >= sp->s_blocks_count ||
288 bit_returned < sp->s_first_data_block)
289 panic("trying to free block %d beyond blocks scope.",
290 bit_returned);
292 /* At first search group, to which bit_returned belongs to
293 * and figure out in what word bit is stored.
295 group = (bit_returned - sp->s_first_data_block) / sp->s_blocks_per_group;
296 bit = (bit_returned - sp->s_first_data_block) % sp->s_blocks_per_group;
298 gd = get_group_desc(group);
299 if (gd == NULL)
300 panic("can't get group_desc to alloc block");
302 /* We might be buggy (No way! :P), so check if we deallocate
303 * data block, but not control (system) block.
304 * This should never happen.
306 if (bit_returned == gd->inode_bitmap || bit_returned == gd->block_bitmap
307 || (bit_returned >= gd->inode_table
308 && bit_returned < (gd->inode_table + sp->s_itb_per_group))) {
309 ext2_debug("ext2: freeing non-data block %d\n", bit_returned);
310 panic("trying to deallocate \
311 system/control block, hardly poke author.");
314 bp = get_block(sp->s_dev, gd->block_bitmap, NORMAL);
316 if (unsetbit(bp->b_bitmap, bit))
317 panic("Tried to free unused block", bit_returned);
319 bp->b_dirt = DIRTY;
320 put_block(bp, MAP_BLOCK);
322 gd->free_blocks_count++;
323 sp->s_free_blocks_count++;
325 group_descriptors_dirty = DIRTY;
327 if (bit_returned < sp->s_bsearch)
328 sp->s_bsearch = bit_returned;
332 static void check_block_number(block_t block, struct super_block *sp,
333 struct group_desc *gd)
336 /* Check if we allocated a data block, but not control (system) block.
337 * Only major bug can cause us to allocate wrong block. If it happens,
338 * we panic (and don't bloat filesystem's bitmap).
340 if (block == gd->inode_bitmap || block == gd->block_bitmap ||
341 (block >= gd->inode_table
342 && block < (gd->inode_table + sp->s_itb_per_group))) {
343 ext2_debug("ext2: allocating non-data block %d\n", block);
344 panic("ext2: block allocator tryed to return \
345 system/control block, poke author.\n");
348 if (block >= sp->s_blocks_count) {
349 panic("ext2: allocator returned blocknum greater, than \
350 total number of blocks.\n");