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