only delete space used by inode, on inode deletion; required
[unix-history] / usr / src / sys / ufs / ffs / ffs_subr.c
index 68e74dd..ec5cdcb 100644 (file)
  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
  * All rights reserved.
  *
  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
  * All rights reserved.
  *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * %sccs.include.redist.c%
  *
  *
- *     @(#)ffs_subr.c  7.8 (Berkeley) %G%
+ *     @(#)ffs_subr.c  7.17 (Berkeley) %G%
  */
 
  */
 
-#ifdef KERNEL
-#include "param.h"
-#include "systm.h"
-#include "buf.h"
-#include "time.h"
-#include "kernel.h"
-#include "file.h"
-#include "mount.h"
-#include "vnode.h"
-#include "../ufs/inode.h"
-#include "../ufs/ufsmount.h"
-#include "../ufs/fs.h"
-#include "../ufs/quota.h"
-#else
 #include <sys/param.h>
 #include <sys/param.h>
-#include <sys/systm.h>
+#include <ufs/ffs/fs.h>
+#include <ufs/ffs/ffs_extern.h>
+
+#ifdef KERNEL
 #include <sys/buf.h>
 #include <sys/buf.h>
-#include <sys/time.h>
-#include <sys/file.h>
-#include <sys/mount.h>
 #include <sys/vnode.h>
 #include <sys/vnode.h>
-#include <ufs/inode.h>
-#include <ufs/ufsmount.h>
-#include <ufs/fs.h>
-#include <ufs/quota.h>
-#endif
+#include <ufs/ufs/quota.h>
+#include <ufs/ufs/inode.h>
 
 
-#ifdef KERNEL
 /*
 /*
- * 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;
-       int s, error, allerror = 0;
-       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) {
-#ifdef SECSIZE
-               lastlbn--;
-               s = fsbtodb(fs, fs->fs_frag);
-               for (lbn = 0; lbn < lastlbn; lbn++) {
-                       error = bmap(ip, lbn, &blkno, (daddr_t *)0, (int *)0);
-                       if (error)
-                               allerror = error;
-                       if (error = blkflush(ip->i_devvp, blkno,
-                           blksize(fs, ip, lbn)))
-                               allerror = error;
-               }
-#endif SECSIZE
-       } 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);
-                       if (error = bwrite(bp))
-                               allerror = error;
-               }
+       lbn = lblkno(fs, offset);
+       bsize = blksize(fs, ip, lbn);
+
+       *bpp = NULL;
+       if (error = bread(vp, lbn, bsize, NOCRED, &bp)) {
+               brelse(bp);
+               return (error);
        }
        }
-       if (error = iupdat(ip, &time, &time, 1))
-               allerror = error;
-       return (allerror);
+       if (res)
+               *res = bp->b_un.b_addr + blkoff(fs, offset);
+       *bpp = bp;
+       return (0);
 }
 }
-#endif KERNEL
-
-extern int around[9];
-extern int inside[9];
-extern u_char *fragtbl[];
+#endif
 
 /*
  * 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[];
@@ -149,30 +87,47 @@ 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;
        struct fs *fs;
        unsigned char *cp;
        daddr_t h;
@@ -192,15 +147,15 @@ 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;
@@ -220,14 +175,15 @@ 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;
@@ -248,75 +204,17 @@ setblock(fs, cp, h)
                cp[h >> 3] |= (0x01 << (h & 0x7));
                return;
        default:
                cp[h >> 3] |= (0x01 << (h & 0x7));
                return;
        default:
-               panic("setblock");
+               panic("ffs_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.
- * Filesystems still working on a mount are skipped.
- *
- * panic: no fs -- the device is not mounted.
- *     this "cannot happen"
- */
-struct fs *
-getfs(dev)
-       dev_t dev;
-{
-       register struct ufsmount *mp;
-       register struct fs *fs;
-
-       for (mp = &mounttab[0]; mp < &mounttab[NMOUNT]; mp++) {
-               if (mp->um_fs == NULL || mp->um_dev != dev ||
-                   mp->um_fs == (struct fs *)1)                /* XXX */
-                       continue;
-               fs = mp->um_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);
-}
-
-/*
- * 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 ufsmount *mp;
-
-       if (dev == swapdev)
-               return (MSWAPX);
-       for(mp = &mounttab[0]; mp < &mounttab[NMOUNT]; mp++)
-               if (mp->um_dev == dev)
-                       return (mp - &mounttab[0]);
-       return (-1);
-}
-#endif
-
-#if (!defined(vax) && !defined(tahoe)) || defined(VAX630) || defined(VAX650)
+#if (!defined(vax) && !defined(tahoe) && !defined(hp300)) \
+       || defined(VAX630) || defined(VAX650)
 /*
  * C definitions of special instructions.
  * Normally expanded with inline.
  */
 /*
  * 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[];
@@ -330,7 +228,8 @@ scanc(size, cp, table, mask)
 }
 #endif
 
 }
 #endif
 
-#if !defined(vax) && !defined(tahoe)
+#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;
@@ -343,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;