1433d6423SLionel Sambuc /* This file manages the inode table. There are procedures to allocate and 2433d6423SLionel Sambuc * deallocate inodes, acquire, erase, and release them, and read and write 3433d6423SLionel Sambuc * them from the disk. 4433d6423SLionel Sambuc * 5433d6423SLionel Sambuc * The entry points into this file are 6433d6423SLionel Sambuc * get_inode: search inode table for a given inode; if not there, 7433d6423SLionel Sambuc * read it 8433d6423SLionel Sambuc * put_inode: indicate that an inode is no longer needed in memory 9433d6423SLionel Sambuc * alloc_inode: allocate a new, unused inode 10433d6423SLionel Sambuc * wipe_inode: erase some fields of a newly allocated inode 11433d6423SLionel Sambuc * free_inode: mark an inode as available for a new file 12433d6423SLionel Sambuc * update_times: update atime, ctime, and mtime 13433d6423SLionel Sambuc * rw_inode: read a disk block and extract an inode, or corresp. write 14433d6423SLionel Sambuc * dup_inode: indicate that someone else is using an inode table entry 15433d6423SLionel Sambuc * find_inode: retrieve pointer to inode in inode cache 16433d6423SLionel Sambuc * 17433d6423SLionel Sambuc */ 18433d6423SLionel Sambuc 19433d6423SLionel Sambuc #include "fs.h" 20433d6423SLionel Sambuc #include "buf.h" 21433d6423SLionel Sambuc #include "inode.h" 22433d6423SLionel Sambuc #include "super.h" 23433d6423SLionel Sambuc #include <minix/vfsif.h> 24433d6423SLionel Sambuc #include <assert.h> 25433d6423SLionel Sambuc 26433d6423SLionel Sambuc static void addhash_inode(struct inode *node); 27433d6423SLionel Sambuc 28433d6423SLionel Sambuc static void free_inode(dev_t dev, ino_t numb); 29433d6423SLionel Sambuc static void new_icopy(struct inode *rip, d2_inode *dip, int direction, 30433d6423SLionel Sambuc int norm); 31433d6423SLionel Sambuc static void unhash_inode(struct inode *node); 32433d6423SLionel Sambuc static void wipe_inode(struct inode *rip); 33433d6423SLionel Sambuc 34433d6423SLionel Sambuc 35433d6423SLionel Sambuc /*===========================================================================* 36433d6423SLionel Sambuc * fs_putnode * 37433d6423SLionel Sambuc *===========================================================================*/ 38433d6423SLionel Sambuc int fs_putnode(void) 39433d6423SLionel Sambuc { 40433d6423SLionel Sambuc /* Find the inode specified by the request message and decrease its counter.*/ 41433d6423SLionel Sambuc 42433d6423SLionel Sambuc struct inode *rip; 43433d6423SLionel Sambuc int count; 44433d6423SLionel Sambuc 45433d6423SLionel Sambuc rip = find_inode(fs_dev, fs_m_in.m_vfs_fs_putnode.inode); 46433d6423SLionel Sambuc 47433d6423SLionel Sambuc if(!rip) { 48433d6423SLionel Sambuc printf("%s:%d put_inode: inode #%llu dev: %llx not found\n", __FILE__, 49433d6423SLionel Sambuc __LINE__, fs_m_in.m_vfs_fs_putnode.inode, fs_dev); 50433d6423SLionel Sambuc panic("fs_putnode failed"); 51433d6423SLionel Sambuc } 52433d6423SLionel Sambuc 53433d6423SLionel Sambuc count = fs_m_in.m_vfs_fs_putnode.count; 54433d6423SLionel Sambuc if (count <= 0) { 55433d6423SLionel Sambuc printf("%s:%d put_inode: bad value for count: %d\n", __FILE__, 56433d6423SLionel Sambuc __LINE__, count); 57433d6423SLionel Sambuc panic("fs_putnode failed"); 58433d6423SLionel Sambuc } else if(count > rip->i_count) { 59433d6423SLionel Sambuc printf("%s:%d put_inode: count too high: %d > %d\n", __FILE__, 60433d6423SLionel Sambuc __LINE__, count, rip->i_count); 61433d6423SLionel Sambuc panic("fs_putnode failed"); 62433d6423SLionel Sambuc } 63433d6423SLionel Sambuc 64433d6423SLionel Sambuc /* Decrease reference counter, but keep one reference; it will be consumed by 65433d6423SLionel Sambuc * put_inode(). */ 66433d6423SLionel Sambuc rip->i_count -= count - 1; 67433d6423SLionel Sambuc put_inode(rip); 68433d6423SLionel Sambuc 69433d6423SLionel Sambuc return(OK); 70433d6423SLionel Sambuc } 71433d6423SLionel Sambuc 72433d6423SLionel Sambuc 73433d6423SLionel Sambuc /*===========================================================================* 74433d6423SLionel Sambuc * init_inode_cache * 75433d6423SLionel Sambuc *===========================================================================*/ 76433d6423SLionel Sambuc void init_inode_cache() 77433d6423SLionel Sambuc { 78433d6423SLionel Sambuc struct inode *rip; 79433d6423SLionel Sambuc struct inodelist *rlp; 80433d6423SLionel Sambuc 81433d6423SLionel Sambuc inode_cache_hit = 0; 82433d6423SLionel Sambuc inode_cache_miss = 0; 83433d6423SLionel Sambuc 84433d6423SLionel Sambuc /* init free/unused list */ 85433d6423SLionel Sambuc TAILQ_INIT(&unused_inodes); 86433d6423SLionel Sambuc 87433d6423SLionel Sambuc /* init hash lists */ 88433d6423SLionel Sambuc for (rlp = &hash_inodes[0]; rlp < &hash_inodes[INODE_HASH_SIZE]; ++rlp) 89433d6423SLionel Sambuc LIST_INIT(rlp); 90433d6423SLionel Sambuc 91433d6423SLionel Sambuc /* add free inodes to unused/free list */ 92433d6423SLionel Sambuc for (rip = &inode[0]; rip < &inode[NR_INODES]; ++rip) { 93433d6423SLionel Sambuc rip->i_num = NO_ENTRY; 94433d6423SLionel Sambuc TAILQ_INSERT_HEAD(&unused_inodes, rip, i_unused); 95433d6423SLionel Sambuc } 96433d6423SLionel Sambuc } 97433d6423SLionel Sambuc 98433d6423SLionel Sambuc 99433d6423SLionel Sambuc /*===========================================================================* 100433d6423SLionel Sambuc * addhash_inode * 101433d6423SLionel Sambuc *===========================================================================*/ 102433d6423SLionel Sambuc static void addhash_inode(struct inode *node) 103433d6423SLionel Sambuc { 104433d6423SLionel Sambuc int hashi = (int) (node->i_num & INODE_HASH_MASK); 105433d6423SLionel Sambuc 106433d6423SLionel Sambuc /* insert into hash table */ 107433d6423SLionel Sambuc LIST_INSERT_HEAD(&hash_inodes[hashi], node, i_hash); 108433d6423SLionel Sambuc } 109433d6423SLionel Sambuc 110433d6423SLionel Sambuc 111433d6423SLionel Sambuc /*===========================================================================* 112433d6423SLionel Sambuc * unhash_inode * 113433d6423SLionel Sambuc *===========================================================================*/ 114433d6423SLionel Sambuc static void unhash_inode(struct inode *node) 115433d6423SLionel Sambuc { 116433d6423SLionel Sambuc /* remove from hash table */ 117433d6423SLionel Sambuc LIST_REMOVE(node, i_hash); 118433d6423SLionel Sambuc } 119433d6423SLionel Sambuc 120433d6423SLionel Sambuc 121433d6423SLionel Sambuc /*===========================================================================* 122433d6423SLionel Sambuc * get_inode * 123433d6423SLionel Sambuc *===========================================================================*/ 124433d6423SLionel Sambuc struct inode *get_inode( 125433d6423SLionel Sambuc dev_t dev, /* device on which inode resides */ 126433d6423SLionel Sambuc ino_t numb /* inode number */ 127433d6423SLionel Sambuc ) 128433d6423SLionel Sambuc { 129433d6423SLionel Sambuc /* Find the inode in the hash table. If it is not there, get a free inode 130433d6423SLionel Sambuc * load it from the disk if it's necessary and put on the hash list 131433d6423SLionel Sambuc */ 132433d6423SLionel Sambuc register struct inode *rip; 133433d6423SLionel Sambuc int hashi; 134433d6423SLionel Sambuc 135433d6423SLionel Sambuc hashi = (int) (numb & INODE_HASH_MASK); 136433d6423SLionel Sambuc 137433d6423SLionel Sambuc /* Search inode in the hash table */ 138433d6423SLionel Sambuc LIST_FOREACH(rip, &hash_inodes[hashi], i_hash) { 139433d6423SLionel Sambuc if (rip->i_num == numb && rip->i_dev == dev) { 140433d6423SLionel Sambuc /* If unused, remove it from the unused/free list */ 141433d6423SLionel Sambuc if (rip->i_count == 0) { 142433d6423SLionel Sambuc inode_cache_hit++; 143433d6423SLionel Sambuc TAILQ_REMOVE(&unused_inodes, rip, i_unused); 144433d6423SLionel Sambuc } 145433d6423SLionel Sambuc ++rip->i_count; 146433d6423SLionel Sambuc return(rip); 147433d6423SLionel Sambuc } 148433d6423SLionel Sambuc } 149433d6423SLionel Sambuc 150433d6423SLionel Sambuc inode_cache_miss++; 151433d6423SLionel Sambuc 152433d6423SLionel Sambuc /* Inode is not on the hash, get a free one */ 153433d6423SLionel Sambuc if (TAILQ_EMPTY(&unused_inodes)) { 154433d6423SLionel Sambuc err_code = ENFILE; 155433d6423SLionel Sambuc return(NULL); 156433d6423SLionel Sambuc } 157433d6423SLionel Sambuc rip = TAILQ_FIRST(&unused_inodes); 158433d6423SLionel Sambuc 159433d6423SLionel Sambuc /* If not free unhash it */ 160433d6423SLionel Sambuc if (rip->i_num != NO_ENTRY) 161433d6423SLionel Sambuc unhash_inode(rip); 162433d6423SLionel Sambuc 163433d6423SLionel Sambuc /* Inode is not unused any more */ 164433d6423SLionel Sambuc TAILQ_REMOVE(&unused_inodes, rip, i_unused); 165433d6423SLionel Sambuc 166433d6423SLionel Sambuc /* Load the inode. */ 167433d6423SLionel Sambuc rip->i_dev = dev; 168433d6423SLionel Sambuc rip->i_num = numb; 169433d6423SLionel Sambuc rip->i_count = 1; 170433d6423SLionel Sambuc if (dev != NO_DEV) rw_inode(rip, READING); /* get inode from disk */ 171433d6423SLionel Sambuc rip->i_update = 0; /* all the times are initially up-to-date */ 172433d6423SLionel Sambuc rip->i_zsearch = NO_ZONE; /* no zones searched for yet */ 173433d6423SLionel Sambuc rip->i_mountpoint= FALSE; 174433d6423SLionel Sambuc rip->i_last_dpos = 0; /* no dentries searched for yet */ 175433d6423SLionel Sambuc 176433d6423SLionel Sambuc /* Add to hash */ 177433d6423SLionel Sambuc addhash_inode(rip); 178433d6423SLionel Sambuc 179433d6423SLionel Sambuc return(rip); 180433d6423SLionel Sambuc } 181433d6423SLionel Sambuc 182433d6423SLionel Sambuc 183433d6423SLionel Sambuc /*===========================================================================* 184433d6423SLionel Sambuc * find_inode * 185433d6423SLionel Sambuc *===========================================================================*/ 186433d6423SLionel Sambuc struct inode *find_inode( 187433d6423SLionel Sambuc dev_t dev, /* device on which inode resides */ 188433d6423SLionel Sambuc ino_t numb /* inode number */ 189433d6423SLionel Sambuc ) 190433d6423SLionel Sambuc { 191433d6423SLionel Sambuc /* Find the inode specified by the inode and device number. 192433d6423SLionel Sambuc */ 193433d6423SLionel Sambuc struct inode *rip; 194433d6423SLionel Sambuc int hashi; 195433d6423SLionel Sambuc 196433d6423SLionel Sambuc hashi = (int) (numb & INODE_HASH_MASK); 197433d6423SLionel Sambuc 198433d6423SLionel Sambuc /* Search inode in the hash table */ 199433d6423SLionel Sambuc LIST_FOREACH(rip, &hash_inodes[hashi], i_hash) { 200433d6423SLionel Sambuc if (rip->i_count > 0 && rip->i_num == numb && rip->i_dev == dev) { 201433d6423SLionel Sambuc return(rip); 202433d6423SLionel Sambuc } 203433d6423SLionel Sambuc } 204433d6423SLionel Sambuc 205433d6423SLionel Sambuc return(NULL); 206433d6423SLionel Sambuc } 207433d6423SLionel Sambuc 208433d6423SLionel Sambuc 209433d6423SLionel Sambuc /*===========================================================================* 210433d6423SLionel Sambuc * put_inode * 211433d6423SLionel Sambuc *===========================================================================*/ 212433d6423SLionel Sambuc void put_inode(rip) 213433d6423SLionel Sambuc register struct inode *rip; /* pointer to inode to be released */ 214433d6423SLionel Sambuc { 215433d6423SLionel Sambuc /* The caller is no longer using this inode. If no one else is using it either 216433d6423SLionel Sambuc * write it back to the disk immediately. If it has no links, truncate it and 217433d6423SLionel Sambuc * return it to the pool of available inodes. 218433d6423SLionel Sambuc */ 219433d6423SLionel Sambuc 220433d6423SLionel Sambuc if (rip == NULL) return; /* checking here is easier than in caller */ 221433d6423SLionel Sambuc 222433d6423SLionel Sambuc if (rip->i_count < 1) 223433d6423SLionel Sambuc panic("put_inode: i_count already below 1: %d", rip->i_count); 224433d6423SLionel Sambuc 225433d6423SLionel Sambuc if (--rip->i_count == 0) { /* i_count == 0 means no one is using it now */ 226433d6423SLionel Sambuc if (rip->i_nlinks == NO_LINK) { 227433d6423SLionel Sambuc /* i_nlinks == NO_LINK means free the inode. */ 228433d6423SLionel Sambuc /* return all the disk blocks */ 229433d6423SLionel Sambuc 230433d6423SLionel Sambuc /* Ignore errors by truncate_inode in case inode is a block 231433d6423SLionel Sambuc * special or character special file. 232433d6423SLionel Sambuc */ 233433d6423SLionel Sambuc (void) truncate_inode(rip, (off_t) 0); 234433d6423SLionel Sambuc rip->i_mode = I_NOT_ALLOC; /* clear I_TYPE field */ 235433d6423SLionel Sambuc IN_MARKDIRTY(rip); 236433d6423SLionel Sambuc free_inode(rip->i_dev, rip->i_num); 237433d6423SLionel Sambuc } 238433d6423SLionel Sambuc 239433d6423SLionel Sambuc rip->i_mountpoint = FALSE; 240433d6423SLionel Sambuc if (IN_ISDIRTY(rip)) rw_inode(rip, WRITING); 241433d6423SLionel Sambuc 242433d6423SLionel Sambuc if (rip->i_nlinks == NO_LINK) { 243433d6423SLionel Sambuc /* free, put at the front of the LRU list */ 244433d6423SLionel Sambuc unhash_inode(rip); 245433d6423SLionel Sambuc rip->i_num = NO_ENTRY; 246433d6423SLionel Sambuc TAILQ_INSERT_HEAD(&unused_inodes, rip, i_unused); 247433d6423SLionel Sambuc } else { 248433d6423SLionel Sambuc /* unused, put at the back of the LRU (cache it) */ 249433d6423SLionel Sambuc TAILQ_INSERT_TAIL(&unused_inodes, rip, i_unused); 250433d6423SLionel Sambuc } 251433d6423SLionel Sambuc } 252433d6423SLionel Sambuc } 253433d6423SLionel Sambuc 254433d6423SLionel Sambuc 255433d6423SLionel Sambuc /*===========================================================================* 256433d6423SLionel Sambuc * alloc_inode * 257433d6423SLionel Sambuc *===========================================================================*/ 258433d6423SLionel Sambuc struct inode *alloc_inode(dev_t dev, mode_t bits) 259433d6423SLionel Sambuc { 260433d6423SLionel Sambuc /* Allocate a free inode on 'dev', and return a pointer to it. */ 261433d6423SLionel Sambuc 262433d6423SLionel Sambuc register struct inode *rip; 263433d6423SLionel Sambuc register struct super_block *sp; 264433d6423SLionel Sambuc int major, minor, inumb; 265433d6423SLionel Sambuc bit_t b; 266433d6423SLionel Sambuc 267433d6423SLionel Sambuc sp = get_super(dev); /* get pointer to super_block */ 268433d6423SLionel Sambuc if (sp->s_rd_only) { /* can't allocate an inode on a read only device. */ 269433d6423SLionel Sambuc err_code = EROFS; 270433d6423SLionel Sambuc return(NULL); 271433d6423SLionel Sambuc } 272433d6423SLionel Sambuc 273433d6423SLionel Sambuc /* Acquire an inode from the bit map. */ 274433d6423SLionel Sambuc b = alloc_bit(sp, IMAP, sp->s_isearch); 275433d6423SLionel Sambuc if (b == NO_BIT) { 276433d6423SLionel Sambuc err_code = ENOSPC; 277433d6423SLionel Sambuc major = major(sp->s_dev); 278433d6423SLionel Sambuc minor = minor(sp->s_dev); 279433d6423SLionel Sambuc printf("Out of i-nodes on device %d/%d\n", major, minor); 280433d6423SLionel Sambuc return(NULL); 281433d6423SLionel Sambuc } 282433d6423SLionel Sambuc sp->s_isearch = b; /* next time start here */ 283433d6423SLionel Sambuc inumb = (int) b; /* be careful not to pass unshort as param */ 284433d6423SLionel Sambuc 285433d6423SLionel Sambuc /* Try to acquire a slot in the inode table. */ 286433d6423SLionel Sambuc if ((rip = get_inode(NO_DEV, inumb)) == NULL) { 287433d6423SLionel Sambuc /* No inode table slots available. Free the inode just allocated. */ 288433d6423SLionel Sambuc free_bit(sp, IMAP, b); 289433d6423SLionel Sambuc } else { 290433d6423SLionel Sambuc /* An inode slot is available. Put the inode just allocated into it. */ 291433d6423SLionel Sambuc rip->i_mode = bits; /* set up RWX bits */ 292433d6423SLionel Sambuc rip->i_nlinks = NO_LINK; /* initial no links */ 293433d6423SLionel Sambuc rip->i_uid = caller_uid; /* file's uid is owner's */ 294433d6423SLionel Sambuc rip->i_gid = caller_gid; /* ditto group id */ 295433d6423SLionel Sambuc rip->i_dev = dev; /* mark which device it is on */ 296433d6423SLionel Sambuc rip->i_ndzones = sp->s_ndzones; /* number of direct zones */ 297433d6423SLionel Sambuc rip->i_nindirs = sp->s_nindirs; /* number of indirect zones per blk*/ 298433d6423SLionel Sambuc rip->i_sp = sp; /* pointer to super block */ 299433d6423SLionel Sambuc 300433d6423SLionel Sambuc /* Fields not cleared already are cleared in wipe_inode(). They have 301433d6423SLionel Sambuc * been put there because truncate() needs to clear the same fields if 302433d6423SLionel Sambuc * the file happens to be open while being truncated. It saves space 303433d6423SLionel Sambuc * not to repeat the code twice. 304433d6423SLionel Sambuc */ 305433d6423SLionel Sambuc wipe_inode(rip); 306433d6423SLionel Sambuc } 307433d6423SLionel Sambuc 308433d6423SLionel Sambuc return(rip); 309433d6423SLionel Sambuc } 310433d6423SLionel Sambuc 311433d6423SLionel Sambuc 312433d6423SLionel Sambuc /*===========================================================================* 313433d6423SLionel Sambuc * wipe_inode * 314433d6423SLionel Sambuc *===========================================================================*/ 315433d6423SLionel Sambuc static void wipe_inode(rip) 316433d6423SLionel Sambuc register struct inode *rip; /* the inode to be erased */ 317433d6423SLionel Sambuc { 318433d6423SLionel Sambuc /* Erase some fields in the inode. This function is called from alloc_inode() 319433d6423SLionel Sambuc * when a new inode is to be allocated, and from truncate(), when an existing 320433d6423SLionel Sambuc * inode is to be truncated. 321433d6423SLionel Sambuc */ 322433d6423SLionel Sambuc 323433d6423SLionel Sambuc register int i; 324433d6423SLionel Sambuc 325433d6423SLionel Sambuc rip->i_size = 0; 326433d6423SLionel Sambuc rip->i_update = ATIME | CTIME | MTIME; /* update all times later */ 327433d6423SLionel Sambuc IN_MARKDIRTY(rip); 328433d6423SLionel Sambuc for (i = 0; i < V2_NR_TZONES; i++) rip->i_zone[i] = NO_ZONE; 329433d6423SLionel Sambuc } 330433d6423SLionel Sambuc 331433d6423SLionel Sambuc /*===========================================================================* 332433d6423SLionel Sambuc * free_inode * 333433d6423SLionel Sambuc *===========================================================================*/ 334433d6423SLionel Sambuc static void free_inode( 335433d6423SLionel Sambuc dev_t dev, /* on which device is the inode? */ 336433d6423SLionel Sambuc ino_t inumb /* number of the inode to be freed */ 337433d6423SLionel Sambuc ) 338433d6423SLionel Sambuc { 339433d6423SLionel Sambuc /* Return an inode to the pool of unallocated inodes. */ 340433d6423SLionel Sambuc 341433d6423SLionel Sambuc register struct super_block *sp; 342433d6423SLionel Sambuc bit_t b; 343433d6423SLionel Sambuc 344433d6423SLionel Sambuc /* Locate the appropriate super_block. */ 345433d6423SLionel Sambuc sp = get_super(dev); 346433d6423SLionel Sambuc if (inumb == NO_ENTRY || inumb > sp->s_ninodes) return; 347433d6423SLionel Sambuc b = (bit_t) inumb; 348433d6423SLionel Sambuc free_bit(sp, IMAP, b); 349433d6423SLionel Sambuc if (b < sp->s_isearch) sp->s_isearch = b; 350433d6423SLionel Sambuc } 351433d6423SLionel Sambuc 352433d6423SLionel Sambuc 353433d6423SLionel Sambuc /*===========================================================================* 354433d6423SLionel Sambuc * update_times * 355433d6423SLionel Sambuc *===========================================================================*/ 356433d6423SLionel Sambuc void update_times(rip) 357433d6423SLionel Sambuc register struct inode *rip; /* pointer to inode to be read/written */ 358433d6423SLionel Sambuc { 359433d6423SLionel Sambuc /* Various system calls are required by the standard to update atime, ctime, 360433d6423SLionel Sambuc * or mtime. Since updating a time requires sending a message to the clock 361433d6423SLionel Sambuc * task--an expensive business--the times are marked for update by setting 362433d6423SLionel Sambuc * bits in i_update. When a stat, fstat, or sync is done, or an inode is 363433d6423SLionel Sambuc * released, update_times() may be called to actually fill in the times. 364433d6423SLionel Sambuc */ 365433d6423SLionel Sambuc 366433d6423SLionel Sambuc time_t cur_time; 367433d6423SLionel Sambuc struct super_block *sp; 368433d6423SLionel Sambuc 369433d6423SLionel Sambuc sp = rip->i_sp; /* get pointer to super block. */ 370433d6423SLionel Sambuc if (sp->s_rd_only) return; /* no updates for read-only file systems */ 371433d6423SLionel Sambuc 372*ad80a203SDavid van Moolenbroek cur_time = clock_time(NULL); 373433d6423SLionel Sambuc if (rip->i_update & ATIME) rip->i_atime = cur_time; 374433d6423SLionel Sambuc if (rip->i_update & CTIME) rip->i_ctime = cur_time; 375433d6423SLionel Sambuc if (rip->i_update & MTIME) rip->i_mtime = cur_time; 376433d6423SLionel Sambuc rip->i_update = 0; /* they are all up-to-date now */ 377433d6423SLionel Sambuc } 378433d6423SLionel Sambuc 379433d6423SLionel Sambuc /*===========================================================================* 380433d6423SLionel Sambuc * rw_inode * 381433d6423SLionel Sambuc *===========================================================================*/ 382433d6423SLionel Sambuc void rw_inode(rip, rw_flag) 383433d6423SLionel Sambuc register struct inode *rip; /* pointer to inode to be read/written */ 384433d6423SLionel Sambuc int rw_flag; /* READING or WRITING */ 385433d6423SLionel Sambuc { 386433d6423SLionel Sambuc /* An entry in the inode table is to be copied to or from the disk. */ 387433d6423SLionel Sambuc 388433d6423SLionel Sambuc register struct buf *bp; 389433d6423SLionel Sambuc register struct super_block *sp; 390433d6423SLionel Sambuc d2_inode *dip2; 391433d6423SLionel Sambuc block_t b, offset; 392433d6423SLionel Sambuc 393433d6423SLionel Sambuc /* Get the block where the inode resides. */ 394433d6423SLionel Sambuc sp = get_super(rip->i_dev); /* get pointer to super block */ 395433d6423SLionel Sambuc rip->i_sp = sp; /* inode must contain super block pointer */ 396433d6423SLionel Sambuc offset = START_BLOCK + sp->s_imap_blocks + sp->s_zmap_blocks; 397433d6423SLionel Sambuc b = (block_t) (rip->i_num - 1)/sp->s_inodes_per_block + offset; 398433d6423SLionel Sambuc bp = get_block(rip->i_dev, b, NORMAL); 399433d6423SLionel Sambuc dip2 = b_v2_ino(bp) + (rip->i_num - 1) % 400433d6423SLionel Sambuc V2_INODES_PER_BLOCK(sp->s_block_size); 401433d6423SLionel Sambuc 402433d6423SLionel Sambuc /* Do the read or write. */ 403433d6423SLionel Sambuc if (rw_flag == WRITING) { 404433d6423SLionel Sambuc if (rip->i_update) update_times(rip); /* times need updating */ 405433d6423SLionel Sambuc if (sp->s_rd_only == FALSE) MARKDIRTY(bp); 406433d6423SLionel Sambuc } 407433d6423SLionel Sambuc 408433d6423SLionel Sambuc /* Copy the inode from the disk block to the in-core table or vice versa. 409433d6423SLionel Sambuc * If the fourth parameter below is FALSE, the bytes are swapped. 410433d6423SLionel Sambuc */ 411433d6423SLionel Sambuc assert(sp->s_version == V3); 412433d6423SLionel Sambuc new_icopy(rip, dip2, rw_flag, sp->s_native); 413433d6423SLionel Sambuc 414433d6423SLionel Sambuc put_block(bp, INODE_BLOCK); 415433d6423SLionel Sambuc IN_MARKCLEAN(rip); 416433d6423SLionel Sambuc } 417433d6423SLionel Sambuc 418433d6423SLionel Sambuc /*===========================================================================* 419433d6423SLionel Sambuc * new_icopy * 420433d6423SLionel Sambuc *===========================================================================*/ 421433d6423SLionel Sambuc static void new_icopy(rip, dip, direction, norm) 422433d6423SLionel Sambuc register struct inode *rip; /* pointer to the in-core inode struct */ 423433d6423SLionel Sambuc register d2_inode *dip; /* pointer to the d2_inode struct */ 424433d6423SLionel Sambuc int direction; /* READING (from disk) or WRITING (to disk) */ 425433d6423SLionel Sambuc int norm; /* TRUE = do not swap bytes; FALSE = swap */ 426433d6423SLionel Sambuc { 427433d6423SLionel Sambuc int i; 428433d6423SLionel Sambuc 429433d6423SLionel Sambuc if (direction == READING) { 430433d6423SLionel Sambuc /* Copy V2.x inode to the in-core table, swapping bytes if need be. */ 431433d6423SLionel Sambuc rip->i_mode = (mode_t) conv2(norm,dip->d2_mode); 432433d6423SLionel Sambuc rip->i_uid = (uid_t) conv2(norm,dip->d2_uid); 433433d6423SLionel Sambuc rip->i_nlinks = (nlink_t) conv2(norm,dip->d2_nlinks); 434433d6423SLionel Sambuc rip->i_gid = (gid_t) conv2(norm,dip->d2_gid); 435433d6423SLionel Sambuc rip->i_size = (off_t) conv4(norm,dip->d2_size); 436433d6423SLionel Sambuc rip->i_atime = (time_t) conv4(norm,dip->d2_atime); 437433d6423SLionel Sambuc rip->i_ctime = (time_t) conv4(norm,dip->d2_ctime); 438433d6423SLionel Sambuc rip->i_mtime = (time_t) conv4(norm,dip->d2_mtime); 439433d6423SLionel Sambuc rip->i_ndzones = V2_NR_DZONES; 440433d6423SLionel Sambuc rip->i_nindirs = V2_INDIRECTS(rip->i_sp->s_block_size); 441433d6423SLionel Sambuc for (i = 0; i < V2_NR_TZONES; i++) 442433d6423SLionel Sambuc rip->i_zone[i] = (zone_t) conv4(norm, (long) dip->d2_zone[i]); 443433d6423SLionel Sambuc } else { 444433d6423SLionel Sambuc /* Copying V2.x inode to disk from the in-core table. */ 445433d6423SLionel Sambuc dip->d2_mode = (u16_t) conv2(norm,rip->i_mode); 446433d6423SLionel Sambuc dip->d2_uid = (i16_t) conv2(norm,rip->i_uid); 447433d6423SLionel Sambuc dip->d2_nlinks = (u16_t) conv2(norm,rip->i_nlinks); 448433d6423SLionel Sambuc dip->d2_gid = (u16_t) conv2(norm,rip->i_gid); 449433d6423SLionel Sambuc dip->d2_size = (i32_t) conv4(norm,rip->i_size); 450433d6423SLionel Sambuc dip->d2_atime = (i32_t) conv4(norm,rip->i_atime); 451433d6423SLionel Sambuc dip->d2_ctime = (i32_t) conv4(norm,rip->i_ctime); 452433d6423SLionel Sambuc dip->d2_mtime = (i32_t) conv4(norm,rip->i_mtime); 453433d6423SLionel Sambuc for (i = 0; i < V2_NR_TZONES; i++) 454433d6423SLionel Sambuc dip->d2_zone[i] = (zone_t) conv4(norm, (long) rip->i_zone[i]); 455433d6423SLionel Sambuc } 456433d6423SLionel Sambuc } 457433d6423SLionel Sambuc 458433d6423SLionel Sambuc 459433d6423SLionel Sambuc /*===========================================================================* 460433d6423SLionel Sambuc * dup_inode * 461433d6423SLionel Sambuc *===========================================================================*/ 462433d6423SLionel Sambuc void dup_inode(ip) 463433d6423SLionel Sambuc struct inode *ip; /* The inode to be duplicated. */ 464433d6423SLionel Sambuc { 465433d6423SLionel Sambuc /* This routine is a simplified form of get_inode() for the case where 466433d6423SLionel Sambuc * the inode pointer is already known. 467433d6423SLionel Sambuc */ 468433d6423SLionel Sambuc 469433d6423SLionel Sambuc ip->i_count++; 470433d6423SLionel Sambuc } 471433d6423SLionel Sambuc 472