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 * alloc_inode: allocate a new, unused inode 10 * wipe_inode: erase some fields of a newly allocated inode 11 * free_inode: mark an inode as available for a new file 12 * update_times: update atime, ctime, and mtime 13 * rw_inode: read a disk block and extract an inode, or corresp. write 14 * dup_inode: indicate that someone else is using an inode table entry 15 * find_inode: retrieve pointer to inode in inode cache 16 * 17 */ 18 19 #include "fs.h" 20 #include "buf.h" 21 #include "inode.h" 22 #include "super.h" 23 #include <minix/vfsif.h> 24 #include <assert.h> 25 26 static void addhash_inode(struct inode *node); 27 28 static void free_inode(dev_t dev, ino_t numb); 29 static void new_icopy(struct inode *rip, d2_inode *dip, int direction, 30 int norm); 31 static void unhash_inode(struct inode *node); 32 static void wipe_inode(struct inode *rip); 33 34 35 /*===========================================================================* 36 * fs_putnode * 37 *===========================================================================*/ 38 int fs_putnode(void) 39 { 40 /* Find the inode specified by the request message and decrease its counter.*/ 41 42 struct inode *rip; 43 int count; 44 45 rip = find_inode(fs_dev, fs_m_in.m_vfs_fs_putnode.inode); 46 47 if(!rip) { 48 printf("%s:%d put_inode: inode #%llu dev: %llx not found\n", __FILE__, 49 __LINE__, fs_m_in.m_vfs_fs_putnode.inode, fs_dev); 50 panic("fs_putnode failed"); 51 } 52 53 count = fs_m_in.m_vfs_fs_putnode.count; 54 if (count <= 0) { 55 printf("%s:%d put_inode: bad value for count: %d\n", __FILE__, 56 __LINE__, count); 57 panic("fs_putnode failed"); 58 } else if(count > rip->i_count) { 59 printf("%s:%d put_inode: count too high: %d > %d\n", __FILE__, 60 __LINE__, count, rip->i_count); 61 panic("fs_putnode failed"); 62 } 63 64 /* Decrease reference counter, but keep one reference; it will be consumed by 65 * put_inode(). */ 66 rip->i_count -= count - 1; 67 put_inode(rip); 68 69 return(OK); 70 } 71 72 73 /*===========================================================================* 74 * init_inode_cache * 75 *===========================================================================*/ 76 void init_inode_cache() 77 { 78 struct inode *rip; 79 struct inodelist *rlp; 80 81 inode_cache_hit = 0; 82 inode_cache_miss = 0; 83 84 /* init free/unused list */ 85 TAILQ_INIT(&unused_inodes); 86 87 /* init hash lists */ 88 for (rlp = &hash_inodes[0]; rlp < &hash_inodes[INODE_HASH_SIZE]; ++rlp) 89 LIST_INIT(rlp); 90 91 /* add free inodes to unused/free list */ 92 for (rip = &inode[0]; rip < &inode[NR_INODES]; ++rip) { 93 rip->i_num = NO_ENTRY; 94 TAILQ_INSERT_HEAD(&unused_inodes, rip, i_unused); 95 } 96 } 97 98 99 /*===========================================================================* 100 * addhash_inode * 101 *===========================================================================*/ 102 static void addhash_inode(struct inode *node) 103 { 104 int hashi = (int) (node->i_num & INODE_HASH_MASK); 105 106 /* insert into hash table */ 107 LIST_INSERT_HEAD(&hash_inodes[hashi], node, i_hash); 108 } 109 110 111 /*===========================================================================* 112 * unhash_inode * 113 *===========================================================================*/ 114 static void unhash_inode(struct inode *node) 115 { 116 /* remove from hash table */ 117 LIST_REMOVE(node, i_hash); 118 } 119 120 121 /*===========================================================================* 122 * get_inode * 123 *===========================================================================*/ 124 struct inode *get_inode( 125 dev_t dev, /* device on which inode resides */ 126 ino_t numb /* inode number */ 127 ) 128 { 129 /* Find the inode in the hash table. If it is not there, get a free inode 130 * load it from the disk if it's necessary and put on the hash list 131 */ 132 register struct inode *rip; 133 int hashi; 134 135 hashi = (int) (numb & INODE_HASH_MASK); 136 137 /* Search inode in the hash table */ 138 LIST_FOREACH(rip, &hash_inodes[hashi], i_hash) { 139 if (rip->i_num == numb && rip->i_dev == dev) { 140 /* If unused, remove it from the unused/free list */ 141 if (rip->i_count == 0) { 142 inode_cache_hit++; 143 TAILQ_REMOVE(&unused_inodes, rip, i_unused); 144 } 145 ++rip->i_count; 146 return(rip); 147 } 148 } 149 150 inode_cache_miss++; 151 152 /* Inode is not on the hash, get a free one */ 153 if (TAILQ_EMPTY(&unused_inodes)) { 154 err_code = ENFILE; 155 return(NULL); 156 } 157 rip = TAILQ_FIRST(&unused_inodes); 158 159 /* If not free unhash it */ 160 if (rip->i_num != NO_ENTRY) 161 unhash_inode(rip); 162 163 /* Inode is not unused any more */ 164 TAILQ_REMOVE(&unused_inodes, rip, i_unused); 165 166 /* Load the inode. */ 167 rip->i_dev = dev; 168 rip->i_num = numb; 169 rip->i_count = 1; 170 if (dev != NO_DEV) rw_inode(rip, READING); /* get inode from disk */ 171 rip->i_update = 0; /* all the times are initially up-to-date */ 172 rip->i_zsearch = NO_ZONE; /* no zones searched for yet */ 173 rip->i_mountpoint= FALSE; 174 rip->i_last_dpos = 0; /* no dentries searched for yet */ 175 176 /* Add to hash */ 177 addhash_inode(rip); 178 179 return(rip); 180 } 181 182 183 /*===========================================================================* 184 * find_inode * 185 *===========================================================================*/ 186 struct inode *find_inode( 187 dev_t dev, /* device on which inode resides */ 188 ino_t numb /* inode number */ 189 ) 190 { 191 /* Find the inode specified by the inode and device number. 192 */ 193 struct inode *rip; 194 int hashi; 195 196 hashi = (int) (numb & INODE_HASH_MASK); 197 198 /* Search inode in the hash table */ 199 LIST_FOREACH(rip, &hash_inodes[hashi], i_hash) { 200 if (rip->i_count > 0 && rip->i_num == numb && rip->i_dev == dev) { 201 return(rip); 202 } 203 } 204 205 return(NULL); 206 } 207 208 209 /*===========================================================================* 210 * put_inode * 211 *===========================================================================*/ 212 void put_inode(rip) 213 register struct inode *rip; /* pointer to inode to be released */ 214 { 215 /* The caller is no longer using this inode. If no one else is using it either 216 * write it back to the disk immediately. If it has no links, truncate it and 217 * return it to the pool of available inodes. 218 */ 219 220 if (rip == NULL) return; /* checking here is easier than in caller */ 221 222 if (rip->i_count < 1) 223 panic("put_inode: i_count already below 1: %d", rip->i_count); 224 225 if (--rip->i_count == 0) { /* i_count == 0 means no one is using it now */ 226 if (rip->i_nlinks == NO_LINK) { 227 /* i_nlinks == NO_LINK means free the inode. */ 228 /* return all the disk blocks */ 229 230 /* Ignore errors by truncate_inode in case inode is a block 231 * special or character special file. 232 */ 233 (void) truncate_inode(rip, (off_t) 0); 234 rip->i_mode = I_NOT_ALLOC; /* clear I_TYPE field */ 235 IN_MARKDIRTY(rip); 236 free_inode(rip->i_dev, rip->i_num); 237 } 238 239 rip->i_mountpoint = FALSE; 240 if (IN_ISDIRTY(rip)) rw_inode(rip, WRITING); 241 242 if (rip->i_nlinks == NO_LINK) { 243 /* free, put at the front of the LRU list */ 244 unhash_inode(rip); 245 rip->i_num = NO_ENTRY; 246 TAILQ_INSERT_HEAD(&unused_inodes, rip, i_unused); 247 } else { 248 /* unused, put at the back of the LRU (cache it) */ 249 TAILQ_INSERT_TAIL(&unused_inodes, rip, i_unused); 250 } 251 } 252 } 253 254 255 /*===========================================================================* 256 * alloc_inode * 257 *===========================================================================*/ 258 struct inode *alloc_inode(dev_t dev, mode_t bits) 259 { 260 /* Allocate a free inode on 'dev', and return a pointer to it. */ 261 262 register struct inode *rip; 263 register struct super_block *sp; 264 int major, minor, inumb; 265 bit_t b; 266 267 sp = get_super(dev); /* get pointer to super_block */ 268 if (sp->s_rd_only) { /* can't allocate an inode on a read only device. */ 269 err_code = EROFS; 270 return(NULL); 271 } 272 273 /* Acquire an inode from the bit map. */ 274 b = alloc_bit(sp, IMAP, sp->s_isearch); 275 if (b == NO_BIT) { 276 err_code = ENOSPC; 277 major = major(sp->s_dev); 278 minor = minor(sp->s_dev); 279 printf("Out of i-nodes on device %d/%d\n", major, minor); 280 return(NULL); 281 } 282 sp->s_isearch = b; /* next time start here */ 283 inumb = (int) b; /* be careful not to pass unshort as param */ 284 285 /* Try to acquire a slot in the inode table. */ 286 if ((rip = get_inode(NO_DEV, inumb)) == NULL) { 287 /* No inode table slots available. Free the inode just allocated. */ 288 free_bit(sp, IMAP, b); 289 } else { 290 /* An inode slot is available. Put the inode just allocated into it. */ 291 rip->i_mode = bits; /* set up RWX bits */ 292 rip->i_nlinks = NO_LINK; /* initial no links */ 293 rip->i_uid = caller_uid; /* file's uid is owner's */ 294 rip->i_gid = caller_gid; /* ditto group id */ 295 rip->i_dev = dev; /* mark which device it is on */ 296 rip->i_ndzones = sp->s_ndzones; /* number of direct zones */ 297 rip->i_nindirs = sp->s_nindirs; /* number of indirect zones per blk*/ 298 rip->i_sp = sp; /* pointer to super block */ 299 300 /* Fields not cleared already are cleared in wipe_inode(). They have 301 * been put there because truncate() needs to clear the same fields if 302 * the file happens to be open while being truncated. It saves space 303 * not to repeat the code twice. 304 */ 305 wipe_inode(rip); 306 } 307 308 return(rip); 309 } 310 311 312 /*===========================================================================* 313 * wipe_inode * 314 *===========================================================================*/ 315 static void wipe_inode(rip) 316 register struct inode *rip; /* the inode to be erased */ 317 { 318 /* Erase some fields in the inode. This function is called from alloc_inode() 319 * when a new inode is to be allocated, and from truncate(), when an existing 320 * inode is to be truncated. 321 */ 322 323 register int i; 324 325 rip->i_size = 0; 326 rip->i_update = ATIME | CTIME | MTIME; /* update all times later */ 327 IN_MARKDIRTY(rip); 328 for (i = 0; i < V2_NR_TZONES; i++) rip->i_zone[i] = NO_ZONE; 329 } 330 331 /*===========================================================================* 332 * free_inode * 333 *===========================================================================*/ 334 static void free_inode( 335 dev_t dev, /* on which device is the inode? */ 336 ino_t inumb /* number of the inode to be freed */ 337 ) 338 { 339 /* Return an inode to the pool of unallocated inodes. */ 340 341 register struct super_block *sp; 342 bit_t b; 343 344 /* Locate the appropriate super_block. */ 345 sp = get_super(dev); 346 if (inumb == NO_ENTRY || inumb > sp->s_ninodes) return; 347 b = (bit_t) inumb; 348 free_bit(sp, IMAP, b); 349 if (b < sp->s_isearch) sp->s_isearch = b; 350 } 351 352 353 /*===========================================================================* 354 * update_times * 355 *===========================================================================*/ 356 void update_times(rip) 357 register struct inode *rip; /* pointer to inode to be read/written */ 358 { 359 /* Various system calls are required by the standard to update atime, ctime, 360 * or mtime. Since updating a time requires sending a message to the clock 361 * task--an expensive business--the times are marked for update by setting 362 * bits in i_update. When a stat, fstat, or sync is done, or an inode is 363 * released, update_times() may be called to actually fill in the times. 364 */ 365 366 time_t cur_time; 367 struct super_block *sp; 368 369 sp = rip->i_sp; /* get pointer to super block. */ 370 if (sp->s_rd_only) return; /* no updates for read-only file systems */ 371 372 cur_time = clock_time(); 373 if (rip->i_update & ATIME) rip->i_atime = cur_time; 374 if (rip->i_update & CTIME) rip->i_ctime = cur_time; 375 if (rip->i_update & MTIME) rip->i_mtime = cur_time; 376 rip->i_update = 0; /* they are all up-to-date now */ 377 } 378 379 /*===========================================================================* 380 * rw_inode * 381 *===========================================================================*/ 382 void rw_inode(rip, rw_flag) 383 register struct inode *rip; /* pointer to inode to be read/written */ 384 int rw_flag; /* READING or WRITING */ 385 { 386 /* An entry in the inode table is to be copied to or from the disk. */ 387 388 register struct buf *bp; 389 register struct super_block *sp; 390 d2_inode *dip2; 391 block_t b, offset; 392 393 /* Get the block where the inode resides. */ 394 sp = get_super(rip->i_dev); /* get pointer to super block */ 395 rip->i_sp = sp; /* inode must contain super block pointer */ 396 offset = START_BLOCK + sp->s_imap_blocks + sp->s_zmap_blocks; 397 b = (block_t) (rip->i_num - 1)/sp->s_inodes_per_block + offset; 398 bp = get_block(rip->i_dev, b, NORMAL); 399 dip2 = b_v2_ino(bp) + (rip->i_num - 1) % 400 V2_INODES_PER_BLOCK(sp->s_block_size); 401 402 /* Do the read or write. */ 403 if (rw_flag == WRITING) { 404 if (rip->i_update) update_times(rip); /* times need updating */ 405 if (sp->s_rd_only == FALSE) MARKDIRTY(bp); 406 } 407 408 /* Copy the inode from the disk block to the in-core table or vice versa. 409 * If the fourth parameter below is FALSE, the bytes are swapped. 410 */ 411 assert(sp->s_version == V3); 412 new_icopy(rip, dip2, rw_flag, sp->s_native); 413 414 put_block(bp, INODE_BLOCK); 415 IN_MARKCLEAN(rip); 416 } 417 418 /*===========================================================================* 419 * new_icopy * 420 *===========================================================================*/ 421 static void new_icopy(rip, dip, direction, norm) 422 register struct inode *rip; /* pointer to the in-core inode struct */ 423 register d2_inode *dip; /* pointer to the d2_inode struct */ 424 int direction; /* READING (from disk) or WRITING (to disk) */ 425 int norm; /* TRUE = do not swap bytes; FALSE = swap */ 426 { 427 int i; 428 429 if (direction == READING) { 430 /* Copy V2.x inode to the in-core table, swapping bytes if need be. */ 431 rip->i_mode = (mode_t) conv2(norm,dip->d2_mode); 432 rip->i_uid = (uid_t) conv2(norm,dip->d2_uid); 433 rip->i_nlinks = (nlink_t) conv2(norm,dip->d2_nlinks); 434 rip->i_gid = (gid_t) conv2(norm,dip->d2_gid); 435 rip->i_size = (off_t) conv4(norm,dip->d2_size); 436 rip->i_atime = (time_t) conv4(norm,dip->d2_atime); 437 rip->i_ctime = (time_t) conv4(norm,dip->d2_ctime); 438 rip->i_mtime = (time_t) conv4(norm,dip->d2_mtime); 439 rip->i_ndzones = V2_NR_DZONES; 440 rip->i_nindirs = V2_INDIRECTS(rip->i_sp->s_block_size); 441 for (i = 0; i < V2_NR_TZONES; i++) 442 rip->i_zone[i] = (zone_t) conv4(norm, (long) dip->d2_zone[i]); 443 } else { 444 /* Copying V2.x inode to disk from the in-core table. */ 445 dip->d2_mode = (u16_t) conv2(norm,rip->i_mode); 446 dip->d2_uid = (i16_t) conv2(norm,rip->i_uid); 447 dip->d2_nlinks = (u16_t) conv2(norm,rip->i_nlinks); 448 dip->d2_gid = (u16_t) conv2(norm,rip->i_gid); 449 dip->d2_size = (i32_t) conv4(norm,rip->i_size); 450 dip->d2_atime = (i32_t) conv4(norm,rip->i_atime); 451 dip->d2_ctime = (i32_t) conv4(norm,rip->i_ctime); 452 dip->d2_mtime = (i32_t) conv4(norm,rip->i_mtime); 453 for (i = 0; i < V2_NR_TZONES; i++) 454 dip->d2_zone[i] = (zone_t) conv4(norm, (long) rip->i_zone[i]); 455 } 456 } 457 458 459 /*===========================================================================* 460 * dup_inode * 461 *===========================================================================*/ 462 void dup_inode(ip) 463 struct inode *ip; /* The inode to be duplicated. */ 464 { 465 /* This routine is a simplified form of get_inode() for the case where 466 * the inode pointer is already known. 467 */ 468 469 ip->i_count++; 470 } 471 472