only delete space used by inode, on inode deletion; required
[unix-history] / usr / src / sys / ufs / ffs / ffs_subr.c
index d7c9567..ec5cdcb 100644 (file)
-/*     ffs_subr.c      6.7     85/05/27        */
+/*
+ * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.redist.c%
+ *
+ *     @(#)ffs_subr.c  7.17 (Berkeley) %G%
+ */
 
 
-#ifdef KERNEL
-#include "param.h"
-#include "systm.h"
-#include "mount.h"
-#include "fs.h"
-#include "buf.h"
-#include "inode.h"
-#include "dir.h"
-#include "user.h"
-#include "quota.h"
-#include "kernel.h"
-#else
 #include <sys/param.h>
 #include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/mount.h>
-#include <sys/fs.h>
-#include <sys/buf.h>
-#include <sys/inode.h>
-#include <sys/dir.h>
-#include <sys/user.h>
-#include <sys/quota.h>
-#endif
+#include <ufs/ffs/fs.h>
+#include <ufs/ffs/ffs_extern.h>
 
 #ifdef KERNEL
 
 #ifdef KERNEL
-int    syncprt = 0;
-
-/*
- * 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 ||
-                   (ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 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 <sys/buf.h>
+#include <sys/vnode.h>
+#include <ufs/ufs/quota.h>
+#include <ufs/ufs/inode.h>
 
 /*
 
 /*
- * 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.
+ * 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(vp, offset, res, bpp)
+       struct vnode *vp;
+       off_t offset;
+       char **res;
+       struct buf **bpp;
 {
 {
+       struct inode *ip;
        register struct fs *fs;
        register struct fs *fs;
-       register struct buf *bp;
-       struct buf *lastbufp;
-       long lbn, lastlbn, s;
-       daddr_t blkno;
+       struct buf *bp;
+       daddr_t lbn;
+       int bsize, error;
 
 
+       ip = VTOI(vp);
        fs = ip->i_fs;
        fs = ip->i_fs;
-       lastlbn = howmany(ip->i_size, fs->fs_bsize);
-       if (lastlbn < nbuf / 2) {
-               for (lbn = 0; lbn < lastlbn; lbn++) {
-                       blkno = fsbtodb(fs, bmap(ip, lbn, B_READ));
-                       blkflush(ip->i_dev, blkno, blksize(fs, ip, lbn));
-               }
-       } 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 = spl6();
-                       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);
-               }
+       lbn = lblkno(fs, offset);
+       bsize = blksize(fs, ip, lbn);
+
+       *bpp = NULL;
+       if (error = bread(vp, 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
 
 }
 #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.
  */
 /*
  * 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[];
        struct fs *fs;
        int fragmap;
        long fraglist[];
@@ -175,37 +87,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;
+#if defined(KERNEL) && defined(DIAGNOSTIC)
+void
+ffs_checkoverlap(bp, ip)
+       struct buf *bp;
+       struct inode *ip;
 {
 {
+       register struct buf *ebp, *ep;
+       register daddr_t start, last;
+       struct vnode *vp;
 
 
-       if ((unsigned)bn >= fs->fs_size) {
-               printf("bad block %d, ", bn);
-               fserr(fs, "bad block");
-               return (1);
+       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
  */
 
 /*
  * 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;
 
        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:
        case 8:
                return (cp[h] == 0xff);
        case 4:
@@ -218,21 +147,21 @@ isblock(fs, cp, h)
                mask = 0x01 << (h & 0x7);
                return ((cp[h >> 3] & mask) == mask);
        default:
                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
  */
        }
 }
 
 /*
  * 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;
 {
 
        struct fs *fs;
        u_char *cp;
        daddr_t h;
 {
 
-       switch ((fs)->fs_frag) {
+       switch ((int)fs->fs_frag) {
        case 8:
                cp[h] = 0;
                return;
        case 8:
                cp[h] = 0;
                return;
@@ -246,20 +175,21 @@ clrblock(fs, cp, h)
                cp[h >> 3] &= ~(0x01 << (h & 0x7));
                return;
        default:
                cp[h >> 3] &= ~(0x01 << (h & 0x7));
                return;
        default:
-               panic("clrblock");
+               panic("ffs_clrblock");
        }
 }
 
 /*
  * put a block into the map
  */
        }
 }
 
 /*
  * 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;
 {
 
        struct fs *fs;
        unsigned char *cp;
        daddr_t h;
 {
 
-       switch (fs->fs_frag) {
+       switch ((int)fs->fs_frag) {
 
        case 8:
                cp[h] = 0xff;
 
        case 8:
                cp[h] = 0xff;
@@ -274,102 +204,17 @@ setblock(fs, cp, h)
                cp[h >> 3] |= (0x01 << (h & 0x7));
                return;
        default:
                cp[h >> 3] |= (0x01 << (h & 0x7));
                return;
        default:
-               panic("setblock");
-       }
-}
-
-#ifdef KERNEL
-/*
- * 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_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);
+               panic("ffs_setblock");
        }
        }
-       printf("dev = 0x%x\n", dev);
-       panic("getfs: no fs");
-       return (NULL);
 }
 
 }
 
+#if (!defined(vax) && !defined(tahoe) && !defined(hp300)) \
+       || defined(VAX630) || defined(VAX650)
 /*
 /*
- * 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
- *     <getfsx(dev),blkno>
- * rather than
- *     <dev, blkno>
- * provided the information need remain valid only
- * as long as the file system is mounted.
- */
-getfsx(dev)
-       dev_t dev;
-{
-       register struct mount *mp;
-
-       if (dev == swapdev)
-               return (MSWAPX);
-       for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
-               if (mp->m_dev == dev)
-                       return (mp - &mount[0]);
-       return (-1);
-}
-
-/*
- * 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 s, i, j, count;
-       register struct buf *bp, *dp;
-       int counts[MAXBSIZE/CLBYTES+1];
-       static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" };
-
-       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");
-       }
-}
-#endif
-
-#if !defined(vax)
-/*
- * C definitions of special vax instructions.
+ * C definitions of special instructions.
+ * Normally expanded with inline.
  */
  */
+int
 scanc(size, cp, table, mask)
        u_int size;
        register u_char *cp, table[];
 scanc(size, cp, table, mask)
        u_int size;
        register u_char *cp, table[];
@@ -381,7 +226,10 @@ scanc(size, cp, table, mask)
                cp++;
        return (end - cp);
 }
                cp++;
        return (end - cp);
 }
+#endif
 
 
+#if !defined(vax) && !defined(tahoe) && !defined(hp300)
+int
 skpc(mask, size, cp)
        register u_char mask;
        u_int size;
 skpc(mask, size, cp)
        register u_char mask;
        u_int size;
@@ -394,6 +242,7 @@ skpc(mask, size, cp)
        return (end - cp);
 }
 
        return (end - cp);
 }
 
+int
 locc(mask, size, cp)
        register u_char mask;
        u_int size;
 locc(mask, size, cp)
        register u_char mask;
        u_int size;
@@ -405,4 +254,4 @@ locc(mask, size, cp)
                cp++;
        return (end - cp);
 }
                cp++;
        return (end - cp);
 }
-#endif vax
+#endif