BSD 4_4_Lite1 release
[unix-history] / usr / src / sys / ufs / ffs / ffs_balloc.c
index aaef4b5..752feec 100644 (file)
 /*
 /*
- * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1982, 1986, 1989, 1993
+ *     The 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.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
  *
- *     @(#)ffs_balloc.c        7.7 (Berkeley) %G%
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)ffs_balloc.c        8.4 (Berkeley) 9/23/93
  */
 
  */
 
-#include "param.h"
-#include "systm.h"
-#include "user.h"
-#include "buf.h"
-#include "proc.h"
-#include "file.h"
-#include "vnode.h"
-#include "../ufs/inode.h"
-#include "../ufs/fs.h"
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/proc.h>
+#include <sys/file.h>
+#include <sys/vnode.h>
 
 
-/*
- * Bmap defines the structure of file system storage
- * by returning the physical block number on a device
- * given the inode and the logical block number in a file.
- */
-bmap(ip, bn, bnp)
-       register struct inode *ip;
-       register daddr_t bn;
-       daddr_t *bnp;
-{
-       register struct fs *fs;
-       register daddr_t nb;
-       struct buf *bp;
-       daddr_t *bap;
-       int i, j, sh;
-       int error;
+#include <vm/vm.h>
 
 
-       if (bn < 0)
-               return (EFBIG);
-       fs = ip->i_fs;
+#include <ufs/ufs/quota.h>
+#include <ufs/ufs/inode.h>
+#include <ufs/ufs/ufs_extern.h>
 
 
-       /*
-        * The first NDADDR blocks are direct blocks
-        */
-       if (bn < NDADDR) {
-               nb = ip->i_db[bn];
-               if (nb == 0) {
-                       *bnp = (daddr_t)-1;
-                       return (0);
-               }
-               *bnp = fsbtodb(fs, nb);
-               return (0);
-       }
-       /*
-        * Determine the number of levels of indirection.
-        */
-       sh = 1;
-       bn -= NDADDR;
-       for (j = NIADDR; j > 0; j--) {
-               sh *= NINDIR(fs);
-               if (bn < sh)
-                       break;
-               bn -= sh;
-       }
-       if (j == 0)
-               return (EFBIG);
-       /*
-        * Fetch through the indirect blocks.
-        */
-       nb = ip->i_ib[NIADDR - j];
-       if (nb == 0) {
-               *bnp = (daddr_t)-1;
-               return (0);
-       }
-       for (; j <= NIADDR; j++) {
-               if (error = bread(ip->i_devvp, fsbtodb(fs, nb),
-                   (int)fs->fs_bsize, NOCRED, &bp)) {
-                       brelse(bp);
-                       return (error);
-               }
-               bap = bp->b_un.b_daddr;
-               sh /= NINDIR(fs);
-               i = (bn / sh) % NINDIR(fs);
-               nb = bap[i];
-               if (nb == 0) {
-                       *bnp = (daddr_t)-1;
-                       brelse(bp);
-                       return (0);
-               }
-               brelse(bp);
-       }
-       *bnp = fsbtodb(fs, nb);
-       return (0);
-}
+#include <ufs/ffs/fs.h>
+#include <ufs/ffs/ffs_extern.h>
 
 /*
  * Balloc defines the structure of file system storage
  * by allocating the physical blocks on a device given
  * the inode and the logical block number in a file.
  */
 
 /*
  * Balloc defines the structure of file system storage
  * by allocating the physical blocks on a device given
  * the inode and the logical block number in a file.
  */
-balloc(ip, bn, size, bpp, flags)
+ffs_balloc(ip, bn, size, cred, bpp, flags)
        register struct inode *ip;
        register daddr_t bn;
        int size;
        register struct inode *ip;
        register daddr_t bn;
        int size;
