P8000/WEGA/src/uts/sys/iget.c

358 lines
6.6 KiB
C

/******************************************************************************
*******************************************************************************
W E G A - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1988
KERN 3.2 Modul: iget.c
Bearbeiter:
Datum: $D$
Version: $R$
*******************************************************************************
******************************************************************************/
#include <sys/param.h>
#include <sys/inode.h>
char igetwstr[]="@[$]iget.c Rev : 4.1 08/27/83 11:54:46";
#include <sys/sysinfo.h>
#include <sys/systm.h>
#include <sys/mount.h>
#include <sys/dir.h>
#include <sys/ino.h>
#include <sys/filsys.h>
#include <sys/conf.h>
#include <sys/buf.h>
#include <sys/mmu.h>
#include <sys/s.out.h>
#include <sys/user.h>
extern int Ninode;
extern int Nmount;
struct inode *ihash[INOHSZ] = 0 ;
struct inode *ifreelist;
ihinit()
{
register i;
register struct inode *ip;
ifreelist = inode;
for(ip=inode; ip < &inode[Ninode-1]; ip++)
ip->i_link = (struct inode *) ip+1;
ip->i_link = (struct inode *) 0;
for(i=0;i< INOHSZ;i++)
ihash[i] = (struct inode *) 0;
}
struct inode *
ifind(idev,inum)
register dev_t idev;
register ino_t inum;
{
register struct inode *ip;
ip=ihash[INOHASH(idev,inum)];
while(ip !=(struct inode *)0) {
if(inum == ip->i_number && idev == ip->i_dev)
return(ip);
ip=ip->i_link;
}
return((struct inode *)0);
}
struct inode *
iget(dev, ino)
register dev_t dev;
register ino_t ino;
{
register struct inode *ip;
register struct mount *mp;
register h_index;
register struct buf *bp;
register struct dinode *dp;
int i;
sysinfo.iget++;
loop:
h_index = INOHASH(dev, ino);
for(ip=ihash[h_index];ip!=(struct inode *) 0;ip=ip->i_link) {
if(ino == ip->i_number && dev == ip->i_dev) {
while((ip->i_flag & ILOCK) != 0) {
ip->i_flag |= IWANT;
sleep((caddr_t)ip, PINOD);
if(ino == ip->i_number && dev == ip->i_dev)
continue;
goto loop;
}
if((ip->i_flag & IMOUNT) !=0) {
for(mp = &mount[0]; mp < &mount[Nmount]; mp++)
if(mp->m_inodp == ip) {
dev = mp->m_dev;
ino = ROOTINO;
goto loop;
}
panic("no imt");
}
ip->i_count++;
ip->i_flag |= ILOCK;
return(ip);
}
}
if(ifreelist == NULL) {
printf("Inode table overflow\n");
u.u_error = ENFILE;
return(NULL);
}
ip=ifreelist;
ifreelist=ip->i_link;
ip->i_link=ihash[h_index];
ihash[h_index]=ip;
ip->i_dev = dev;
ip->i_number = ino;
ip->i_flag = ILOCK;
ip->i_count++;
ip->i_blks.i_l = (daddr_t) 0;
bp = bread(dev, itod(ino));
if((bp->b_flags&B_ERROR) != 0) {
brelse(bp);
iput(ip);
return(NULL);
}
dp = bp->b_un.b_dino;
dp += itoo(ino);
iexpand(ip, dp);
brelse(bp);
return(ip);
}
iexpand(ip, dp)
register struct inode *ip;
register struct dinode *dp;
{
ip->i_mode = dp->di_mode;
ip->i_nlink = dp->di_nlink;
ip->i_uid = dp->di_uid;
ip->i_gid = dp->di_gid;
ip->i_size = dp->di_size;
l3tol((char *) ip->i_blks.i_p.i_a, (char *)dp->di_addr, NADDR);
ip->i_locklist = 0;
}
iput(ip)
register struct inode *ip;
{
register struct inode *ip1;
register h_index, i_unbenutzt;
long unbenutzt;
if(ip->i_count == 1) {
ip->i_flag |= ILOCK;
if(ip->i_nlink <= 0) {
itrunc(ip);
ip->i_mode = 0;
ip->i_flag |= IUPD|ICHG;
ifree(ip->i_dev, ip->i_number);
}
iupdat(ip, &time, &time);
prele(ip);
h_index = INOHASH(ip->i_dev, ip->i_number);
if(ip == ihash[h_index])
ihash[h_index] = ip->i_link;
else {
ip1 = ihash[h_index];
for(;ip1;ip1=ip1->i_link)
if(ip == ip1->i_link) {
ip1->i_link = ip->i_link;
goto m1;
}
panic("iput");
}
m1:
ip->i_link = ifreelist;
ifreelist = ip;
ip ->i_flag= NULL;
ip->i_number = 0;
} else
prele(ip);
ip->i_count--;
}
iupdat(ip, ta, tm)
register struct inode *ip;
time_t *ta, *tm;
{
register struct buf *bp;
register struct dinode *dp;
char *di_addr;
char *i_f;
unsigned i;
if((ip->i_flag&(IUPD|IACC|ICHG)) == 0)
return;
if(getfs(ip->i_dev)->s_ronly) {
if(ip->i_flag & (IUPD | ICHG))
u.u_error = EROFS;
ip->i_flag &= ~(IUPD | ICHG | IACC);
return;
}
bp = bread(ip->i_dev, itod(ip->i_number));
if (bp->b_flags & B_ERROR) {
brelse(bp);
return;
}
dp = bp->b_un.b_dino;
dp += itoo(ip->i_number);
dp->di_mode = ip->i_mode;
dp->di_nlink = ip->i_nlink;
dp->di_uid = ip->i_uid;
dp->di_gid = ip->i_gid;
dp->di_size = ip->i_size;
if((ip->i_mode & IFMT) == IFIFO) {
di_addr = (char *) dp->di_addr;
i_f = (char *) ip->i_faddr;
i=0;
do {
*di_addr++ = *i_f++;
if( * i_f++)
printf("iaddress > 2^24\n");
*di_addr++ = *i_f++;
*di_addr++ = *i_f++;
}while(++i < NFADDR);
for(;i<13;i++) {
*di_addr++ = 0;
*di_addr++ = 0;
*di_addr++ = 0;
}
} else
ltol3((char *)dp->di_addr, (char *)ip->i_addr, NADDR);
if(ip->i_flag&IACC)
dp->di_atime = *ta;
if(ip->i_flag&IUPD)
dp->di_mtime = *tm;
if(ip->i_flag&ICHG)
dp->di_ctime = time;
ip->i_flag &= ~(IUPD|IACC|ICHG);
bdwrite(bp);
}
itrunc(ip)
register struct inode *ip;
{
register i;
register dev_t dev;
register daddr_t bn;
i = ip->i_mode & IFMT;
if (i!=IFREG && i!=IFDIR)
return;
dev = ip->i_dev;
for(i=NADDR-1; i>=0; i--) {
bn = ip->i_addr[i];
if(bn == (daddr_t)0)
continue;
ip->i_addr[i] = (daddr_t)0;
switch(i) {
default:
free(dev, bn);
break;
case NADDR-3:
tloop(dev, bn, 0, 0);
break;
case NADDR-2:
tloop(dev, bn, 1, 0);
break;
case NADDR-1:
tloop(dev, bn, 1, 1);
}
}
ip->i_size = 0;
ip->i_flag |= ICHG|IUPD;
}
tloop(dev, bn, f1, f2)
dev_t dev;
daddr_t bn;
{
register i;
register struct buf *bp;
register daddr_t *bap;
int unbenutzt, u2, u3, u4, u5;
daddr_t nb;
bp = NULL;
for(i=NINDIR-1; i>=0; i--) {
if(bp == NULL) {
bp = bread(dev, bn);
if (bp->b_flags & B_ERROR) {
brelse(bp);
return;
}
bap = bp->b_un.b_daddr;
}
nb = bap[i];
if(nb == (daddr_t)0)
continue;
if(f1) {
brelse(bp);
bp = NULL;
tloop(dev, nb, f2, 0);
} else
free(dev, nb);
}
if(bp != NULL)
brelse(bp);
free(dev, bn);
}
struct inode *
maknode(mode)
{
register struct inode *ip;
struct inode *ip1;
ip = ialloc(u.u_pdir->i_dev);
if(ip == NULL) {
iput(u.u_pdir);
return(NULL);
}
ip->i_flag |= IACC|IUPD|ICHG;
if((mode&IFMT) == 0)
mode |= IFREG;
ip->i_mode = mode & ~u.u_cmask;
ip->i_nlink = 1;
ip->i_uid = u.u_uid;
ip->i_gid = u.u_gid;
wdir(ip);
return(ip);
}
wdir(ip)
struct inode *ip;
{
if (u.u_pdir->i_nlink <= 0) {
u.u_error = ENOTDIR;
} else {
u.u_dent.d_ino = ip->i_number;
bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_dent.d_name, DIRSIZ);
u.u_count = sizeof(struct direct);
u.u_segflg = 1;
u.u_base.l= (caddr_t) &u.u_dent;
writei(u.u_pdir);
u.u_segflg = 0;
}
iput(u.u_pdir);
}