1 /* This file manages the inode table. There are procedures to allocate and 2 * deallocate inodes, acquire, erase, and release them, and read and write 3 * them from the disk. 4 * 5 * The entry points into this file are 6 * get_inode: search inode table for a given inode; if not there, 7 * read it 8 * put_inode: indicate that an inode is no longer needed in memory 9 * update_times: update atime, ctime, and mtime 10 * rw_inode: read a disk block and extract an inode, or corresp. write 11 * dup_inode: indicate that someone else is using an inode table entry 12 * find_inode: retrieve pointer to inode in inode cache 13 * 14 * Created (MFS based): 15 * February 2010 (Evgeniy Ivanov) 16 */ 17 18 #include "fs.h" 19 #include <string.h> 20 #include "buf.h" 21 #include "inode.h" 22 #include "super.h" 23 #include <minix/vfsif.h> 24 25 static void icopy(struct inode *rip, d_inode *dip, int direction, int 26 norm); 27 static void addhash_inode(struct inode *node); 28 static void unhash_inode(struct inode *node); 29 30 31 /*===========================================================================* 32 * fs_putnode * 33 *===========================================================================*/ 34 int fs_putnode(ino_t ino_nr, unsigned int count) 35 { 36 /* Find the inode specified by the request message and decrease its counter.*/ 37 38 struct inode *rip; 39 40 rip = find_inode(fs_dev, ino_nr); 41 42 if (!rip) { 43 printf("%s:%d put_inode: inode #%llu dev: %llx not found\n", __FILE__, 44 __LINE__, ino_nr, fs_dev); 45 panic("fs_putnode failed"); 46 } 47 48 if (count > rip->i_count) { 49 printf("%s:%d put_inode: count too high: %d > %d\n", __FILE__, 50 __LINE__, count, rip->i_count); 51 panic("fs_putnode failed"); 52 } 53 54 /* Decrease reference counter, but keep one reference; 55 * it will be consumed by put_inode(). 56 */ 57 rip->i_count -= count - 1; 58 put_inode(rip); 59 60 return(OK); 61 } 62 63 64 /*===========================================================================* 65 * init_inode_cache * 66 *===========================================================================*/ 67 void init_inode_cache() 68 { 69 struct inode *rip; 70 struct inodelist *rlp; 71 72 inode_cache_hit = 0; 73 inode_cache_miss = 0; 74 75 /* init free/unused list */ 76 TAILQ_INIT(&unused_inodes); 77 78 /* init hash lists */ 79 for (rlp = &hash_inodes[0]; rlp < &hash_inodes[INODE_HASH_SIZE]; ++rlp) 80 LIST_INIT(rlp); 81 82 /* add free inodes to unused/free list */ 83 for (rip = &inode[0]; rip < &inode[NR_INODES]; ++rip) { 84 rip->i_num = NO_ENTRY; 85 TAILQ_INSERT_HEAD(&unused_inodes, rip, i_unused); 86 } 87 } 88 89 90 /*===========================================================================* 91 * addhash_inode * 92 *===========================================================================*/ 93 static void addhash_inode(struct inode *node) 94 { 95 int hashi = node->i_num & INODE_HASH_MASK; 96 97 /* insert into hash table */ 98 LIST_INSERT_HEAD(&hash_inodes[hashi], node, i_hash); 99 } 100 101 102 /*===========================================================================* 103 * unhash_inode * 104 *===========================================================================*/ 105 static void unhash_inode(struct inode *node) 106 { 107 /* remove from hash table */ 108 LIST_REMOVE(node, i_hash); 109 } 110 111 112 /*===========================================================================* 113 * get_inode * 114 *===========================================================================*/ 115 struct inode *get_inode( 116 dev_t dev, /* device on which inode resides */ 117 ino_t numb /* inode number (ANSI: may not be unshort) */ 118 ) 119 { 120 /* Find the inode in the hash table. If it is not there, get a free inode 121 * load it from the disk if it's necessary and put on the hash list 122 */ 123 register struct inode *rip; 124 int hashi; 125 int i; 126 127 hashi = (int) numb & INODE_HASH_MASK; 128 129 /* Search inode in the hash table */ 130 LIST_FOREACH(rip, &hash_inodes[hashi], i_hash) { 131 if (rip->i_num == numb && rip->i_dev == dev) { 132 /* If unused, remove it from the unused/free list */ 133 if (rip->i_count == 0) { 134 inode_cache_hit++; 135 TAILQ_REMOVE(&unused_inodes, rip, i_unused); 136 } 137 ++rip->i_count; 138 return(rip); 139 } 140 } 141 142 inode_cache_miss++; 143 144 /* Inode is not on the hash, get a free one */ 145 if (TAILQ_EMPTY(&unused_inodes)) { 146 err_code = ENFILE; 147 return(NULL); 148 } 149 rip = TAILQ_FIRST(&unused_inodes); 150 151 /* If not free unhash it */ 152 if (rip->i_num != NO_ENTRY) 153 unhash_inode(rip); 154 155 /* Inode is not unused any more */ 156 TAILQ_REMOVE(&unused_inodes, rip, i_unused); 157 158 /* Load the inode. */ 159 rip->i_dev = dev; 160 rip->i_num = numb; 161 rip->i_count = 1; 162 if (dev != NO_DEV) 163 rw_inode(rip, READING); /* get inode from disk */ 164 rip->i_update = 0; /* all the times are initially up-to-date */ 165 rip->i_last_dpos = 0; /* no dentries searched for yet */ 166 rip->i_bsearch = NO_BLOCK; 167 rip->i_last_pos_bl_alloc = 0; 168 rip->i_last_dentry_size = 0; 169 rip->i_mountpoint= FALSE; 170 171 rip->i_preallocation = opt.use_prealloc; 172 rip->i_prealloc_count = rip->i_prealloc_index = 0; 173 174 for (i = 0; i < EXT2_PREALLOC_BLOCKS; i++) { 175 if (rip->i_prealloc_blocks[i] != NO_BLOCK) { 176 /* Actually this should never happen */ 177 free_block(rip->i_sp, rip->i_prealloc_blocks[i]); 178 rip->i_prealloc_blocks[i] = NO_BLOCK; 179 ext2_debug("Warning: Unexpected preallocated block."); 180 } 181 } 182 183 /* Add to hash */ 184 addhash_inode(rip); 185 186 return(rip); 187 } 188 189 190 /*===========================================================================* 191 * find_inode * 192 *===========================================================================*/ 193 struct inode *find_inode( 194 dev_t dev, /* device on which inode resides */ 195 ino_t numb /* inode number (ANSI: may not be unshort) */ 196 ) 197 { 198 /* Find the inode specified by the inode and device number. */ 199 struct inode *rip; 200 int hashi; 201 202 hashi = (int) numb & INODE_HASH_MASK; 203 204 /* Search inode in the hash table */ 205 LIST_FOREACH(rip, &hash_inodes[hashi], i_hash) { 206 if (rip->i_count > 0 && rip->i_num == numb && rip->i_dev == dev) { 207 return(rip); 208 } 209 } 210 211 return(NULL); 212 } 213 214 215 /*===========================================================================* 216 * put_inode * 217 *===========================================================================*/ 218 void put_inode( 219 register struct inode *rip /* pointer to inode to be released */ 220 ) 221 { 222 /* The caller is no longer using this inode. If no one else is using it either 223 * write it back to the disk immediately. If it has no links, truncate it and 224 * return it to the pool of available inodes. 225 */ 226 227 if (rip == NULL) 228 return; /* checking here is easier than in caller */ 229 230 if (rip->i_count < 1) 231 panic("put_inode: i_count already below 1: %d", rip->i_count); 232 233 if (--rip->i_count == 0) { /* i_count == 0 means no one is using it now */ 234 if (rip->i_links_count == NO_LINK) { 235 /* i_nlinks == NO_LINK means free the inode. */ 236 /* return all the disk blocks */ 237 238 /* Ignore errors by truncate_inode in case inode is a block 239 * special or character special file. 240 */ 241 (void) truncate_inode(rip, (off_t) 0); 242 /* free inode clears I_TYPE field, since it's used there */ 243 rip->i_dirt = IN_DIRTY; 244 free_inode(rip); 245 } 246 247 rip->i_mountpoint = FALSE; 248 if (rip->i_dirt == IN_DIRTY) rw_inode(rip, WRITING); 249 250 discard_preallocated_blocks(rip); /* Return blocks to the filesystem */ 251 252 if (rip->i_links_count == NO_LINK) { 253 /* free, put at the front of the LRU list */ 254 unhash_inode(rip); 255 rip->i_num = NO_ENTRY; 256 TAILQ_INSERT_HEAD(&unused_inodes, rip, i_unused); 257 } else { 258 /* unused, put at the back of the LRU (cache it) */ 259 TAILQ_INSERT_TAIL(&unused_inodes, rip, i_unused); 260 } 261 } 262 } 263 264 265 /*===========================================================================* 266 * update_times * 267 *===========================================================================*/ 268 void update_times( 269 register struct inode *rip /* pointer to inode to be read/written */ 270 ) 271 { 272 /* Various system calls are required by the standard to update atime, ctime, 273 * or mtime. Since updating a time requires sending a message to the clock 274 * task--an expensive business--the times are marked for update by setting 275 * bits in i_update. When a stat, fstat, or sync is done, or an inode is 276 * released, update_times() may be called to actually fill in the times. 277 */ 278 279 time_t cur_time; 280 struct super_block *sp; 281 282 sp = rip->i_sp; /* get pointer to super block. */ 283 if (sp->s_rd_only) 284 return; /* no updates for read-only file systems */ 285 286 cur_time = clock_time(NULL); 287 if (rip->i_update & ATIME) 288 rip->i_atime = cur_time; 289 if (rip->i_update & CTIME) 290 rip->i_ctime = cur_time; 291 if (rip->i_update & MTIME) 292 rip->i_mtime = cur_time; 293 rip->i_update = 0; /* they are all up-to-date now */ 294 } 295 296 /*===========================================================================* 297 * rw_inode * 298 *===========================================================================*/ 299 void rw_inode( 300 register struct inode *rip, /* pointer to inode to be read/written */ 301 int rw_flag /* READING or WRITING */ 302 ) 303 { 304 /* An entry in the inode table is to be copied to or from the disk. */ 305 306 register struct buf *bp; 307 register struct super_block *sp; 308 register struct group_desc *gd; 309 register d_inode *dip; 310 u32_t block_group_number; 311 block_t b, offset; 312 313 /* Get the block where the inode resides. */ 314 sp = get_super(rip->i_dev); /* get pointer to super block */ 315 rip->i_sp = sp; /* inode must contain super block pointer */ 316 317 block_group_number = (rip->i_num - 1) / sp->s_inodes_per_group; 318 319 gd = get_group_desc(block_group_number); 320 321 if (gd == NULL) 322 panic("can't get group_desc to read/write inode"); 323 324 offset = ((rip->i_num - 1) % sp->s_inodes_per_group) * EXT2_INODE_SIZE(sp); 325 /* offset requires shifting, since each block contains several inodes, 326 * e.g. inode 2 is stored in bklock 0. 327 */ 328 b = (block_t) gd->inode_table + (offset >> sp->s_blocksize_bits); 329 bp = get_block(rip->i_dev, b, NORMAL); 330 331 offset &= (sp->s_block_size - 1); 332 dip = (d_inode*) (b_data(bp) + offset); 333 334 /* Do the read or write. */ 335 if (rw_flag == WRITING) { 336 if (rip->i_update) 337 update_times(rip); /* times need updating */ 338 if (sp->s_rd_only == FALSE) 339 lmfs_markdirty(bp); 340 } 341 342 icopy(rip, dip, rw_flag, TRUE); 343 344 put_block(bp); 345 rip->i_dirt = IN_CLEAN; 346 } 347 348 349 /*===========================================================================* 350 * icopy * 351 *===========================================================================*/ 352 static void icopy( 353 register struct inode *rip, /* pointer to the in-core inode struct */ 354 register d_inode *dip, /* pointer to the on-disk struct */ 355 int direction, /* READING (from disk) or WRITING (to disk) */ 356 int norm /* TRUE = do not swap bytes; FALSE = swap */ 357 ) 358 { 359 int i; 360 361 if (direction == READING) { 362 /* Copy inode to the in-core table, swapping bytes if need be. */ 363 rip->i_mode = conv2(norm,dip->i_mode); 364 rip->i_uid = conv2(norm,dip->i_uid); 365 rip->i_size = conv4(norm,dip->i_size); 366 rip->i_atime = conv4(norm,dip->i_atime); 367 rip->i_ctime = conv4(norm,dip->i_ctime); 368 rip->i_mtime = conv4(norm,dip->i_mtime); 369 rip->i_dtime = conv4(norm,dip->i_dtime); 370 rip->i_gid = conv2(norm,dip->i_gid); 371 rip->i_links_count = conv2(norm,dip->i_links_count); 372 rip->i_blocks = conv4(norm,dip->i_blocks); 373 rip->i_flags = conv4(norm,dip->i_flags); 374 /* Minix doesn't touch osd1 and osd2 either, so just copy. */ 375 memcpy(&rip->osd1, &dip->osd1, sizeof(rip->osd1)); 376 for (i = 0; i < EXT2_N_BLOCKS; i++) 377 rip->i_block[i] = conv4(norm, dip->i_block[i]); 378 rip->i_generation = conv4(norm,dip->i_generation); 379 rip->i_file_acl = conv4(norm,dip->i_file_acl); 380 rip->i_dir_acl = conv4(norm,dip->i_dir_acl); 381 rip->i_faddr = conv4(norm,dip->i_faddr); 382 memcpy(&rip->osd2, &dip->osd2, sizeof(rip->osd2)); 383 } else { 384 /* Copying inode to disk from the in-core table. */ 385 dip->i_mode = conv2(norm,rip->i_mode); 386 dip->i_uid = conv2(norm,rip->i_uid); 387 dip->i_size = conv4(norm,rip->i_size); 388 dip->i_atime = conv4(norm,rip->i_atime); 389 dip->i_ctime = conv4(norm,rip->i_ctime); 390 dip->i_mtime = conv4(norm,rip->i_mtime); 391 dip->i_dtime = conv4(norm,rip->i_dtime); 392 dip->i_gid = conv2(norm,rip->i_gid); 393 dip->i_links_count = conv2(norm,rip->i_links_count); 394 dip->i_blocks = conv4(norm,rip->i_blocks); 395 dip->i_flags = conv4(norm,rip->i_flags); 396 /* Minix doesn't touch osd1 and osd2 either, so just copy. */ 397 memcpy(&dip->osd1, &rip->osd1, sizeof(dip->osd1)); 398 for (i = 0; i < EXT2_N_BLOCKS; i++) 399 dip->i_block[i] = conv4(norm, rip->i_block[i]); 400 dip->i_generation = conv4(norm,rip->i_generation); 401 dip->i_file_acl = conv4(norm,rip->i_file_acl); 402 dip->i_dir_acl = conv4(norm,rip->i_dir_acl); 403 dip->i_faddr = conv4(norm,rip->i_faddr); 404 memcpy(&dip->osd2, &rip->osd2, sizeof(dip->osd2)); 405 } 406 } 407 408 409 /*===========================================================================* 410 * dup_inode * 411 *===========================================================================*/ 412 void dup_inode( 413 struct inode *ip /* The inode to be duplicated. */ 414 ) 415 { 416 /* This routine is a simplified form of get_inode() for the case where 417 * the inode pointer is already known. 418 */ 419 ip->i_count++; 420 } 421