X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/b11be0569e17869fd29b11b615ee74ce78425ed9..c5fd1724a109ad4d71eee844cced6c1d713101ee:/usr/src/sys/ufs/ffs/ffs_subr.c diff --git a/usr/src/sys/ufs/ffs/ffs_subr.c b/usr/src/sys/ufs/ffs/ffs_subr.c index b8961171db..6b75c310d4 100644 --- a/usr/src/sys/ufs/ffs/ffs_subr.c +++ b/usr/src/sys/ufs/ffs/ffs_subr.c @@ -1,122 +1,60 @@ -/* ffs_subr.c 6.1 83/07/29 */ +/* + * Copyright (c) 1982, 1986, 1989 Regents of the University of California. + * All rights reserved. + * + * %sccs.include.redist.c% + * + * @(#)ffs_subr.c 7.14 (Berkeley) %G% + */ -#ifdef KERNEL -#include "../h/param.h" -#include "../h/systm.h" -#include "../h/mount.h" -#include "../h/fs.h" -#include "../h/conf.h" -#include "../h/buf.h" -#include "../h/inode.h" -#include "../h/dir.h" -#include "../h/user.h" -#include "../h/quota.h" -#include "../h/kernel.h" -#else #include -#include -#include -#include -#include #include -#include -#include -#include -#include -#endif +#include -#ifdef KERNEL -int syncprt = 0; +#include +#include -/* - * Update is the internal name of 'sync'. It goes through the disk - * queues to initiate sandbagged IO; goes through the inodes to write - * modified nodes; and it goes through the mount table to initiate - * the writing of the modified super blocks. - */ -update() -{ - register struct inode *ip; - register struct mount *mp; - struct fs *fs; - - if (syncprt) - bufstats(); - if (updlock) - return; - updlock++; - /* - * Write back modified superblocks. - * Consistency check that the superblock - * of each file system is still in the buffer cache. - */ - for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { - if (mp->m_bufp == NULL || mp->m_dev == NODEV) - continue; - fs = mp->m_bufp->b_un.b_fs; - if (fs->fs_fmod == 0) - continue; - if (fs->fs_ronly != 0) { /* XXX */ - printf("fs = %s\n", fs->fs_fsmnt); - panic("update: rofs mod"); - } - fs->fs_fmod = 0; - fs->fs_time = time.tv_sec; - sbupdate(mp); - } - /* - * Write back each (modified) inode. - */ - for (ip = inode; ip < inodeNINODE; ip++) { - if ((ip->i_flag & ILOCKED) != 0 || ip->i_count == 0) - continue; - ip->i_flag |= ILOCKED; - ip->i_count++; - iupdat(ip, &time, &time, 0); - iput(ip); - } - updlock = 0; - /* - * Force stale buffer cache information to be flushed, - * for all devices. - */ - bflush(NODEV); -} +#include +#include /* - * Flush all the blocks associated with an inode. - * 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. + * Return buffer with the contents of block "offset" from the beginning of + * directory "ip". If "res" is non-zero, fill it in with a pointer to the + * remaining space in the directory. */ -syncip(ip) - register struct inode *ip; +int +ffs_blkatoff(ip, offset, res, bpp) + struct inode *ip; + off_t offset; + char **res; + struct buf **bpp; { register struct fs *fs; - long lbn, lastlbn; - daddr_t blkno; + struct buf *bp; + daddr_t lbn; + int bsize, error; fs = ip->i_fs; - lastlbn = howmany(ip->i_size, fs->fs_bsize); - for (lbn = 0; lbn < lastlbn; lbn++) { - blkno = fsbtodb(fs, bmap(ip, lbn, B_READ)); - blkflush(ip->i_dev, blkno, blksize(fs, ip, lbn)); + lbn = lblkno(fs, offset); + bsize = blksize(fs, ip, lbn); + + *bpp = NULL; + if (error = bread(ITOV(ip), lbn, bsize, NOCRED, &bp)) { + brelse(bp); + return (error); } - ip->i_flag |= ICHG; - iupdat(ip, &time, &time, 1); + if (res) + *res = bp->b_un.b_addr + blkoff(fs, offset); + *bpp = bp; + return (0); } -#endif - -extern int around[9]; -extern int inside[9]; -extern u_char *fragtbl[]; /* * Update the frsum fields to reflect addition or deletion * of some frags. */ -fragacct(fs, fragmap, fraglist, cnt) +void +ffs_fragacct(fs, fragmap, fraglist, cnt) struct fs *fs; int fragmap; long fraglist[]; @@ -146,37 +84,54 @@ fragacct(fs, fragmap, fraglist, cnt) } } -#ifdef KERNEL -/* - * Check that a specified block number is in range. - */ -badblock(fs, bn) - register struct fs *fs; - daddr_t bn; +#ifdef DIAGNOSTIC +void +ffs_checkoverlap(bp, ip) + struct buf *bp; + struct inode *ip; { - - if ((unsigned)bn >= fs->fs_size) { - printf("bad block %d, ", bn); - fserr(fs, "bad block"); - return (1); + register struct buf *ebp, *ep; + register daddr_t start, last; + struct vnode *vp; + + ebp = &buf[nbuf]; + start = bp->b_blkno; + last = start + btodb(bp->b_bcount) - 1; + for (ep = buf; ep < ebp; ep++) { + if (ep == bp || (ep->b_flags & B_INVAL) || + ep->b_vp == NULLVP) + continue; + if (VOP_BMAP(ep->b_vp, (daddr_t)0, &vp, (daddr_t)0)) + continue; + if (vp != ip->i_devvp) + continue; + /* look for overlap */ + if (ep->b_bcount == 0 || ep->b_blkno > last || + ep->b_blkno + btodb(ep->b_bcount) <= start) + continue; + vprint("Disk overlap", vp); + (void)printf("\tstart %d, end %d overlap start %d, end %d\n", + start, last, ep->b_blkno, + ep->b_blkno + btodb(ep->b_bcount) - 1); + panic("Disk buffer overlap"); } - return (0); } -#endif +#endif /* DIAGNOSTIC */ /* * block operations * * check if a block is available */ -isblock(fs, cp, h) +int +ffs_isblock(fs, cp, h) struct fs *fs; unsigned char *cp; daddr_t h; { unsigned char mask; - switch (fs->fs_frag) { + switch ((int)fs->fs_frag) { case 8: return (cp[h] == 0xff); case 4: @@ -189,21 +144,21 @@ isblock(fs, cp, h) mask = 0x01 << (h & 0x7); return ((cp[h >> 3] & mask) == mask); default: - panic("isblock"); - return (NULL); + panic("ffs_isblock"); } } /* * take a block out of the map */ -clrblock(fs, cp, h) +void +ffs_clrblock(fs, cp, h) struct fs *fs; u_char *cp; daddr_t h; { - switch ((fs)->fs_frag) { + switch ((int)fs->fs_frag) { case 8: cp[h] = 0; return; @@ -217,20 +172,21 @@ clrblock(fs, cp, h) cp[h >> 3] &= ~(0x01 << (h & 0x7)); return; default: - panic("clrblock"); + panic("ffs_clrblock"); } } /* * put a block into the map */ -setblock(fs, cp, h) +void +ffs_setblock(fs, cp, h) struct fs *fs; unsigned char *cp; daddr_t h; { - switch (fs->fs_frag) { + switch ((int)fs->fs_frag) { case 8: cp[h] = 0xff; @@ -245,94 +201,54 @@ setblock(fs, cp, h) cp[h >> 3] |= (0x01 << (h & 0x7)); return; default: - panic("setblock"); + panic("ffs_setblock"); } } -#ifdef KERNEL +#if (!defined(vax) && !defined(tahoe) && !defined(hp300)) \ + || defined(VAX630) || defined(VAX650) /* - * 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" + * C definitions of special instructions. + * Normally expanded with inline. */ -struct fs * -getfs(dev) - dev_t dev; +int +scanc(size, cp, table, mask) + u_int size; + register u_char *cp, table[]; + register u_char mask; { - register struct mount *mp; - register struct fs *fs; + register u_char *end = &cp[size]; - for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { - if (mp->m_bufp == NULL || mp->m_dev != dev) - continue; - fs = mp->m_bufp->b_un.b_fs; - if (fs->fs_magic != FS_MAGIC) { - printf("dev = 0x%x, fs = %s\n", dev, fs->fs_fsmnt); - panic("getfs: bad magic"); - } - return (fs); - } - printf("dev = 0x%x\n", dev); - panic("getfs: no fs"); - return (NULL); + while (cp < end && (table[*cp] & mask) == 0) + cp++; + return (end - cp); } +#endif -/* - * Getfsx returns the index in the file system - * table of the specified device. The swap device - * is also assigned a pseudo-index. The index may - * be used as a compressed indication of the location - * of a block, recording - * - * rather than - * - * provided the information need remain valid only - * as long as the file system is mounted. - */ -getfsx(dev) - dev_t dev; +#if !defined(vax) && !defined(tahoe) && !defined(hp300) +int +skpc(mask, size, cp) + register u_char mask; + u_int size; + register u_char *cp; { - register struct mount *mp; + register u_char *end = &cp[size]; - if (dev == swapdev) - return (MSWAPX); - for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) - if (mp->m_dev == dev) - return (mp - &mount[0]); - return (-1); + while (cp < end && *cp == mask) + cp++; + return (end - cp); } -/* - * Print out statistics on the current allocation of the buffer pool. - * Can be enabled to print out on every ``sync'' by setting "syncprt" - * above. - */ -bufstats() +int +locc(mask, size, cp) + register u_char mask; + u_int size; + register u_char *cp; { - int s, i, j, count; - register struct buf *bp, *dp; - int counts[MAXBSIZE/CLBYTES+1]; - static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" }; + register u_char *end = &cp[size]; - for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) { - count = 0; - for (j = 0; j <= MAXBSIZE/CLBYTES; j++) - counts[j] = 0; - s = spl6(); - for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) { - counts[dp->b_bufsize/CLBYTES]++; - count++; - } - splx(s); - printf("%s: total-%d", bname[i], count); - for (j = 0; j <= MAXBSIZE/CLBYTES; j++) - if (counts[j] != 0) - printf(", %d-%d", j * CLBYTES, counts[j]); - printf("\n"); - } + while (cp < end && *cp != mask) + cp++; + return (end - cp); } #endif