1*1203Sbill /* lfs_inode.c 3.5 10/03/80 */ 224Sbill 324Sbill #include "../h/param.h" 424Sbill #include "../h/systm.h" 524Sbill #include "../h/mount.h" 624Sbill #include "../h/dir.h" 724Sbill #include "../h/user.h" 824Sbill #include "../h/inode.h" 924Sbill #include "../h/ino.h" 1024Sbill #include "../h/filsys.h" 1124Sbill #include "../h/conf.h" 1224Sbill #include "../h/buf.h" 1324Sbill #include "../h/inline.h" 1424Sbill 1524Sbill #define INOHSZ 63 1624Sbill #define INOHASH(dev,ino) (((dev)+(ino))%INOHSZ) 1724Sbill short inohash[INOHSZ]; 1824Sbill short ifreel; 1924Sbill 2024Sbill /* 2124Sbill * Initialize hash links for inodes 2224Sbill * and build inode free list. 2324Sbill */ 2424Sbill ihinit() 2524Sbill { 2624Sbill register int i; 2724Sbill 2824Sbill ifreel = 0; 2924Sbill for (i = 0; i < NINODE - 1; i++) 3024Sbill inode[i].i_hlink = i+1; 3124Sbill inode[NINODE - 1].i_hlink = -1; 3224Sbill for (i = 0; i < INOHSZ; i++) 3324Sbill inohash[i] = -1; 3424Sbill } 3524Sbill 3624Sbill /* 3724Sbill * Find an inode if it is incore. 3824Sbill * This is the equivalent, for inodes, 3924Sbill * of ``incore'' in bio.c or ``pfind'' in subr.c. 4024Sbill */ 4124Sbill struct inode * 4224Sbill ifind(dev, ino) 4324Sbill dev_t dev; 4424Sbill ino_t ino; 4524Sbill { 4624Sbill register struct inode *ip; 4724Sbill 4824Sbill for (ip = &inode[inohash[INOHASH(dev,ino)]]; ip != &inode[-1]; 4924Sbill ip = &inode[ip->i_hlink]) 5024Sbill if (ino==ip->i_number && dev==ip->i_dev) 5124Sbill return (ip); 5224Sbill return ((struct inode *)0); 5324Sbill } 5424Sbill 5524Sbill /* 5624Sbill * Look up an inode by device,inumber. 5724Sbill * If it is in core (in the inode structure), 5824Sbill * honor the locking protocol. 5924Sbill * If it is not in core, read it in from the 6024Sbill * specified device. 6124Sbill * If the inode is mounted on, perform 6224Sbill * the indicated indirection. 6324Sbill * In all cases, a pointer to a locked 6424Sbill * inode structure is returned. 6524Sbill * 6624Sbill * printf warning: no inodes -- if the inode 6724Sbill * structure is full 6824Sbill * panic: no imt -- if the mounted file 6924Sbill * system is not in the mount table. 7024Sbill * "cannot happen" 7124Sbill */ 7224Sbill struct inode * 7324Sbill iget(dev, ino) 7424Sbill dev_t dev; 7524Sbill ino_t ino; 7624Sbill { 7724Sbill register struct inode *ip; 7824Sbill register struct mount *mp; 7924Sbill register struct buf *bp; 8024Sbill register struct dinode *dp; 8124Sbill register int slot; 8224Sbill 8324Sbill loop: 8424Sbill slot = INOHASH(dev, ino); 8524Sbill ip = &inode[inohash[slot]]; 8624Sbill while (ip != &inode[-1]) { 8724Sbill if(ino == ip->i_number && dev == ip->i_dev) { 8824Sbill if((ip->i_flag&ILOCK) != 0) { 8924Sbill ip->i_flag |= IWANT; 9024Sbill sleep((caddr_t)ip, PINOD); 9124Sbill goto loop; 9224Sbill } 9324Sbill if((ip->i_flag&IMOUNT) != 0) { 9424Sbill for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 9524Sbill if(mp->m_inodp == ip) { 9624Sbill dev = mp->m_dev; 9724Sbill ino = ROOTINO; 9824Sbill goto loop; 9924Sbill } 10024Sbill panic("no imt"); 10124Sbill } 10224Sbill ip->i_count++; 10324Sbill ip->i_flag |= ILOCK; 10424Sbill return(ip); 10524Sbill } 10624Sbill ip = &inode[ip->i_hlink]; 10724Sbill } 10824Sbill if(ifreel < 0) { 10924Sbill printf("Inode table overflow\n"); 11024Sbill u.u_error = ENFILE; 11124Sbill return(NULL); 11224Sbill } 11324Sbill ip = &inode[ifreel]; 11424Sbill ifreel = ip->i_hlink; 11524Sbill ip->i_hlink = inohash[slot]; 11624Sbill inohash[slot] = ip - inode; 11724Sbill ip->i_dev = dev; 11824Sbill ip->i_number = ino; 11924Sbill ip->i_flag = ILOCK; 12024Sbill ip->i_count++; 12124Sbill ip->i_un.i_lastr = 0; 12224Sbill bp = bread(dev, itod(ino)); 12324Sbill /* 12424Sbill * Check I/O errors 12524Sbill */ 12624Sbill if((bp->b_flags&B_ERROR) != 0) { 12724Sbill brelse(bp); 12824Sbill iput(ip); 12924Sbill return(NULL); 13024Sbill } 13124Sbill dp = bp->b_un.b_dino; 13224Sbill dp += itoo(ino); 13324Sbill iexpand(ip, dp); 13424Sbill brelse(bp); 13524Sbill return(ip); 13624Sbill } 13724Sbill 13824Sbill iexpand(ip, dp) 13924Sbill register struct inode *ip; 14024Sbill register struct dinode *dp; 14124Sbill { 14224Sbill register char *p1, *p2; 14324Sbill register int i; 14424Sbill 14524Sbill ip->i_mode = dp->di_mode; 14624Sbill ip->i_nlink = dp->di_nlink; 14724Sbill ip->i_uid = dp->di_uid; 14824Sbill ip->i_gid = dp->di_gid; 14924Sbill ip->i_size = dp->di_size; 15024Sbill p1 = (char *)ip->i_un.i_addr; 15124Sbill p2 = (char *)dp->di_addr; 15224Sbill for(i=0; i<NADDR; i++) { 15324Sbill *p1++ = *p2++; 15424Sbill *p1++ = *p2++; 15524Sbill *p1++ = *p2++; 15624Sbill *p1++ = 0; 15724Sbill } 15824Sbill } 15924Sbill 16024Sbill /* 16124Sbill * Decrement reference count of 16224Sbill * an inode structure. 16324Sbill * On the last reference, 16424Sbill * write the inode out and if necessary, 16524Sbill * truncate and deallocate the file. 16624Sbill */ 16724Sbill iput(ip) 16824Sbill register struct inode *ip; 16924Sbill { 17024Sbill register int i, x; 17124Sbill register struct inode *jp; 17224Sbill 17324Sbill if(ip->i_count == 1) { 17424Sbill ip->i_flag |= ILOCK; 17524Sbill if(ip->i_nlink <= 0) { 17624Sbill itrunc(ip); 17724Sbill ip->i_mode = 0; 17824Sbill ip->i_flag |= IUPD|ICHG; 17924Sbill ifree(ip->i_dev, ip->i_number); 18024Sbill } 181*1203Sbill IUPDAT(ip, &time, &time, 0); 18224Sbill prele(ip); 18324Sbill i = INOHASH(ip->i_dev, ip->i_number); 18424Sbill x = ip - inode; 18524Sbill if (inohash[i] == x) { 18624Sbill inohash[i] = ip->i_hlink; 18724Sbill } else { 18824Sbill for (jp = &inode[inohash[i]]; jp != &inode[-1]; 18924Sbill jp = &inode[jp->i_hlink]) 19024Sbill if (jp->i_hlink == x) { 19124Sbill jp->i_hlink = ip->i_hlink; 19224Sbill goto done; 19324Sbill } 19424Sbill panic("iput"); 19524Sbill } 19624Sbill done: 19724Sbill ip->i_hlink = ifreel; 19824Sbill ifreel = x; 19924Sbill ip->i_flag = 0; 20024Sbill ip->i_number = 0; 20124Sbill } else 20224Sbill prele(ip); 20324Sbill ip->i_count--; 20424Sbill } 20524Sbill 20624Sbill /* 20724Sbill * Check accessed and update flags on 20824Sbill * an inode structure. 20924Sbill * If any is on, update the inode 21024Sbill * with the current time. 211*1203Sbill * If waitfor is given, then must insure 212*1203Sbill * i/o order so wait for write to complete. 21324Sbill */ 214*1203Sbill iupdat(ip, ta, tm, waitfor) 21524Sbill register struct inode *ip; 21624Sbill time_t *ta, *tm; 217*1203Sbill int waitfor; 21824Sbill { 21924Sbill register struct buf *bp; 22024Sbill struct dinode *dp; 22124Sbill register char *p1, *p2; 22224Sbill register int i; 22324Sbill 22424Sbill if((ip->i_flag&(IUPD|IACC|ICHG)) != 0) { 22524Sbill if(getfs(ip->i_dev)->s_ronly) 22624Sbill return; 22724Sbill bp = bread(ip->i_dev, itod(ip->i_number)); 22824Sbill if (bp->b_flags & B_ERROR) { 22924Sbill brelse(bp); 23024Sbill return; 23124Sbill } 23224Sbill dp = bp->b_un.b_dino; 23324Sbill dp += itoo(ip->i_number); 23424Sbill dp->di_mode = ip->i_mode; 23524Sbill dp->di_nlink = ip->i_nlink; 23624Sbill dp->di_uid = ip->i_uid; 23724Sbill dp->di_gid = ip->i_gid; 23824Sbill dp->di_size = ip->i_size; 23924Sbill p1 = (char *)dp->di_addr; 24024Sbill p2 = (char *)ip->i_un.i_addr; 24124Sbill for(i=0; i<NADDR; i++) { 24224Sbill *p1++ = *p2++; 24324Sbill *p1++ = *p2++; 24424Sbill *p1++ = *p2++; 24524Sbill if(*p2++ != 0 && (ip->i_mode&IFMT)!=IFMPC 24624Sbill && (ip->i_mode&IFMT)!=IFMPB) 24724Sbill printf("iaddress > 2^24\n"); 24824Sbill } 24924Sbill if(ip->i_flag&IACC) 25024Sbill dp->di_atime = *ta; 25124Sbill if(ip->i_flag&IUPD) 25224Sbill dp->di_mtime = *tm; 25324Sbill if(ip->i_flag&ICHG) 25424Sbill dp->di_ctime = time; 25524Sbill ip->i_flag &= ~(IUPD|IACC|ICHG); 256*1203Sbill if (waitfor) 257*1203Sbill bwrite(bp); 258*1203Sbill else 259*1203Sbill bdwrite(bp); 26024Sbill } 26124Sbill } 26224Sbill 26324Sbill /* 26424Sbill * Free all the disk blocks associated 26524Sbill * with the specified inode structure. 26624Sbill * The blocks of the file are removed 26724Sbill * in reverse order. This FILO 26824Sbill * algorithm will tend to maintain 26924Sbill * a contiguous free list much longer 27024Sbill * than FIFO. 27124Sbill */ 27224Sbill itrunc(ip) 27324Sbill register struct inode *ip; 27424Sbill { 27524Sbill register i; 27624Sbill dev_t dev; 27724Sbill daddr_t bn; 278*1203Sbill struct inode itmp; 27924Sbill 28024Sbill if (ip->i_vfdcnt) 28124Sbill panic("itrunc"); 28224Sbill i = ip->i_mode & IFMT; 28324Sbill if (i!=IFREG && i!=IFDIR) 28424Sbill return; 285*1203Sbill 286*1203Sbill /* 287*1203Sbill * Clean inode on disk before freeing blocks 288*1203Sbill * to insure no duplicates if system crashes. 289*1203Sbill */ 290*1203Sbill itmp = *ip; 291*1203Sbill itmp.i_size = 0; 292*1203Sbill for (i = 0; i < NADDR; i++) 293*1203Sbill itmp.i_un.i_addr[i] = 0; 294*1203Sbill itmp.i_flag |= ICHG|IUPD; 295*1203Sbill iupdat(&itmp, &time, &time, 1); 296*1203Sbill ip->i_flag &= ~(IUPD|IACC|ICHG); 297*1203Sbill 298*1203Sbill /* 299*1203Sbill * Now return blocks to free list... if machine 300*1203Sbill * crashes, they will be harmless MISSING blocks. 301*1203Sbill */ 30224Sbill dev = ip->i_dev; 30324Sbill for(i=NADDR-1; i>=0; i--) { 30424Sbill bn = ip->i_un.i_addr[i]; 30524Sbill if(bn == (daddr_t)0) 30624Sbill continue; 30724Sbill ip->i_un.i_addr[i] = (daddr_t)0; 30824Sbill switch(i) { 30924Sbill 31024Sbill default: 31124Sbill free(dev, bn); 31224Sbill break; 31324Sbill 31424Sbill case NADDR-3: 31524Sbill tloop(dev, bn, 0, 0); 31624Sbill break; 31724Sbill 31824Sbill case NADDR-2: 31924Sbill tloop(dev, bn, 1, 0); 32024Sbill break; 32124Sbill 32224Sbill case NADDR-1: 32324Sbill tloop(dev, bn, 1, 1); 32424Sbill } 32524Sbill } 32624Sbill ip->i_size = 0; 327*1203Sbill /* 328*1203Sbill * Inode was written and flags updated above. 329*1203Sbill * No need to modify flags here. 330*1203Sbill */ 33124Sbill } 33224Sbill 33324Sbill tloop(dev, bn, f1, f2) 33424Sbill dev_t dev; 33524Sbill daddr_t bn; 33624Sbill { 33724Sbill register i; 33824Sbill register struct buf *bp; 33924Sbill register daddr_t *bap; 34024Sbill daddr_t nb; 34124Sbill 34224Sbill bp = NULL; 34324Sbill for(i=NINDIR-1; i>=0; i--) { 34424Sbill if(bp == NULL) { 34524Sbill bp = bread(dev, bn); 34624Sbill if (bp->b_flags & B_ERROR) { 34724Sbill brelse(bp); 34824Sbill return; 34924Sbill } 35024Sbill bap = bp->b_un.b_daddr; 35124Sbill } 35224Sbill nb = bap[i]; 35324Sbill if(nb == (daddr_t)0) 35424Sbill continue; 35524Sbill if(f1) { 35624Sbill brelse(bp); 35724Sbill bp = NULL; 35824Sbill tloop(dev, nb, f2, 0); 35924Sbill } else 36024Sbill free(dev, nb); 36124Sbill } 36224Sbill if(bp != NULL) 36324Sbill brelse(bp); 36424Sbill free(dev, bn); 36524Sbill } 36624Sbill 36724Sbill /* 36824Sbill * Make a new file. 36924Sbill */ 37024Sbill struct inode * 37124Sbill maknode(mode) 37224Sbill { 37324Sbill register struct inode *ip; 37424Sbill 37524Sbill ip = ialloc(u.u_pdir->i_dev); 37624Sbill if(ip == NULL) { 37724Sbill iput(u.u_pdir); 37824Sbill return(NULL); 37924Sbill } 38024Sbill ip->i_flag |= IACC|IUPD|ICHG; 38124Sbill if((mode&IFMT) == 0) 38224Sbill mode |= IFREG; 38324Sbill ip->i_mode = mode & ~u.u_cmask; 38424Sbill ip->i_nlink = 1; 38524Sbill ip->i_uid = u.u_uid; 38624Sbill ip->i_gid = u.u_gid; 387*1203Sbill 388*1203Sbill /* 389*1203Sbill * Make sure inode goes to disk before directory entry. 390*1203Sbill */ 391*1203Sbill iupdat(ip, &time, &time, 1); 392*1203Sbill 39324Sbill wdir(ip); 39424Sbill return(ip); 39524Sbill } 39624Sbill 39724Sbill /* 39824Sbill * Write a directory entry with 39924Sbill * parameters left as side effects 40024Sbill * to a call to namei. 40124Sbill */ 40224Sbill wdir(ip) 40324Sbill struct inode *ip; 40424Sbill { 40524Sbill 40624Sbill u.u_dent.d_ino = ip->i_number; 40724Sbill bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_dent.d_name, DIRSIZ); 40824Sbill u.u_count = sizeof(struct direct); 40924Sbill u.u_segflg = 1; 41024Sbill u.u_base = (caddr_t)&u.u_dent; 41124Sbill writei(u.u_pdir); 41224Sbill iput(u.u_pdir); 41324Sbill } 414