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