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