kernel: restore setting KTS_NONE
[minix.git] / servers / ext2 / ialloc.c
blob187733e10b3533a71f5491487942932adfee020d
1 /* This files manages inodes allocation and deallocation.
3 * The entry points into this file are:
4 * alloc_inode: allocate a new, unused inode.
5 * free_inode: mark an inode as available for a new file.
7 * Created (alloc_inode/free_inode/wipe_inode are from MFS):
8 * June 2010 (Evgeniy Ivanov)
9 */
11 #include "fs.h"
12 #include <string.h>
13 #include <stdlib.h>
14 #include <minix/com.h>
15 #include <minix/u64.h>
16 #include "buf.h"
17 #include "inode.h"
18 #include "super.h"
19 #include "const.h"
22 static bit_t alloc_inode_bit(struct super_block *sp, struct inode
23 *parent, int is_dir);
24 static void free_inode_bit(struct super_block *sp, bit_t bit_returned,
25 int is_dir);
26 static void wipe_inode(struct inode *rip);
29 /*===========================================================================*
30 * alloc_inode *
31 *===========================================================================*/
32 struct inode *alloc_inode(struct inode *parent, mode_t bits)
34 /* Allocate a free inode on parent's dev, and return a pointer to it. */
36 register struct inode *rip;
37 register struct super_block *sp;
38 int inumb;
39 bit_t b;
40 static int print_oos_msg = 1;
42 sp = get_super(parent->i_dev); /* get pointer to super_block */
43 if (sp->s_rd_only) { /* can't allocate an inode on a read only device. */
44 err_code = EROFS;
45 return(NULL);
48 /* Acquire an inode from the bit map. */
49 b = alloc_inode_bit(sp, parent, (bits & I_TYPE) == I_DIRECTORY);
50 if (b == NO_BIT) {
51 err_code = ENOSPC;
52 if (print_oos_msg)
53 ext2_debug("Out of i-nodes on device %d/%d\n",
54 major(sp->s_dev), minor(sp->s_dev));
55 print_oos_msg = 0; /* Don't repeat message */
56 return(NULL);
58 print_oos_msg = 1;
60 inumb = (int) b; /* be careful not to pass unshort as param */
62 /* Try to acquire a slot in the inode table. */
63 if ((rip = get_inode(NO_DEV, inumb)) == NULL) {
64 /* No inode table slots available. Free the inode just allocated. */
65 free_inode_bit(sp, b, (bits & I_TYPE) == I_DIRECTORY);
66 } else {
67 /* An inode slot is available. Put the inode just allocated into it. */
68 rip->i_mode = bits; /* set up RWX bits */
69 rip->i_links_count = NO_LINK; /* initial no links */
70 rip->i_uid = caller_uid; /* file's uid is owner's */
71 rip->i_gid = caller_gid; /* ditto group id */
72 rip->i_dev = parent->i_dev; /* mark which device it is on */
73 rip->i_sp = sp; /* pointer to super block */
75 /* Fields not cleared already are cleared in wipe_inode(). They have
76 * been put there because truncate() needs to clear the same fields if
77 * the file happens to be open while being truncated. It saves space
78 * not to repeat the code twice.
80 wipe_inode(rip);
83 return(rip);
87 /*===========================================================================*
88 * free_inode *
89 *===========================================================================*/
90 void free_inode(
91 register struct inode *rip /* inode to free */
94 /* Return an inode to the pool of unallocated inodes. */
95 register struct super_block *sp;
96 dev_t dev = rip->i_dev;
97 bit_t b = rip->i_num;
98 u16_t mode = rip->i_mode;
100 /* Locate the appropriate super_block. */
101 sp = get_super(dev);
103 if (b <= NO_ENTRY || b > sp->s_inodes_count)
104 return;
105 free_inode_bit(sp, b, (mode & I_TYPE) == I_DIRECTORY);
107 rip->i_mode = I_NOT_ALLOC; /* clear I_TYPE field */
111 static int find_group_dir(struct super_block *sp);
112 static int find_group_hashalloc(struct super_block *sp, struct inode
113 *parent);
114 static int find_group_any(struct super_block *sp);
115 static int find_group_orlov(struct super_block *sp, struct inode
116 *parent);
119 /*===========================================================================*
120 * alloc_inode_bit *
121 *===========================================================================*/
122 static bit_t alloc_inode_bit(sp, parent, is_dir)
123 struct super_block *sp; /* the filesystem to allocate from */
124 struct inode *parent; /* parent of newly allocated inode */
125 int is_dir; /* inode will be a directory if it is TRUE */
127 int group;
128 ino_t inumber = NO_BIT;
129 bit_t bit;
130 struct buf *bp;
131 struct group_desc *gd;
133 if (sp->s_rd_only)
134 panic("can't alloc inode on read-only filesys.");
136 if (opt.mfsalloc) {
137 group = find_group_any(sp);
138 } else {
139 if (is_dir) {
140 if (opt.use_orlov) {
141 group = find_group_orlov(sp, parent);
142 } else {
143 group = find_group_dir(sp);
145 } else {
146 group = find_group_hashalloc(sp, parent);
149 /* Check if we have a group where to allocate an inode */
150 if (group == -1)
151 return(NO_BIT); /* no bit could be allocated */
153 gd = get_group_desc(group);
154 if (gd == NULL)
155 panic("can't get group_desc to alloc block");
157 /* find_group_* should always return either a group with
158 * a free inode slot or -1, which we checked earlier.
160 ASSERT(gd->free_inodes_count);
162 bp = get_block(sp->s_dev, gd->inode_bitmap, NORMAL);
163 bit = setbit(b_bitmap(bp), sp->s_inodes_per_group, 0);
164 ASSERT(bit != -1); /* group definitly contains free inode */
166 inumber = group * sp->s_inodes_per_group + bit + 1;
168 /* Extra checks before real allocation.
169 * Only major bug can cause problems. Since setbit changed
170 * bp->b_bitmap there is no way to recover from this bug.
171 * Should never happen.
173 if (inumber > sp->s_inodes_count) {
174 panic("ext2: allocator returned inum greater, than\
175 total number of inodes.\n");
178 if (inumber < EXT2_FIRST_INO(sp)) {
179 panic("ext2: allocator tryed to use reserved inode.\n");
182 lmfs_markdirty(bp);
183 put_block(bp, MAP_BLOCK);
185 gd->free_inodes_count--;
186 sp->s_free_inodes_count--;
187 if (is_dir) {
188 gd->used_dirs_count++;
189 sp->s_dirs_counter++;
192 group_descriptors_dirty = 1;
194 /* Almost the same as previous 'group' ASSERT */
195 ASSERT(inumber != NO_BIT);
196 return inumber;
200 /*===========================================================================*
201 * free_inode_bit *
202 *===========================================================================*/
203 static void free_inode_bit(struct super_block *sp, bit_t bit_returned,
204 int is_dir)
206 /* Return an inode by turning off its bitmap bit. */
207 int group; /* group number of bit_returned */
208 int bit; /* bit_returned number within its group */
209 struct buf *bp;
210 struct group_desc *gd;
212 if (sp->s_rd_only)
213 panic("can't free bit on read-only filesys.");
215 /* At first search group, to which bit_returned belongs to
216 * and figure out in what word bit is stored.
218 if (bit_returned > sp->s_inodes_count ||
219 bit_returned < EXT2_FIRST_INO(sp))
220 panic("trying to free inode %d beyond inodes scope.", bit_returned);
222 group = (bit_returned - 1) / sp->s_inodes_per_group;
223 bit = (bit_returned - 1) % sp->s_inodes_per_group; /* index in bitmap */
225 gd = get_group_desc(group);
226 if (gd == NULL)
227 panic("can't get group_desc to alloc block");
229 bp = get_block(sp->s_dev, gd->inode_bitmap, NORMAL);
231 if (unsetbit(b_bitmap(bp), bit))
232 panic("Tried to free unused inode", bit_returned);
234 lmfs_markdirty(bp);
235 put_block(bp, MAP_BLOCK);
237 gd->free_inodes_count++;
238 sp->s_free_inodes_count++;
240 if (is_dir) {
241 gd->used_dirs_count--;
242 sp->s_dirs_counter--;
245 group_descriptors_dirty = 1;
247 if (group < sp->s_igsearch)
248 sp->s_igsearch = group;
252 /* it's implemented very close to the linux' find_group_dir() */
253 static int find_group_dir(struct super_block *sp)
255 int avefreei = sp->s_free_inodes_count / sp->s_groups_count;
256 struct group_desc *gd, *best_gd = NULL;
257 int group, best_group = -1;
259 for (group = 0; group < sp->s_groups_count; ++group) {
260 gd = get_group_desc(group);
261 if (gd == NULL)
262 panic("can't get group_desc to alloc inode");
263 if (gd->free_inodes_count == 0)
264 continue;
265 if (gd->free_inodes_count < avefreei)
266 continue;
267 if (!best_gd ||
268 gd->free_blocks_count > best_gd->free_blocks_count) {
269 best_gd = gd;
270 best_group = group;
274 return best_group; /* group or -1 */
278 /* Analog of ffs_hashalloc() from *BSD.
279 * 1) Check parent's for free inodes and blocks.
280 * 2) Quadradically rehash on the group number.
281 * 3) Make a linear search for free inode.
283 static int find_group_hashalloc(struct super_block *sp, struct inode *parent)
285 int ngroups = sp->s_groups_count;
286 struct group_desc *gd;
287 int group, i;
288 int parent_group = (parent->i_num - 1) / sp->s_inodes_per_group;
290 /* Try to place new inode in its parent group */
291 gd = get_group_desc(parent_group);
292 if (gd == NULL)
293 panic("can't get group_desc to alloc inode");
294 if (gd->free_inodes_count && gd->free_blocks_count)
295 return parent_group;
297 /* We can't allocate inode in the parent's group.
298 * Now we will try to place it in another blockgroup.
299 * The main idea is still to keep files from the same
300 * directory together and use different blockgroups for
301 * files from another directory, which lives in the same
302 * blockgroup as our parent.
303 * Thus we will spread things on the disk.
305 group = (parent_group + parent->i_num) % ngroups;
307 /* Make quadratic probing to find a group with free inodes and blocks. */
308 for (i = 1; i < ngroups; i <<= 1) {
309 group += i;
310 if (group >= ngroups)
311 group -= ngroups;
312 gd = get_group_desc(group);
313 if (gd == NULL)
314 panic("can't get group_desc to alloc inode");
315 if (gd->free_inodes_count && gd->free_blocks_count)
316 return group;
319 /* Still no group for new inode, try linear search.
320 * Also check parent again (but for free inodes only).
322 group = parent_group;
323 for (i = 0; i < ngroups; i++, group++) {
324 if (group >= ngroups)
325 group = 0;
326 gd = get_group_desc(group);
327 if (gd == NULL)
328 panic("can't get group_desc to alloc inode");
329 if (gd->free_inodes_count)
330 return group;
333 return -1;
337 /* Find first group which has free inode slot.
338 * This is similar to what MFS does.
340 static int find_group_any(struct super_block *sp)
342 int ngroups = sp->s_groups_count;
343 struct group_desc *gd;
344 int group = sp->s_igsearch;
346 for (; group < ngroups; group++) {
347 gd = get_group_desc(group);
348 if (gd == NULL)
349 panic("can't get group_desc to alloc inode");
350 if (gd->free_inodes_count) {
351 sp->s_igsearch = group;
352 return group;
356 return -1;
360 /* We try to spread first-level directories (i.e. directories in the root
361 * or in the directory marked as TOPDIR).
362 * If there are blockgroups with counts for blocks and inodes less than average
363 * we return a group with lowest directory count. Otherwise we either
364 * return a group with good free inodes and blocks counts or just a group
365 * with free inode.
367 * For other directories we try to find a 'good' group, we consider a group as
368 * a 'good' if it has enough blocks and inodes (greater than min_blocks and
369 * min_inodes).
372 static int find_group_orlov(struct super_block *sp, struct inode *parent)
374 int avefreei = sp->s_free_inodes_count / sp->s_groups_count;
375 int avefreeb = sp->s_free_blocks_count / sp->s_groups_count;
377 int group = -1;
378 int fallback_group = -1; /* Group with at least 1 free inode */
379 struct group_desc *gd;
380 int i;
382 if (parent->i_num == ROOT_INODE ||
383 parent->i_flags & EXT2_TOPDIR_FL) {
384 int best_group = -1;
385 int best_avefree_group = -1; /* Best value of avefreei/avefreeb */
386 int best_ndir = sp->s_inodes_per_group;
388 group = (unsigned int)random();
389 for (i = 0; i < sp->s_groups_count; i++, group++) {
390 if (group >= sp->s_groups_count)
391 group = 0;
392 gd = get_group_desc(group);
393 if (gd == NULL)
394 panic("can't get group_desc to alloc inode");
395 if (gd->free_inodes_count == 0)
396 continue;
398 fallback_group = group;
400 if (gd->free_inodes_count < avefreei ||
401 gd->free_blocks_count < avefreeb)
402 continue;
404 best_avefree_group = group;
406 if (gd->used_dirs_count >= best_ndir)
407 continue;
408 best_ndir = gd->used_dirs_count;
409 best_group = group;
411 if (best_group >= 0)
412 return best_group;
413 if (best_avefree_group >= 0)
414 return best_avefree_group;
415 return fallback_group;
416 } else {
417 int parent_group = (parent->i_num - 1) / sp->s_inodes_per_group;
418 /* 2 is kind of random thing for now,
419 * but performance results are still good.
421 int min_blocks = avefreeb / 2;
422 int min_inodes = avefreei / 2;
424 group = parent_group;
425 for (i = 0; i < sp->s_groups_count; i++, group++) {
426 if (group >= sp->s_groups_count)
427 group = 0;
428 gd = get_group_desc(group);
429 if (gd == NULL)
430 panic("can't get group_desc to alloc inode");
431 if (gd->free_inodes_count == 0)
432 continue;
434 fallback_group = group;
436 if (gd->free_inodes_count >= min_inodes &&
437 gd->free_blocks_count >= min_blocks)
438 return group;
440 return fallback_group;
443 return -1;
447 /*===========================================================================*
448 * wipe_inode *
449 *===========================================================================*/
450 static void wipe_inode(
451 register struct inode *rip /* the inode to be erased */
454 /* Erase some fields in the inode. This function is called from alloc_inode()
455 * when a new inode is to be allocated, and from truncate(), when an existing
456 * inode is to be truncated.
459 register int i;
461 rip->i_size = 0;
462 rip->i_update = ATIME | CTIME | MTIME; /* update all times later */
463 rip->i_blocks = 0;
464 rip->i_flags = 0;
465 rip->i_generation = 0;
466 rip->i_file_acl = 0;
467 rip->i_dir_acl = 0;
468 rip->i_faddr = 0;
470 for (i = 0; i < EXT2_N_BLOCKS; i++)
471 rip->i_block[i] = NO_BLOCK;
472 rip->i_block[0] = NO_BLOCK;
474 rip->i_dirt = IN_DIRTY;