Files
retrobsd/sys/kernel/ufs_subr.c
Serge Vakulenko 585773955b Fix include paths in the kernel sources.
Max32 kernel successfully compiled with kconfig utility.
2015-08-31 00:21:41 -07:00

146 lines
3.8 KiB
C

/*
* Copyright (c) 1986 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include <sys/param.h>
#include <sys/user.h>
#include <sys/proc.h>
#include <sys/fs.h>
#include <sys/inode.h>
#include <sys/buf.h>
#include <sys/mount.h>
#include <sys/kernel.h>
#include <sys/systm.h>
int updlock; /* lock for sync */
/*
* Go through the mount table looking for filesystems which have been modified.
* For each "dirty" filesystem call 'ufs_sync' to flush changed inodes, data
* blocks and the superblock to disc.
*/
void
sync()
{
register struct mount *mp;
register struct fs *fs;
int async;
if (updlock)
return;
updlock++;
for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
if (mp->m_inodp == NULL || mp->m_dev == NODEV)
continue;
fs = &mp->m_filsys;
if (fs->fs_fmod == 0 || fs->fs_ilock || fs->fs_flock)
continue;
async = mp->m_flags & MNT_ASYNC;
mp->m_flags &= ~MNT_ASYNC;
ufs_sync(mp);
mp->m_flags |= async;
}
updlock = 0;
}
/*
* Flush all the blocks associated with an inode.
* There are two strategies based on the size of the file;
* large files are those with more than NBUF/2 blocks.
* Large files
* Walk through the buffer pool and push any dirty pages
* associated with the device on which the file resides.
* Small files
* Look up each block in the file to see if it is in the
* buffer pool writing any that are found to disk.
* Note that we make a more stringent check of
* writing out any block in the buffer pool that may
* overlap the inode. This brings the inode up to
* date with recent mods to the cooked device.
*/
void
syncip(ip)
struct inode *ip;
{
register struct buf *bp;
register struct buf *lastbufp;
long lbn, lastlbn;
register int s;
daddr_t blkno;
lastlbn = howmany(ip->i_size, DEV_BSIZE);
if (lastlbn < NBUF / 2) {
for (lbn = 0; lbn < lastlbn; lbn++) {
blkno = fsbtodb(bmap(ip, lbn, B_READ, 0));
blkflush(ip->i_dev, blkno);
}
} else {
lastbufp = &buf[NBUF];
for (bp = buf; bp < lastbufp; bp++) {
if (bp->b_dev != ip->i_dev ||
(bp->b_flags & B_DELWRI) == 0)
continue;
s = splbio();
if (bp->b_flags & B_BUSY) {
bp->b_flags |= B_WANTED;
sleep((caddr_t)bp, PRIBIO+1);
splx(s);
bp--;
continue;
}
splx(s);
notavail(bp);
bwrite(bp);
}
}
ip->i_flag |= ICHG;
iupdat(ip, &time, &time, 1);
}
/*
* Check that a specified block number is in range.
*/
int
badblock (fp, bn)
register struct fs *fp;
daddr_t bn;
{
if (bn < fp->fs_isize || bn >= fp->fs_fsize) {
printf("bad block %D, ",bn);
fserr(fp, "bad block");
return (1);
}
return (0);
}
/*
* 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 super block magic number is performed.
*
* panic: no fs -- the device is not mounted.
* this "cannot happen"
*/
struct fs *
getfs(dev)
dev_t dev;
{
register struct mount *mp;
register struct fs *fs;
for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
if (mp->m_inodp == NULL || mp->m_dev != dev)
continue;
fs = &mp->m_filsys;
if (fs->fs_nfree > NICFREE || fs->fs_ninode > NICINOD) {
fserr(fs, "bad count");
fs->fs_nfree = fs->fs_ninode = 0;
}
return(fs);
}
printf("no fs on dev %u/%u\n",major(dev), minor(dev));
return((struct fs *) NULL);
}