merge in vnodes
[unix-history] / usr / src / sys / ufs / ffs / ffs_balloc.c
index b481675..beec1b0 100644 (file)
@@ -1,19 +1,31 @@
 /*
 /*
- * Copyright (c) 1982, 1986 Regents of the University of California.
- * All rights reserved.  The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+ * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
+ * All rights reserved.
  *
  *
- *     @(#)ffs_balloc.c        7.2 (Berkeley) %G%
+ * 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.
+ *
+ *     @(#)ffs_balloc.c        7.3 (Berkeley) %G%
  */
 
 #include "param.h"
 #include "systm.h"
  */
 
 #include "param.h"
 #include "systm.h"
-#include "inode.h"
-#include "dir.h"
 #include "user.h"
 #include "buf.h"
 #include "proc.h"
 #include "user.h"
 #include "buf.h"
 #include "proc.h"
-#include "fs.h"
+#include "file.h"
+#include "vnode.h"
+#include "../ufs/inode.h"
+#include "../ufs/fs.h"
 
 /*
  * Bmap defines the structure of file system storage
 
 /*
  * Bmap defines the structure of file system storage
  * block number of the next block of the file in rablock
  * for use in read-ahead.
  */
  * block number of the next block of the file in rablock
  * for use in read-ahead.
  */
-/*VARARGS3*/
-daddr_t
-bmap(ip, bn, rwflg, size)
+bmap(ip, bn, bnp, rablockp, rasizep)
        register struct inode *ip;
        register struct inode *ip;
-       daddr_t bn;
-       int rwflg;
-       int size;       /* supplied only when rwflg == B_WRITE */
+       register daddr_t bn;
+       daddr_t *bnp;
+       daddr_t *rablockp;
+       int *rasizep;
 {
 {
-       register int i;
-       int osize, nsize;
-       struct buf *bp, *nbp;
-       struct fs *fs;
-       int j, sh;
-       daddr_t nb, lbn, *bap, pref, blkpref();
+       register struct fs *fs;
+       register daddr_t nb;
+       struct buf *bp;
+       daddr_t *bap;
+       int i, j, sh;
+       int error;
+
+       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);
+               }
+               if (rablockp && rasizep) {
+                       if (bn < NDADDR - 1) {
+                               *rablockp = fsbtodb(fs, ip->i_db[bn + 1]);
+                               *rasizep = blksize(fs, ip, bn + 1);
+                       } else {
+                               *rablockp = 0;
+                               *rasizep = 0;
+                       }
+               }
+               *bnp = fsbtodb(fs, nb);
+               return (0);
+       }
+
+       /*
+        * Determine how many 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);
 
 
-       if (bn < 0) {
-               u.u_error = EFBIG;
-               return ((daddr_t)0);
+       /*
+        * fetch the first indirect block
+        */
+       nb = ip->i_ib[NIADDR - j];
+       if (nb == 0) {
+               *bnp = (daddr_t)-1;
+               return (0);
        }
        }