+       struct ucred *cred;
        struct buf **bpp;
        int flags;
 {
        struct buf **bpp;
        int flags;
 {
@@ -118,13 +66,15 @@ balloc(ip, bn, size, bpp, flags)
        register daddr_t nb;
        struct buf *bp, *nbp;
        struct vnode *vp = ITOV(ip);
        register daddr_t nb;
        struct buf *bp, *nbp;
        struct vnode *vp = ITOV(ip);
-       int osize, nsize, i, j, sh, error;
-       daddr_t newb, lbn, *bap, pref, blkpref();
+       struct indir indirs[NIADDR + 2];
+       daddr_t newb, lbn, *bap, pref;
+       int osize, nsize, num, i, error;
 
 
-       *bpp = (struct buf *)0;
+       *bpp = NULL;
        if (bn < 0)
                return (EFBIG);
        fs = ip->i_fs;
        if (bn < 0)
                return (EFBIG);
        fs = ip->i_fs;
+       lbn = bn;
 
        /*
         * If the next write will extend the file into a new block,
 
        /*
         * If the next write will extend the file into a new block,
@@ -135,14 +85,15 @@ balloc(ip, bn, size, bpp, flags)
        if (nb < NDADDR && nb < bn) {
                osize = blksize(fs, ip, nb);
                if (osize < fs->fs_bsize && osize > 0) {
        if (nb < NDADDR && nb < bn) {
                osize = blksize(fs, ip, nb);
                if (osize < fs->fs_bsize && osize > 0) {
-                       error = realloccg(ip, nb,
-                               blkpref(ip, nb, (int)nb, &ip->i_db[0]),
-                               osize, (int)fs->fs_bsize, &bp);
+                       error = ffs_realloccg(ip, nb,
+                               ffs_blkpref(ip, nb, (int)nb, &ip->i_db[0]),
+                               osize, (int)fs->fs_bsize, cred, &bp);
                        if (error)
                                return (error);
                        ip->i_size = (nb + 1) * fs->fs_bsize;
                        if (error)
                                return (error);
                        ip->i_size = (nb + 1) * fs->fs_bsize;
+                       vnode_pager_setsize(vp, (u_long)ip->i_size);
                        ip->i_db[nb] = dbtofsb(fs, bp->b_blkno);
                        ip->i_db[nb] = dbtofsb(fs, bp->b_blkno);
-                       ip->i_flag |= IUPD|ICHG;
+                       ip->i_flag |= IN_CHANGE | IN_UPDATE;
                        if (flags & B_SYNC)
                                bwrite(bp);
                        else
                        if (flags & B_SYNC)
                                bwrite(bp);
                        else
@@ -176,9 +127,9 @@ balloc(ip, bn, size, bpp, flags)
                                        return (error);
                                }
                        } else {
                                        return (error);
                                }
                        } else {
-                               error = realloccg(ip, bn,
-                                       blkpref(ip, bn, (int)bn, &ip->i_db[0]),
-                                       osize, nsize, &bp);
+                               error = ffs_realloccg(ip, bn,
+                                   ffs_blkpref(ip, bn, (int)bn, &ip->i_db[0]),
+                                   osize, nsize, cred, &bp);
                                if (error)
                                        return (error);
                        }
                                if (error)
                                        return (error);
                        }
@@ -187,18 +138,18 @@ balloc(ip, bn, size, bpp, flags)
                                nsize = fragroundup(fs, size);
                        else
                                nsize = fs->fs_bsize;
                                nsize = fragroundup(fs, size);
                        else
                                nsize = fs->fs_bsize;
-                       error = alloc(ip, bn,
-                               blkpref(ip, bn, (int)bn, &ip->i_db[0]),
-                               nsize, &newb);
+                       error = ffs_alloc(ip, bn,
+                           ffs_blkpref(ip, bn, (int)bn, &ip->i_db[0]),
+                           nsize, cred, &newb);
                        if (error)
                                return (error);
                        if (error)
                                return (error);
-                       bp = getblk(vp, bn, nsize);
+                       bp = getblk(vp, bn, nsize, 0, 0);
                        bp->b_blkno = fsbtodb(fs, newb);
                        if (flags & B_CLRBUF)
                                clrbuf(bp);
                }
                ip->i_db[bn] = dbtofsb(fs, bp->b_blkno);
                        bp->b_blkno = fsbtodb(fs, newb);
                        if (flags & B_CLRBUF)
                                clrbuf(bp);
                }
                ip->i_db[bn] = dbtofsb(fs, bp->b_blkno);
-               ip->i_flag |= IUPD|ICHG;
+               ip->i_flag |= IN_CHANGE | IN_UPDATE;
                *bpp = bp;
                return (0);
        }
                *bpp = bp;
                return (0);
        }
@@ -206,135 +157,125 @@ balloc(ip, bn, size, bpp, flags)
         * Determine the number of levels of indirection.
         */
        pref = 0;
         * Determine the number of levels of indirection.
         */
        pref = 0;
-       sh = 1;
-       lbn = bn;
-       bn -= NDADDR;
-       for (j = NIADDR; j > 0; j--) {
-               sh *= NINDIR(fs);
-               if (bn < sh)
-                       break;
-               bn -= sh;
-       }
-       if (j == 0)
-               return (EFBIG);
+       if (error = ufs_getlbns(vp, bn, indirs, &num))
+               return(error);
+#ifdef DIAGNOSTIC
+       if (num < 1)
+               panic ("ffs_balloc: ufs_bmaparray returned indirect block\n");
+#endif
        /*
         * Fetch the first indirect block allocating if necessary.
         */
        /*
         * Fetch the first indirect block allocating if necessary.
         */
-       nb = ip->i_ib[NIADDR - j];
+       --num;
+       nb = ip->i_ib[indirs[0].in_off];
        if (nb == 0) {
        if (nb == 0) {
-               pref = blkpref(ip, lbn, 0, (daddr_t *)0);
-               if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb))
+               pref = ffs_blkpref(ip, lbn, 0, (daddr_t *)0);
+               if (error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize,
+                   cred, &newb))
                        return (error);
                nb = newb;
                        return (error);
                nb = newb;
-               bp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize);
+               bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0);
+               bp->b_blkno = fsbtodb(fs, newb);
                clrbuf(bp);
                /*
                 * Write synchronously so that indirect blocks
                 * never point at garbage.
                 */
                if (error = bwrite(bp)) {
                clrbuf(bp);
                /*
                 * Write synchronously so that indirect blocks
                 * never point at garbage.
                 */
                if (error = bwrite(bp)) {
-                       blkfree(ip, nb, fs->fs_bsize);
+                       ffs_blkfree(ip, nb, fs->fs_bsize);
                        return (error);
                }
                        return (error);
                }
