LSX/sys/alloc.c
#
/*
* Copyright 1975 Bell Telephone Laboratories Inc
*/
#include "param.h"
#include "systm.h"
#include "filsys.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;
bp = bread(ROOTDEV, 1);
cp = getblk(NODEV);
if(u.u_error)
panic();
bcopy(bp->b_addr, cp->b_addr, 256);
brelse(bp);
mount[0].m_bufp = cp;
mount[0].m_dev = ROOTDEV;
cp = cp->b_addr;
time[0] = cp->s_time[0];
time[1] = cp->s_time[1];
}
/*
* mount user file system
*/
minit()
{
register *cp, *bp, *ip;
bp = bread(MNTDEV, 1);
if(bp->b_flags&B_ERROR)
goto nomount;
u.u_dirp = "/usr";
ip = namei(0);
mount[1].m_inodp = ip;
mount[1].m_dev = MNTDEV;
mount[1].m_bufp = cp = getblk(NODEV);
bcopy(bp->b_addr, cp->b_addr, 256);
ip->i_flag =| IMOUNT;
nomount:
brelse(bp);
}
#ifdef CONTIG
alloc(dev)
{
register bno;
register *fp, *bp;
fp = getfs(dev);
for(bno = fp->s_isize+2; bno < fp->s_fsize; bno++) {
if(fp->s_bmap[bno>>3]&(1<<(bno&07))) {
fp->s_bmap[bno>>3] =& ~(1<<(bno&07));
bp = getblk(dev, bno);
clrbuf(bp);
fp->s_fmod = 1;
return(bp);
}
}
u.u_error = ENOSPC;
return(0);
}
free(dev, bno)
{
register *fp;
fp = getfs(dev);
fp->s_bmap[bno>>3] =| (1<<(bno&07));
}
#endif
#ifndef CONTIG
/*
* 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);
if(fp->s_nfree <= 0)
goto nospace;
bno = fp->s_free[--fp->s_nfree];
if(bno == 0)
goto nospace;
if(fp->s_nfree <= 0) {
bp = bread(dev, bno);
ip = bp->b_addr;
fp->s_nfree = *ip++;
bcopy(ip, fp->s_free, 100);
brelse(bp);
}
if(bno < fp->s_isize+2 || bno >= fp->s_fsize)
panic();
bp = getblk(dev, bno);
clrbuf(bp);
fp->s_fmod = 1;
return(bp);
nospace:
fp->s_nfree = 0;
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);
if(bno < fp->s_isize+2 || bno >= fp->s_fsize)
panic();
if(fp->s_nfree <= 0) {
fp->s_nfree = 1;
fp->s_free[0] = 0;
}
if(fp->s_nfree >= 100) {
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_free[fp->s_nfree++] = bno;
fp->s_fmod = 1;
}
#endif
/*
* 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);
#ifdef CONTIG
for(ino = 1; ino < fp->s_isize*16; ino++) {
if((fp->s_imap[ino>>3]&(1<<(ino&07))) == 0)
continue;
ip = iget(dev, ino+1);
#endif
#ifndef CONTIG
loop:
if(fp->s_ninode > 0) {
ino = fp->s_inode[--fp->s_ninode];
ip = iget(dev, ino);
#endif
if (ip==NULL)
return(NULL);
if(ip->i_mode == 0) {
#ifdef CONTIG
fp->s_imap[ino>>3] =& ~(1<<(ino&07));
#endif
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);
#ifndef CONTIG
goto loop;
#endif
}
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);
#ifdef CONTIG
fp->s_imap[(ino-1)>>3] =| (1<<((ino-1)&07));
#endif
#ifndef CONTIG
fp->s_inode[fp->s_ninode++] = ino;
#endif
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.
* panic: no fs -- the device is not mounted.
* this "cannot happen"
*/
getfs(dev)
{
register struct mount *p;
for(p = &mount[0]; p < &mount[NMOUNT]; p++)
if(p->m_bufp != NULL && p->m_dev == dev) {
p = p->m_bufp->b_addr;
return(p);
}
panic();
}
/*
* 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;
for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
if(mp->m_bufp != NULL) {
ip = mp->m_bufp->b_addr;
if(ip->s_fmod == 0)
continue;
bp = getblk(mp->m_dev, 1);
ip->s_time[0] = time[0];
ip->s_time[1] = time[1];
ip->s_fmod = 0;
bcopy(ip, bp->b_addr, 256);
bwrite(bp);
}
for(ip = &inode[0]; ip < &inode[NINODE]; ip++)
iupdat(ip);
bflush(NODEV);
}