Ausam/sys/ken/alloc.c
#
/*
*/
#include "../defines.h"
#include "../param.h"
#include "../file.h"
#ifdef AUSAML
#include "../lnode.h"
#include "../proc.h"
#endif AUSAML
#include "../systm.h"
#include "../filsys.h"
#include "../conf.h"
#include "../buf.h"
#include "../inode.h"
#include "../user.h"
#ifndef ONCE
#include "../iinit.h"
#endif
/*
* 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.
*/
#ifndef MAPPED_BUFFERS
alloc(dev)
{
unsigned bno; /* fix000 */
register *bp, *ip, *fp;
#ifdef AUSAML
if( (fp = u.u_procp->p_lnode) && (fp->l_flags & DLIMIT) ) {
/* no further allocation for this user */
u.u_error = EDISKLIM;
return( NULL );
}
#endif AUSAML
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;
#ifdef UPRINTS
uprints( "\nwrite error - device full\n" );
#endif
#ifdef COOL_NO_SPACE
#ifndef DELAY
sleep( &lbolt , PRIBIO );
#endif
#ifdef DELAY
delay( 5*HZ ); /* hang 5 */
#endif
#endif
return(NULL);
}
#else MAPPED_BUFFERS
/*
* ka5 must be preserved
*/
alloc(dev)
{
unsigned bno; /* fix000 */
register *bp;
#ifdef MAPPED_BUFFERS
int ka5sav1;
#endif MAPPED_BUFFERS
#ifdef AUSAML
if( (bp = u.u_procp->p_lnode) && (bp->l_flags & DLIMIT) ) {
/* no further allocation for this user */
u.u_error = EDISKLIM;
return( NULL );
}
#endif AUSAML
ka5sav1 = ka5;
getfs(dev);
while(b.s_flock & S_BUSY) /* fix026 */
{ /* fix026 */
b.s_flock =| S_WANTED; /* fix026 */
sleep(&b.s_flock, PINOD+1); /* fix026 */
} /* fix026 */
do {
if(b.s_nfree <= 0)
goto nospace;
bno = b.s_free[--b.s_nfree];
if(bno == 0)
goto nospace;
} while (badblock(bno, dev));
if(b.s_nfree <= 0) {
register int ka5sav;
b.s_flock++;
ka5sav = ka5;
bp = bread(dev, bno);
bswtch( bp );
bcopy( &b , bufscr , 101 );
brelse(bp);
ka5 = ka5sav;
b.s_nfree = bufscr[0];
bcopy(bufscr+1, b.s_free, 100);
if(b.s_flock & S_WANTED) /* fix026 */
wakeup(&b.s_flock); /* fix026 */
b.s_flock = 0;
}
bp = getblk(dev, bno);
clrbuf(bp);
b.s_fmod = 1;
ka5 = ka5sav1;
return(bp);
nospace:
b.s_nfree = 0;
prdev("no space", dev);
u.u_error = ENOSPC;
#ifdef UPRINTS
uprints( "\nwrite error - device full\n" );
#endif
#ifdef COOL_NO_SPACE
#ifndef DELAY
sleep( &lbolt , PRIBIO );
#endif
#ifdef DELAY
delay( 5*HZ ); /* hang 5 */
#endif
#endif
ka5 = ka5sav1;
return(NULL);
}
#endif MAPPED_BUFFERS
/*
* place the specified disk block
* back on the free list of the
* specified device.
*/
#ifndef MAPPED_BUFFERS
free(dev, bno)
unsigned bno; /* fix000 */
{
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;
}
#else MAPPED_BUFFERS
/*
* ka5 is preserved by this routine
*/
free(dev, bno)
unsigned bno; /* fix000 */
{
register *bp;
register ka5sav1 = ka5;
getfs(dev);
b.s_fmod = 1;
while(b.s_flock & S_BUSY) /* fix026 */
{
b.s_flock =| S_WANTED; /* fix026 */
sleep(&b.s_flock, PINOD);
}
if (badblock(bno, dev))
goto ret;
if(b.s_nfree <= 0) {
b.s_nfree = 1;
b.s_free[0] = 0;
}
if(b.s_nfree >= 100) {
register int ka5sav;
b.s_flock++;
bp = getblk(dev, bno);
bufscr[0] = b.s_nfree;
bcopy( &b.s_free , bufscr+1 , 100);
ka5sav = ka5;
bswtch( bp );
bcopy( bufscr , &b , 101 );
ka5 = ka5sav;
b.s_nfree = 0;
bwrite(bp);
if( b.s_flock & S_WANTED) /* fix026 */
wakeup(&b.s_flock); /* fix026 */
b.s_flock = 0;
}
b.s_free[b.s_nfree++] = bno;
b.s_fmod = 1;
ret:
ka5 = ka5sav1;
}
#endif MAPPED_BUFFERS
/*
* 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
*/
#ifndef MAPPED_BUFFERS
badblock(fp, bn, dev)
register struct filsys *fp; /* fix000 */
register unsigned bn; /* fix000 */
{
if (bn < fp->s_isize+2 || bn >= fp->s_fsize) {
prdev("bad block", dev);
return(1);
}
return(0);
}
#else MAPPED_BUFFERS
badblock(bn, dev)
register unsigned bn; /* fix000 */
{
if (bn < b.s_isize+2 || bn >= b.s_fsize) {
prdev("bad block", dev);
return(1);
}
return(0);
}
#endif MAPPED_BUFFERS
/*
* 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.
*/
#ifndef MAPPED_BUFFERS
ialloc(dev)
{
register *fp, *bp, *ip;
int i, j, k, ino;
#ifdef AUSAML
if( (fp = u.u_procp->p_lnode) && (fp->l_flags & DLIMIT) ) {
/* no further allocation for this user */
u.u_error = EDISKLIM;
return( NULL );
}
#endif AUSAML
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);
#ifdef UPRINTS
uprints("\ncreate error - out of inodes\n");
#endif UPRINTS
u.u_error = ENOSPC;
return(NULL);
}
#else MAPPED_BUFFERS
/*
* ka5 is not preserved by this routine
*/
ialloc(dev)
{
register struct inode *ip;
int ka5sav, ino;
register int i;
#ifdef AUSAML
if( (ip = u.u_procp->p_lnode) && (ip->l_flags & DLIMIT) ) {
/* no further allocation for this user */
u.u_error = EDISKLIM;
return( NULL );
}
#endif AUSAML
getfs(dev);
loop: /* fix026 */
while(b.s_ilock & S_BUSY) /* fix026 */
{
b.s_ilock =| S_WANTED; /* fix026 */
sleep(&b.s_ilock, PINOD); /* fix026 */
}
if(b.s_ninode > 0) {
ino = b.s_inode[--b.s_ninode];
ip = iget(dev, ino);
if (ip==NULL)
return(NULL);
if(ip->i_mode == 0) {
register int *p;
p = &ip->i_mode;
i = 12; /* &i_addr[8] - &i_mode */
do *p++ = 0; while( --i);
b.s_fmod = 1;
return(ip);
}
/*
* Inode was allocated after all.
* Look some more.
*/
iput(ip);
goto loop;
}
b.s_ilock =| S_BUSY; /* fix026 */
ka5sav = ka5;
for(ino = (i = b.s_ilowa) << 4; i < b.s_isize; i++) /* fix026 */
{
register int j;
int bp;
bp = breada(dev, i+2, i+3); /* fix026 */
for(j=0; j<256; j=+16) {
bswtch( bp );
ino++;
if(b.intarray[j] != 0)
continue;
for(ip = inode; ip < &inode[NINODE]; ip++)
if(dev == ip->i_dev && ino == ip->i_number)
goto cont;
ka5 = ka5sav;
b.s_inode[b.s_ninode++] = ino;
if(b.s_ninode >= 100)
break;
cont:;
}
brelse(bp);
ka5 = ka5sav;
if(b.s_ninode >= 100)
break;
}
b.s_ilowa = i; /* fix026 */
if(b.s_ilock & S_WANTED) /* fix026 */
{
wakeup(&b.s_ilock); /* fix026 */
}
b.s_ilock = 0;
if (b.s_ninode > 0)
goto loop;
prdev("Out of inodes", dev);
#ifdef UPRINTS
uprints("\ncreate error - out of inodes\n");
#endif UPRINTS
u.u_error = ENOSPC;
return(NULL);
}
#endif MAPPED_BUFFERS
/*
* 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.
*/
#ifndef MAPPED_BUFFERS
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;
}
#else MAPPED_BUFFERS
/*
* ka5 is preserved
*/
ifree(dev, ino)
{
register ka5sav;
register unsigned bno;
ka5sav = ka5;
getfs(dev);
while( b.s_ilock & S_BUSY ) /* fix026 */
{
b.s_ilock =| S_WANTED;
sleep( &b.s_ilock , PINOD );
} /* fix026 */
if( b.s_ninode < 100 ) /* fix026 */
{
b.s_inode[b.s_ninode++] = ino;
b.s_fmod = 1;
}
else /* fix026 */
{
/* see if inode is before s_ilowa */
if( (bno = (ino - 1) >> 4) < b.s_ilowa)
b.s_ilowa = bno;
} /* fix026 */
ka5 = ka5sav;
}
#endif MAPPED_BUFFERS
/*
* 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"
*/
#ifndef MAPPED_BUFFERS
/*
* on return ka5 addresses the super block just located
*/
getfs(dev)
{
register struct mount *p;
register unsigned n1, n2; /* fix000 */
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");
}
#else MAPPED_BUFFERS
getfs(dev)
{
register struct mount *p;
for(p = &mount[0]; p < &mount[NMOUNT]; p++)
if(p->m_bufp != NULL && p->m_dev == dev) {
bswtch( p->m_bufp );
if( b.s_nfree > 100 || b.s_ninode > 100 ) {
prdev("bad count", dev);
b.s_nfree = 0;
b.s_ninode = 0;
}
return b.buff;
}
panic("no fs");
}
#endif MAPPED_BUFFERS
/*
* 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.
#ifdef BETTER_TIME
* always rewrite the super block of the root
* keep better time
#endif
*/
#ifndef MAPPED_BUFFERS
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;
#ifdef BETTER_TIME
if((mp->m_dev != rootdev && ip->s_fmod==0) ||
ip->s_ilock!=0 ||
#endif
#ifndef BETTER_TIME
if(ip->s_fmod==0 || ip->s_ilock!=0 ||
#endif
ip->s_flock!=0 || ip->s_ronly!=0)
continue;
bp = getblk(mp->m_dev, 1);
#ifdef QMOUNT
if( bp != mp->m_bufp ) panic("update block ??");
#endif QMOUNT
ip->s_fmod = 0;
ip->s_time = time; /* fix000 */
#ifndef QMOUNT
bcopy(ip, bp->b_addr, 256);
#endif QMOUNT
bwrite(bp);
}
for(ip = &inode[0]; ip < &inode[NINODE]; ip++)
if( (ip->i_flag&ILOCK) == 0 && ip->i_count != 0 ) /* fix025 */
{
ip->i_flag =| ILOCK;
ip->i_count++; /* fix025 */
iupdat(ip, time);
iput(ip); /* fix025 */
}
updlock = 0;
bflush(NODEV);
}
#else MAPPED_BUFFERS
/*
* ka5 is not preserved by this routine
*/
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) {
bswtch(mp->m_bufp);
#ifdef BETTER_TIME
if((mp->m_dev != rootdev && b.s_fmod==0) ||
(b.s_ilock & S_BUSY) ||
#else
if(b.s_fmod==0 || (b.s_ilock & S_BUSY) ||
#endif BETTER_TIME
b.s_flock!=0 || b.s_ronly!=0)
continue;
bp = getblk(mp->m_dev, 1);
#ifdef QMOUNT
if( bp != mp->m_bufp ) panic("update block ??");
#else
;***** QMOUNT not defined?? ****;
#endif QMOUNT
b.s_fmod = 0;
b.s_time = time; /* fix000 */
bwrite(bp);
}
for(ip = &inode[0]; ip < &inode[NINODE]; ip++)
if( (ip->i_flag&ILOCK) == 0 && ip->i_count != 0 ) /* fix025 */
{ /* fix025 */
ip->i_flag =| ILOCK;
ip->i_count ++; /* fix025 */
iupdat(ip, time);
iput(ip); /* fix025 */
}
updlock = 0;
bflush(NODEV);
}
#endif MAPPED_BUFFERS