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