Add original unix v6
This commit is contained in:
+314
@@ -0,0 +1,314 @@
|
||||
#
|
||||
/*
|
||||
*/
|
||||
|
||||
#include "../param.h"
|
||||
#include "../systm.h"
|
||||
#include "../filsys.h"
|
||||
#include "../conf.h"
|
||||
#include "../buf.h"
|
||||
#include "../inode.h"
|
||||
#include "../user.h"
|
||||
|
||||
/*
|
||||
* iinit is called once (from main)
|
||||
* very early in initialization.
|
||||
* It reads the root's super block
|
||||
* and initializes the current date
|
||||
* from the last modified date.
|
||||
*
|
||||
* panic: iinit -- cannot read the super
|
||||
* block. Usually because of an IO error.
|
||||
*/
|
||||
iinit()
|
||||
{
|
||||
register *cp, *bp;
|
||||
|
||||
(*bdevsw[rootdev.d_major].d_open)(rootdev, 1);
|
||||
bp = bread(rootdev, 1);
|
||||
cp = getblk(NODEV);
|
||||
if(u.u_error)
|
||||
panic("iinit");
|
||||
bcopy(bp->b_addr, cp->b_addr, 256);
|
||||
brelse(bp);
|
||||
mount[0].m_bufp = cp;
|
||||
mount[0].m_dev = rootdev;
|
||||
cp = cp->b_addr;
|
||||
cp->s_flock = 0;
|
||||
cp->s_ilock = 0;
|
||||
cp->s_ronly = 0;
|
||||
time[0] = cp->s_time[0];
|
||||
time[1] = cp->s_time[1];
|
||||
}
|
||||
|
||||
/*
|
||||
* alloc will obtain the next available
|
||||
* free disk block from the free list of
|
||||
* the specified device.
|
||||
* The super block has up to 100 remembered
|
||||
* free blocks; the last of these is read to
|
||||
* obtain 100 more . . .
|
||||
*
|
||||
* no space on dev x/y -- when
|
||||
* the free list is exhausted.
|
||||
*/
|
||||
alloc(dev)
|
||||
{
|
||||
int bno;
|
||||
register *bp, *ip, *fp;
|
||||
|
||||
fp = getfs(dev);
|
||||
while(fp->s_flock)
|
||||
sleep(&fp->s_flock, PINOD);
|
||||
do {
|
||||
if(fp->s_nfree <= 0)
|
||||
goto nospace;
|
||||
bno = fp->s_free[--fp->s_nfree];
|
||||
if(bno == 0)
|
||||
goto nospace;
|
||||
} while (badblock(fp, bno, dev));
|
||||
if(fp->s_nfree <= 0) {
|
||||
fp->s_flock++;
|
||||
bp = bread(dev, bno);
|
||||
ip = bp->b_addr;
|
||||
fp->s_nfree = *ip++;
|
||||
bcopy(ip, fp->s_free, 100);
|
||||
brelse(bp);
|
||||
fp->s_flock = 0;
|
||||
wakeup(&fp->s_flock);
|
||||
}
|
||||
bp = getblk(dev, bno);
|
||||
clrbuf(bp);
|
||||
fp->s_fmod = 1;
|
||||
return(bp);
|
||||
|
||||
nospace:
|
||||
fp->s_nfree = 0;
|
||||
prdev("no space", dev);
|
||||
u.u_error = ENOSPC;
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* place the specified disk block
|
||||
* back on the free list of the
|
||||
* specified device.
|
||||
*/
|
||||
free(dev, bno)
|
||||
{
|
||||
register *fp, *bp, *ip;
|
||||
|
||||
fp = getfs(dev);
|
||||
fp->s_fmod = 1;
|
||||
while(fp->s_flock)
|
||||
sleep(&fp->s_flock, PINOD);
|
||||
if (badblock(fp, bno, dev))
|
||||
return;
|
||||
if(fp->s_nfree <= 0) {
|
||||
fp->s_nfree = 1;
|
||||
fp->s_free[0] = 0;
|
||||
}
|
||||
if(fp->s_nfree >= 100) {
|
||||
fp->s_flock++;
|
||||
bp = getblk(dev, bno);
|
||||
ip = bp->b_addr;
|
||||
*ip++ = fp->s_nfree;
|
||||
bcopy(fp->s_free, ip, 100);
|
||||
fp->s_nfree = 0;
|
||||
bwrite(bp);
|
||||
fp->s_flock = 0;
|
||||
wakeup(&fp->s_flock);
|
||||
}
|
||||
fp->s_free[fp->s_nfree++] = bno;
|
||||
fp->s_fmod = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that a block number is in the
|
||||
* range between the I list and the size
|
||||
* of the device.
|
||||
* This is used mainly to check that a
|
||||
* garbage file system has not been mounted.
|
||||
*
|
||||
* bad block on dev x/y -- not in range
|
||||
*/
|
||||
badblock(afp, abn, dev)
|
||||
{
|
||||
register struct filsys *fp;
|
||||
register char *bn;
|
||||
|
||||
fp = afp;
|
||||
bn = abn;
|
||||
if (bn < fp->s_isize+2 || bn >= fp->s_fsize) {
|
||||
prdev("bad block", dev);
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate an unused I node
|
||||
* on the specified device.
|
||||
* Used with file creation.
|
||||
* The algorithm keeps up to
|
||||
* 100 spare I nodes in the
|
||||
* super block. When this runs out,
|
||||
* a linear search through the
|
||||
* I list is instituted to pick
|
||||
* up 100 more.
|
||||
*/
|
||||
ialloc(dev)
|
||||
{
|
||||
register *fp, *bp, *ip;
|
||||
int i, j, k, ino;
|
||||
|
||||
fp = getfs(dev);
|
||||
while(fp->s_ilock)
|
||||
sleep(&fp->s_ilock, PINOD);
|
||||
loop:
|
||||
if(fp->s_ninode > 0) {
|
||||
ino = fp->s_inode[--fp->s_ninode];
|
||||
ip = iget(dev, ino);
|
||||
if (ip==NULL)
|
||||
return(NULL);
|
||||
if(ip->i_mode == 0) {
|
||||
for(bp = &ip->i_mode; bp < &ip->i_addr[8];)
|
||||
*bp++ = 0;
|
||||
fp->s_fmod = 1;
|
||||
return(ip);
|
||||
}
|
||||
/*
|
||||
* Inode was allocated after all.
|
||||
* Look some more.
|
||||
*/
|
||||
iput(ip);
|
||||
goto loop;
|
||||
}
|
||||
fp->s_ilock++;
|
||||
ino = 0;
|
||||
for(i=0; i<fp->s_isize; i++) {
|
||||
bp = bread(dev, i+2);
|
||||
ip = bp->b_addr;
|
||||
for(j=0; j<256; j=+16) {
|
||||
ino++;
|
||||
if(ip[j] != 0)
|
||||
continue;
|
||||
for(k=0; k<NINODE; k++)
|
||||
if(dev==inode[k].i_dev && ino==inode[k].i_number)
|
||||
goto cont;
|
||||
fp->s_inode[fp->s_ninode++] = ino;
|
||||
if(fp->s_ninode >= 100)
|
||||
break;
|
||||
cont:;
|
||||
}
|
||||
brelse(bp);
|
||||
if(fp->s_ninode >= 100)
|
||||
break;
|
||||
}
|
||||
fp->s_ilock = 0;
|
||||
wakeup(&fp->s_ilock);
|
||||
if (fp->s_ninode > 0)
|
||||
goto loop;
|
||||
prdev("Out of inodes", dev);
|
||||
u.u_error = ENOSPC;
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the specified I node
|
||||
* on the specified device.
|
||||
* The algorithm stores up
|
||||
* to 100 I nodes in the super
|
||||
* block and throws away any more.
|
||||
*/
|
||||
ifree(dev, ino)
|
||||
{
|
||||
register *fp;
|
||||
|
||||
fp = getfs(dev);
|
||||
if(fp->s_ilock)
|
||||
return;
|
||||
if(fp->s_ninode >= 100)
|
||||
return;
|
||||
fp->s_inode[fp->s_ninode++] = ino;
|
||||
fp->s_fmod = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* getfs maps a device number into
|
||||
* a pointer to the incore super
|
||||
* block.
|
||||
* The algorithm is a linear
|
||||
* search through the mount table.
|
||||
* A consistency check of the
|
||||
* in core free-block and i-node
|
||||
* counts.
|
||||
*
|
||||
* bad count on dev x/y -- the count
|
||||
* check failed. At this point, all
|
||||
* the counts are zeroed which will
|
||||
* almost certainly lead to "no space"
|
||||
* diagnostic
|
||||
* panic: no fs -- the device is not mounted.
|
||||
* this "cannot happen"
|
||||
*/
|
||||
getfs(dev)
|
||||
{
|
||||
register struct mount *p;
|
||||
register char *n1, *n2;
|
||||
|
||||
for(p = &mount[0]; p < &mount[NMOUNT]; p++)
|
||||
if(p->m_bufp != NULL && p->m_dev == dev) {
|
||||
p = p->m_bufp->b_addr;
|
||||
n1 = p->s_nfree;
|
||||
n2 = p->s_ninode;
|
||||
if(n1 > 100 || n2 > 100) {
|
||||
prdev("bad count", dev);
|
||||
p->s_nfree = 0;
|
||||
p->s_ninode = 0;
|
||||
}
|
||||
return(p);
|
||||
}
|
||||
panic("no fs");
|
||||
}
|
||||
|
||||
/*
|
||||
* update is the internal name of
|
||||
* 'sync'. It goes through the disk
|
||||
* queues to initiate sandbagged IO;
|
||||
* goes through the I nodes to write
|
||||
* modified nodes; and it goes through
|
||||
* the mount table to initiate modified
|
||||
* super blocks.
|
||||
*/
|
||||
update()
|
||||
{
|
||||
register struct inode *ip;
|
||||
register struct mount *mp;
|
||||
register *bp;
|
||||
|
||||
if(updlock)
|
||||
return;
|
||||
updlock++;
|
||||
for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
|
||||
if(mp->m_bufp != NULL) {
|
||||
ip = mp->m_bufp->b_addr;
|
||||
if(ip->s_fmod==0 || ip->s_ilock!=0 ||
|
||||
ip->s_flock!=0 || ip->s_ronly!=0)
|
||||
continue;
|
||||
bp = getblk(mp->m_dev, 1);
|
||||
ip->s_fmod = 0;
|
||||
ip->s_time[0] = time[0];
|
||||
ip->s_time[1] = time[1];
|
||||
bcopy(ip, bp->b_addr, 256);
|
||||
bwrite(bp);
|
||||
}
|
||||
for(ip = &inode[0]; ip < &inode[NINODE]; ip++)
|
||||
if((ip->i_flag&ILOCK) == 0) {
|
||||
ip->i_flag =| ILOCK;
|
||||
iupdat(ip, time);
|
||||
prele(ip);
|
||||
}
|
||||
updlock = 0;
|
||||
bflush(NODEV);
|
||||
}
|
||||
Reference in New Issue
Block a user