+
+       /*
+        * fetch through the indirect blocks
+        */
+       for (; j <= NIADDR; j++) {
+               if (error = bread(ip->i_devvp, fsbtodb(fs, nb),
+                   (int)fs->fs_bsize, &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);
+               }
+       }
+
+       /*
+        * calculate read-ahead.
+        */
+       if (rablockp && rasizep) {
+               if (i < NINDIR(fs) - 1) {
+                       *rablockp = fsbtodb(fs, bap[i + 1]);
+                       *rasizep = fs->fs_bsize;
+               } else {
+                       *rablockp = 0;
+                       *rasizep = 0;
+               }
+       }
+       *bnp = fsbtodb(fs, nb);
+       brelse(bp);
+       return (0);
+}
+
+/*
+ * Balloc 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.
+ * When unallocated entries are found, new physical blocks
+ * are allocated.
+ */
+balloc(ip, bn, size, bnp, flags)
+       register struct inode *ip;
+       register daddr_t bn;
+       int size;
+       daddr_t *bnp;
+       int flags;
+{
+       register struct fs *fs;
+       register daddr_t nb;
+       struct buf *bp, *nbp;
+       int osize, nsize, i, j, sh, error;
+       daddr_t lbn, *bap, pref, blkpref();
+
+       if (bn < 0)
+               return (EFBIG);
        fs = ip->i_fs;
        fs = ip->i_fs;
-       rablock = 0;
-       rasize = 0;             /* conservative */
 
        /*
         * If the next write will extend the file into a new block,
 
        /*
         * If the next write will extend the file into a new block,
@@ -52,14 +165,16 @@ bmap(ip, bn, rwflg, size)
         * this fragment has to be extended to be a full block.
         */
        nb = lblkno(fs, ip->i_size);
         * this fragment has to be extended to be a full block.
         */
        nb = lblkno(fs, ip->i_size);
-       if (rwflg == B_WRITE && nb < NDADDR && nb < bn) {
+       if (nb < NDADDR && nb < bn) {
                osize = blksize(fs, ip, nb);
                if (osize < fs->fs_bsize && osize > 0) {
                osize = blksize(fs, ip, nb);
                if (osize < fs->fs_bsize && osize > 0) {
-                       bp = realloccg(ip, ip->i_db[nb],
+                       error = realloccg(ip, ip->i_db[nb],
                                blkpref(ip, nb, (int)nb, &ip->i_db[0]),
                                blkpref(ip, nb, (int)nb, &ip->i_db[0]),
-                               osize, (int)fs->fs_bsize);
-                       if (bp == NULL)
-                               return ((daddr_t)-1);
+                               osize, (int)fs->fs_bsize, &bp);
+                       if (error) {
+                               *bnp = (daddr_t)-1;
+                               return (error);
+                       }
                        ip->i_size = (nb + 1) * fs->fs_bsize;
                        ip->i_db[nb] = dbtofsb(fs, bp->b_blkno);
                        ip->i_flag |= IUPD|ICHG;
                        ip->i_size = (nb + 1) * fs->fs_bsize;
                        ip->i_db[nb] = dbtofsb(fs, bp->b_blkno);
                        ip->i_flag |= IUPD|ICHG;
@@ -71,11 +186,6 @@ bmap(ip, bn, rwflg, size)
         */
        if (bn < NDADDR) {
                nb = ip->i_db[bn];
         */
        if (bn < NDADDR) {
                nb = ip->i_db[bn];
-               if (rwflg == B_READ) {
-                       if (nb == 0)
-                               return ((daddr_t)-1);
-                       goto gotit;
-               }
                if (nb == 0 || ip->i_size < (bn + 1) * fs->fs_bsize) {
                        if (nb != 0) {
                                /* consider need to reallocate a frag */
                if (nb == 0 || ip->i_size < (bn + 1) * fs->fs_bsize) {
                        if (nb != 0) {
                                /* consider need to reallocate a frag */
@@ -83,39 +193,41 @@ bmap(ip, bn, rwflg, size)
                                nsize = fragroundup(fs, size);
                                if (nsize <= osize)
                                        goto gotit;
                                nsize = fragroundup(fs, size);
                                if (nsize <= osize)
                                        goto gotit;
-                               bp = realloccg(ip, nb,
+                               error = realloccg(ip, nb,
                                        blkpref(ip, bn, (int)bn, &ip->i_db[0]),
                                        blkpref(ip, bn, (int)bn, &ip->i_db[0]),
-                                       osize, nsize);
+                                       osize, nsize, &bp);
                        } else {
                                if (ip->i_size < (bn + 1) * fs->fs_bsize)
                                        nsize = fragroundup(fs, size);
                                else
                                        nsize = fs->fs_bsize;
                        } else {
                                if (ip->i_size < (bn + 1) * fs->fs_bsize)
                                        nsize = fragroundup(fs, size);
                                else
                                        nsize = fs->fs_bsize;
-                               bp = alloc(ip,
+                               error = alloc(ip,
                                        blkpref(ip, bn, (int)bn, &ip->i_db[0]),
                                        blkpref(ip, bn, (int)bn, &ip->i_db[0]),
-                                       nsize);
+                                       nsize, &bp, flags);
+                       }
+                       if (error) {
+                               *bnp = (daddr_t)-1;
+                               return (error);
                        }
                        }
-                       if (bp == NULL)
-                               return ((daddr_t)-1);
                        nb = dbtofsb(fs, bp->b_blkno);
                        nb = dbtofsb(fs, bp->b_blkno);
-                       if ((ip->i_mode&IFMT) == IFDIR)
+                       if ((ip->i_mode & IFMT) == IFDIR)
                                /*
                                 * Write directory blocks synchronously
                                 * so they never appear with garbage in
                                 * them on the disk.
                                /*
                                 * Write directory blocks synchronously
                                 * so they never appear with garbage in
                                 * them on the disk.
+                                * 
+                                * NB: Should free space and return error
+                                * if bwrite returns an error.
                                 */
                                 */
-                               bwrite(bp);
+                               error = bwrite(bp);
                        else
                                bdwrite(bp);
                        ip->i_db[bn] = nb;
                        ip->i_flag |= IUPD|ICHG;
                }
 gotit:
                        else
                                bdwrite(bp);
                        ip->i_db[bn] = nb;
                        ip->i_flag |= IUPD|ICHG;
                }
 gotit:
-               if (bn < NDADDR - 1) {
-                       rablock = fsbtodb(fs, ip->i_db[bn + 1]);
-                       rasize = blksize(fs, ip, bn + 1);
-               }
-               return (nb);
+               *bnp = fsbtodb(fs, nb);
+               return (0);
        }
 
        /*
        }
 
        /*
@@ -125,34 +237,35 @@ gotit:
        sh = 1;
        lbn = bn;
        bn -= NDADDR;
        sh = 1;
        lbn = bn;
        bn -= NDADDR;
-       for (j = NIADDR; j>0; j--) {
+       for (j = NIADDR; j > 0; j--) {
                sh *= NINDIR(fs);
                if (bn < sh)
                        break;
                bn -= sh;
        }
                sh *= NINDIR(fs);
                if (bn < sh)
                        break;
                bn -= sh;
        }
-       if (j == 0) {
-               u.u_error = EFBIG;
-               return ((daddr_t)0);
-       }
+       if (j == 0)
+               return (EFBIG);
 
        /*
         * fetch the first indirect block
         */
        nb = ip->i_ib[NIADDR - j];
        if (nb == 0) {
 
        /*
         * fetch the first indirect block
         */
        nb = ip->i_ib[NIADDR - j];
        if (nb == 0) {
-               if (rwflg == B_READ)
-                       return ((daddr_t)-1);
                pref = blkpref(ip, lbn, 0, (daddr_t *)0);
                pref = blkpref(ip, lbn, 0, (daddr_t *)0);
-               bp = alloc(ip, pref, (int)fs->fs_bsize);
-               if (bp == NULL)
-                       return ((daddr_t)-1);
+               error = alloc(ip, pref, (int)fs->fs_bsize, &bp, B_CLRBUF);
+               if (error) {
+                       *bnp = (daddr_t)-1;
+                       return (error);
+               }
                nb = dbtofsb(fs, bp->b_blkno);
                /*
                 * Write synchronously so that indirect blocks
                 * never point at garbage.
                nb = dbtofsb(fs, bp->b_blkno);
                /*
                 * Write synchronously so that indirect blocks
                 * never point at garbage.
+                * 
+                * NB: Should free space and return error
+                * if bwrite returns an error.
                 */
                 */
-               bwrite(bp);
+               error = bwrite(bp);
                ip->i_ib[NIADDR - j] = nb;
                ip->i_flag |= IUPD|ICHG;
        }
                ip->i_ib[NIADDR - j] = nb;
                ip->i_flag |= IUPD|ICHG;
        }
@@ -165,40 +278,40 @@ gotit:
                bp = bread(ip->i_dev, fsbtodb(fs, nb), (int)fs->fs_bsize,
                    fs->fs_dbsize);
 #else SECSIZE
                bp = bread(ip->i_dev, fsbtodb(fs, nb), (int)fs->fs_bsize,
                    fs->fs_dbsize);
 #else SECSIZE
-               bp = bread(ip->i_dev, fsbtodb(fs, nb), (int)fs->fs_bsize);
-#endif SECSIZE
-               if (bp->b_flags & B_ERROR) {
+               if (error = bread(ip->i_devvp, fsbtodb(fs, nb),
+                   (int)fs->fs_bsize, &bp)) {
                        brelse(bp);
                        brelse(bp);
-                       return ((daddr_t)0);
+                       return (error);
                }
                bap = bp->b_un.b_daddr;
                sh /= NINDIR(fs);
                i = (bn / sh) % NINDIR(fs);
                nb = bap[i];
                if (nb == 0) {
                }
                bap = bp->b_un.b_daddr;
                sh /= NINDIR(fs);
                i = (bn / sh) % NINDIR(fs);
                nb = bap[i];
                if (nb == 0) {
-                       if (rwflg==B_READ) {
-                               brelse(bp);
-                               return ((daddr_t)-1);
-                       }
                        if (pref == 0)
                                if (j < NIADDR)
                                        pref = blkpref(ip, lbn, 0,
                                                (daddr_t *)0);
                                else
                                        pref = blkpref(ip, lbn, i, &bap[0]);
                        if (pref == 0)
                                if (j < NIADDR)
                                        pref = blkpref(ip, lbn, 0,
                                                (daddr_t *)0);
                                else
                                        pref = blkpref(ip, lbn, i, &bap[0]);
-                       nbp = alloc(ip, pref, (int)fs->fs_bsize);
-                       if (nbp == NULL) {
+                       error = alloc(ip, pref, (int)fs->fs_bsize, &nbp,
+                               (j < NIADDR) ? B_CLRBUF : flags);
+                       if (error) {
                                brelse(bp);
                                brelse(bp);
-                               return ((daddr_t)-1);
+                               *bnp = (daddr_t)-1;
+                               return (error);
                        }
                        nb = dbtofsb(fs, nbp->b_blkno);
                        }
                        nb = dbtofsb(fs, nbp->b_blkno);
-                       if (j < NIADDR || (ip->i_mode&IFMT) == IFDIR)
+                       if (j < NIADDR || (ip->i_mode & IFMT) == IFDIR)
                                /*
                                 * Write synchronously so indirect blocks
                                 * never point at garbage and blocks
                                 * in directories never contain garbage.
                                /*
                                 * Write synchronously so indirect blocks
                                 * never point at garbage and blocks
                                 * in directories never contain garbage.
+                                * 
+                                * NB: Should free space and return error
+                                * if bwrite returns an error.
                                 */
                                 */
-                               bwrite(nbp);
+                               error = bwrite(nbp);
                        else
                                bdwrite(nbp);
                        bap[i] = nb;
                        else
                                bdwrite(nbp);
                        bap[i] = nb;
@@ -207,12 +320,6 @@ gotit:
                        brelse(bp);
        }
 
                        brelse(bp);
        }
 
-       /*
-        * calculate read-ahead.
-        */
-       if (i < NINDIR(fs) - 1) {
-               rablock = fsbtodb(fs, bap[i+1]);
-               rasize = fs->fs_bsize;
-       }
-       return (nb);
+       *bnp = fsbtodb(fs, nb);
+       return (0);
 }
 }