BSD 4_4_Lite1 release
[unix-history] / usr / src / sys / ufs / ffs / ffs_balloc.c
index 04d419f..752feec 100644 (file)
@@ -1,10 +1,36 @@
 /*
 /*
- * 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.
  *
  *
- * %sccs.include.redist.c%
+ * 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.18 (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 <sys/param.h>
  */
 
 #include <sys/param.h>
 
 #include <ufs/ufs/quota.h>
 #include <ufs/ufs/inode.h>
 
 #include <ufs/ufs/quota.h>
 #include <ufs/ufs/inode.h>
+#include <ufs/ufs/ufs_extern.h>
 
 #include <ufs/ffs/fs.h>
 #include <ufs/ffs/ffs_extern.h>
 
 
 #include <ufs/ffs/fs.h>
 #include <ufs/ffs/ffs_extern.h>
 
-/*
- * Bmap converts a the logical block number of a file
- * to its physical block number on the disk. The conversion
- * is done by using the logical block number to index into
- * the array of block pointers described by the dinode.
- */
-int
-ffs_bmap(vp, bn, vpp, bnp)
-       struct vnode *vp;
-       register daddr_t bn;
-       struct vnode **vpp;
-       daddr_t *bnp;
-{
-       register struct inode *ip;
-       register struct fs *fs;
-       register daddr_t nb;
-       struct buf *bp;
-       daddr_t *bap;
-       int i, j, sh;
-       int error;
-
-       /*
-        * Check for underlying vnode requests and ensure that logical
-        * to physical mapping is requested.
-        */
-       ip = VTOI(vp);
-       if (vpp != NULL)
-               *vpp = ip->i_devvp;
-       if (bnp == NULL)
-               return (0);
-       if (bn < 0)
-               return (EFBIG);
-       fs = ip->i_fs;
-
-       /*
-        * 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);
-}
-
 /*
  * Balloc defines the structure of file system storage
  * by allocating the physical blocks on a device given
 /*
  * Balloc defines the structure of file system storage
  * by allocating the physical blocks on a device given
@@ -127,13 +66,15 @@ ffs_balloc(ip, bn, size, cred, 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;
+       struct indir indirs[NIADDR + 2];
        daddr_t newb, lbn, *bap, pref;
        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,
@@ -152,7 +93,7 @@ ffs_balloc(ip, bn, size, cred, bpp, flags)
                        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_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_flag |= IUPD|ICHG;
+                       ip->i_flag |= IN_CHANGE | IN_UPDATE;
                        if (flags & B_SYNC)
                                bwrite(bp);
                        else
                        if (flags & B_SYNC)
                                bwrite(bp);
                        else
@@ -202,13 +143,13 @@ ffs_balloc(ip, bn, size, cred, bpp, flags)
                            nsize, cred, &newb);
                        if (error)
                                return (error);
                            nsize, cred, &newb);
                        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);
        }
@@ -216,28 +157,25 @@ ffs_balloc(ip, bn, size, cred, 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) {
                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;
        if (nb == 0) {
                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;
-               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
                clrbuf(bp);
                /*
                 * Write synchronously so that indirect blocks
@@ -247,25 +185,24 @@ ffs_balloc(ip, bn, size, cred, bpp, flags)
                        ffs_blkfree(ip, nb, fs->fs_bsize);
                        return (error);
                }
                        ffs_blkfree(ip, nb, fs->fs_bsize);
                        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 (nb != 0) {
                        brelse(bp);
                        continue;
@@ -278,7 +215,8 @@ ffs_balloc(ip, bn, size, cred, bpp, flags)
                        return (error);
                }
                nb = newb;
                        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
                clrbuf(nbp);
                /*
                 * Write synchronously so that indirect blocks
@@ -289,51 +227,41 @@ ffs_balloc(ip, bn, size, cred, bpp, flags)
                        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 = ffs_blkpref(ip, lbn, i, &bap[0]);
-               if (error =
-                   ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, &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);
                }
                *bpp = nbp;
                return (0);
@@ -346,7 +274,7 @@ ffs_balloc(ip, bn, size, cred, bpp, flags)
                        return (error);
                }
        } else {
                        return (error);
                }
        } else {
-               nbp = getblk(vp, lbn, fs->fs_bsize);
+               nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
                nbp->b_blkno = fsbtodb(fs, nb);
        }
        *bpp = nbp;
                nbp->b_blkno = fsbtodb(fs, nb);
        }
        *bpp = nbp;