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