LSX/sys/alloc.c

Compare this file to the similar file:
Show the results in this format:

#
/*
 *	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);
}