-               ip->i_ib[NIADDR - j] = nb;
-               ip->i_flag |= IUPD|ICHG;
+               ip->i_ib[indirs[0].in_off] = newb;
+               ip->i_flag |= IN_CHANGE | IN_UPDATE;
        }
        /*
         * Fetch through the indirect blocks, allocating as necessary.
         */
        }
        /*
         * Fetch through the indirect blocks, allocating as necessary.
         */
-       for (; ; j++) {
-               error = bread(ip->i_devvp, fsbtodb(fs, nb),
-                   (int)fs->fs_bsize, NOCRED, &bp);
+       for (i = 1;;) {
+               error = bread(vp,
+                   indirs[i].in_lbn, (int)fs->fs_bsize, NOCRED, &bp);
                if (error) {
                        brelse(bp);
                        return (error);
                }
                if (error) {
                        brelse(bp);
                        return (error);
                }
-               bap = bp->b_un.b_daddr;
-               sh /= NINDIR(fs);
-               i = (bn / sh) % NINDIR(fs);
-               nb = bap[i];
-               if (j == NIADDR)
+               bap = (daddr_t *)bp->b_data;
+               nb = bap[indirs[i].in_off];
+               if (i == num)
                        break;
                        break;
+               i += 1;
                if (nb != 0) {
                        brelse(bp);
                        continue;
                }
                if (pref == 0)
                if (nb != 0) {
                        brelse(bp);
                        continue;
                }
                if (pref == 0)
-                       pref = blkpref(ip, lbn, 0, (daddr_t *)0);
-               if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) {
+                       pref = ffs_blkpref(ip, lbn, 0, (daddr_t *)0);
+               if (error =
+                   ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, &newb)) {
                        brelse(bp);
                        return (error);
                }
                nb = newb;
                        brelse(bp);
                        return (error);
                }
                nb = newb;
-               nbp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize);
+               nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0);
+               nbp->b_blkno = fsbtodb(fs, nb);
                clrbuf(nbp);
                /*
                 * Write synchronously so that indirect blocks
                 * never point at garbage.
                 */
                if (error = bwrite(nbp)) {
                clrbuf(nbp);
                /*
                 * Write synchronously so that indirect blocks
                 * never point at garbage.
                 */
                if (error = bwrite(nbp)) {
-                       blkfree(ip, nb, fs->fs_bsize);
+                       ffs_blkfree(ip, nb, fs->fs_bsize);
                        brelse(bp);
                        return (error);
                }
                        brelse(bp);
                        return (error);
                }
-               bap[i] = nb;
+               bap[indirs[i - 1].in_off] = nb;
                /*
                 * If required, write synchronously, otherwise use
                /*
                 * If required, write synchronously, otherwise use
-                * delayed write. If this is the first instance of
-                * the delayed write, reassociate the buffer with the
-                * file so it will be written if the file is sync'ed.
+                * delayed write.
                 */
                if (flags & B_SYNC) {
                        bwrite(bp);
                 */
                if (flags & B_SYNC) {
                        bwrite(bp);
-               } else if (bp->b_flags & B_DELWRI) {
-                       bdwrite(bp);
                } else {
                        bdwrite(bp);
                } else {
                        bdwrite(bp);
-                       reassignbuf(bp, vp);
                }
        }
        /*
         * Get the data block, allocating if necessary.
         */
        if (nb == 0) {
                }
        }
        /*
         * Get the data block, allocating if necessary.
         */
        if (nb == 0) {
-               pref = blkpref(ip, lbn, i, &bap[0]);
-               if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) {
+               pref = ffs_blkpref(ip, lbn, indirs[i].in_off, &bap[0]);
+               if (error = ffs_alloc(ip,
+                   lbn, pref, (int)fs->fs_bsize, cred, &newb)) {
                        brelse(bp);
                        return (error);
                }
                nb = newb;
                        brelse(bp);
                        return (error);
                }
                nb = newb;
-               nbp = getblk(vp, lbn, fs->fs_bsize);
+               nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
                nbp->b_blkno = fsbtodb(fs, nb);
                if (flags & B_CLRBUF)
                        clrbuf(nbp);
                nbp->b_blkno = fsbtodb(fs, nb);
                if (flags & B_CLRBUF)
                        clrbuf(nbp);
-               bap[i] = nb;
+               bap[indirs[i].in_off] = nb;
                /*
                 * If required, write synchronously, otherwise use
                /*
                 * If required, write synchronously, otherwise use
-                * delayed write. If this is the first instance of
-                * the delayed write, reassociate the buffer with the
-                * file so it will be written if the file is sync'ed.
+                * delayed write.
                 */
                if (flags & B_SYNC) {
                        bwrite(bp);
                 */
                if (flags & B_SYNC) {
                        bwrite(bp);
-               } else if (bp->b_flags & B_DELWRI) {
-                       bdwrite(bp);
                } else {
                        bdwrite(bp);
                } else {
                        bdwrite(bp);
-                       reassignbuf(bp, vp);
                }
                *bpp = nbp;
                return (0);
        }
        brelse(bp);
                }
                *bpp = nbp;
                return (0);
        }
        brelse(bp);
-       nbp = getblk(vp, lbn, fs->fs_bsize);
-       nbp->b_blkno = fsbtodb(fs, nb);
-       if ((flags & B_CLRBUF) && (nbp->b_flags & (B_DONE|B_DELWRI)) == 0) {
-               brelse(nbp);
+       if (flags & B_CLRBUF) {
                error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp);
                if (error) {
                        brelse(nbp);
                        return (error);
                }
                error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp);
                if (error) {
                        brelse(nbp);
                        return (error);
                }
+       } else {
+               nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
+               nbp->b_blkno = fsbtodb(fs, nb);
        }
        *bpp = nbp;
        return (0);
        }
        *bpp = nbp;
        return (0);