home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / ufs / ufs_bmap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-08  |  8.7 KB  |  361 lines

  1. /*
  2.  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  *
  33.  *    @(#)ufs_bmap.c    7.13 (Berkeley) 5/8/91
  34.  */
  35.  
  36. #include "param.h"
  37. #include "systm.h"
  38. #include "buf.h"
  39. #include "proc.h"
  40. #include "file.h"
  41. #include "vnode.h"
  42.  
  43. #include "quota.h"
  44. #include "inode.h"
  45. #include "fs.h"
  46.  
  47. /*
  48.  * Bmap converts a the logical block number of a file
  49.  * to its physical block number on the disk. The conversion
  50.  * is done by using the logical block number to index into
  51.  * the array of block pointers described by the dinode.
  52.  */
  53. bmap(ip, bn, bnp)
  54.     register struct inode *ip;
  55.     register daddr_t bn;
  56.     daddr_t    *bnp;
  57. {
  58.     register struct fs *fs;
  59.     register daddr_t nb;
  60.     struct buf *bp;
  61.     daddr_t *bap;
  62.     int i, j, sh;
  63.     int error;
  64.  
  65.     if (bn < 0)
  66.         return (EFBIG);
  67.     fs = ip->i_fs;
  68.  
  69.     /*
  70.      * The first NDADDR blocks are direct blocks
  71.      */
  72.     if (bn < NDADDR) {
  73.         nb = ip->i_db[bn];
  74.         if (nb == 0) {
  75.             *bnp = (daddr_t)-1;
  76.             return (0);
  77.         }
  78.         *bnp = fsbtodb(fs, nb);
  79.         return (0);
  80.     }
  81.     /*
  82.      * Determine the number of levels of indirection.
  83.      */
  84.     sh = 1;
  85.     bn -= NDADDR;
  86.     for (j = NIADDR; j > 0; j--) {
  87.         sh *= NINDIR(fs);
  88.         if (bn < sh)
  89.             break;
  90.         bn -= sh;
  91.     }
  92.     if (j == 0)
  93.         return (EFBIG);
  94.     /*
  95.      * Fetch through the indirect blocks.
  96.      */
  97.     nb = ip->i_ib[NIADDR - j];
  98.     if (nb == 0) {
  99.         *bnp = (daddr_t)-1;
  100.         return (0);
  101.     }
  102.     for (; j <= NIADDR; j++) {
  103.         if (error = bread(ip->i_devvp, fsbtodb(fs, nb),
  104.             (int)fs->fs_bsize, NOCRED, &bp)) {
  105.             brelse(bp);
  106.             return (error);
  107.         }
  108.         bap = bp->b_un.b_daddr;
  109.         sh /= NINDIR(fs);
  110.         i = (bn / sh) % NINDIR(fs);
  111.         nb = bap[i];
  112.         if (nb == 0) {
  113.             *bnp = (daddr_t)-1;
  114.             brelse(bp);
  115.             return (0);
  116.         }
  117.         brelse(bp);
  118.     }
  119.     *bnp = fsbtodb(fs, nb);
  120.     return (0);
  121. }
  122.  
  123. /*
  124.  * Balloc defines the structure of file system storage
  125.  * by allocating the physical blocks on a device given
  126.  * the inode and the logical block number in a file.
  127.  */
  128. balloc(ip, bn, size, bpp, flags)
  129.     register struct inode *ip;
  130.     register daddr_t bn;
  131.     int size;
  132.     struct buf **bpp;
  133.     int flags;
  134. {
  135.     register struct fs *fs;
  136.     register daddr_t nb;
  137.     struct buf *bp, *nbp;
  138.     struct vnode *vp = ITOV(ip);
  139.     int osize, nsize, i, j, sh, error;
  140.     daddr_t newb, lbn, *bap, pref, blkpref();
  141.  
  142.     *bpp = (struct buf *)0;
  143.     if (bn < 0)
  144.         return (EFBIG);
  145.     fs = ip->i_fs;
  146.  
  147.     /*
  148.      * If the next write will extend the file into a new block,
  149.      * and the file is currently composed of a fragment
  150.      * this fragment has to be extended to be a full block.
  151.      */
  152.     nb = lblkno(fs, ip->i_size);
  153.     if (nb < NDADDR && nb < bn) {
  154.         osize = blksize(fs, ip, nb);
  155.         if (osize < fs->fs_bsize && osize > 0) {
  156.             error = realloccg(ip, nb,
  157.                 blkpref(ip, nb, (int)nb, &ip->i_db[0]),
  158.                 osize, (int)fs->fs_bsize, &bp);
  159.             if (error)
  160.                 return (error);
  161.             ip->i_size = (nb + 1) * fs->fs_bsize;
  162.             vnode_pager_setsize(ITOV(ip), (u_long)ip->i_size);
  163.             ip->i_db[nb] = dbtofsb(fs, bp->b_blkno);
  164.             ip->i_flag |= IUPD|ICHG;
  165.             if (flags & B_SYNC)
  166.                 bwrite(bp);
  167.             else
  168.                 bawrite(bp);
  169.         }
  170.     }
  171.     /*
  172.      * The first NDADDR blocks are direct blocks
  173.      */
  174.     if (bn < NDADDR) {
  175.         nb = ip->i_db[bn];
  176.         if (nb != 0 && ip->i_size >= (bn + 1) * fs->fs_bsize) {
  177.             error = bread(vp, bn, fs->fs_bsize, NOCRED, &bp);
  178.             if (error) {
  179.                 brelse(bp);
  180.                 return (error);
  181.             }
  182.             *bpp = bp;
  183.             return (0);
  184.         }
  185.         if (nb != 0) {
  186.             /*
  187.              * Consider need to reallocate a fragment.
  188.              */
  189.             osize = fragroundup(fs, blkoff(fs, ip->i_size));
  190.             nsize = fragroundup(fs, size);
  191.             if (nsize <= osize) {
  192.                 error = bread(vp, bn, osize, NOCRED, &bp);
  193.                 if (error) {
  194.                     brelse(bp);
  195.                     return (error);
  196.                 }
  197.             } else {
  198.                 error = realloccg(ip, bn,
  199.                     blkpref(ip, bn, (int)bn, &ip->i_db[0]),
  200.                     osize, nsize, &bp);
  201.                 if (error)
  202.                     return (error);
  203.             }
  204.         } else {
  205.             if (ip->i_size < (bn + 1) * fs->fs_bsize)
  206.                 nsize = fragroundup(fs, size);
  207.             else
  208.                 nsize = fs->fs_bsize;
  209.             error = alloc(ip, bn,
  210.                 blkpref(ip, bn, (int)bn, &ip->i_db[0]),
  211.                 nsize, &newb);
  212.             if (error)
  213.                 return (error);
  214.             bp = getblk(vp, bn, nsize);
  215.             bp->b_blkno = fsbtodb(fs, newb);
  216.             if (flags & B_CLRBUF)
  217.                 clrbuf(bp);
  218.         }
  219.         ip->i_db[bn] = dbtofsb(fs, bp->b_blkno);
  220.         ip->i_flag |= IUPD|ICHG;
  221.         *bpp = bp;
  222.         return (0);
  223.     }
  224.     /*
  225.      * Determine the number of levels of indirection.
  226.      */
  227.     pref = 0;
  228.     sh = 1;
  229.     lbn = bn;
  230.     bn -= NDADDR;
  231.     for (j = NIADDR; j > 0; j--) {
  232.         sh *= NINDIR(fs);
  233.         if (bn < sh)
  234.             break;
  235.         bn -= sh;
  236.     }
  237.     if (j == 0)
  238.         return (EFBIG);
  239.     /*
  240.      * Fetch the first indirect block allocating if necessary.
  241.      */
  242.     nb = ip->i_ib[NIADDR - j];
  243.     if (nb == 0) {
  244.         pref = blkpref(ip, lbn, 0, (daddr_t *)0);
  245.             if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb))
  246.             return (error);
  247.         nb = newb;
  248.         bp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize);
  249.         clrbuf(bp);
  250.         /*
  251.          * Write synchronously so that indirect blocks
  252.          * never point at garbage.
  253.          */
  254.         if (error = bwrite(bp)) {
  255.             blkfree(ip, nb, fs->fs_bsize);
  256.             return (error);
  257.         }
  258.         ip->i_ib[NIADDR - j] = nb;
  259.         ip->i_flag |= IUPD|ICHG;
  260.     }
  261.     /*
  262.      * Fetch through the indirect blocks, allocating as necessary.
  263.      */
  264.     for (; ; j++) {
  265.         error = bread(ip->i_devvp, fsbtodb(fs, nb),
  266.             (int)fs->fs_bsize, NOCRED, &bp);
  267.         if (error) {
  268.             brelse(bp);
  269.             return (error);
  270.         }
  271.         bap = bp->b_un.b_daddr;
  272.         sh /= NINDIR(fs);
  273.         i = (bn / sh) % NINDIR(fs);
  274.         nb = bap[i];
  275.         if (j == NIADDR)
  276.             break;
  277.         if (nb != 0) {
  278.             brelse(bp);
  279.             continue;
  280.         }
  281.         if (pref == 0)
  282.             pref = blkpref(ip, lbn, 0, (daddr_t *)0);
  283.         if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) {
  284.             brelse(bp);
  285.             return (error);
  286.         }
  287.         nb = newb;
  288.         nbp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize);
  289.         clrbuf(nbp);
  290.         /*
  291.          * Write synchronously so that indirect blocks
  292.          * never point at garbage.
  293.          */
  294.         if (error = bwrite(nbp)) {
  295.             blkfree(ip, nb, fs->fs_bsize);
  296.             brelse(bp);
  297.             return (error);
  298.         }
  299.         bap[i] = nb;
  300.         /*
  301.          * If required, write synchronously, otherwise use
  302.          * delayed write. If this is the first instance of
  303.          * the delayed write, reassociate the buffer with the
  304.          * file so it will be written if the file is sync'ed.
  305.          */
  306.         if (flags & B_SYNC) {
  307.             bwrite(bp);
  308.         } else if (bp->b_flags & B_DELWRI) {
  309.             bdwrite(bp);
  310.         } else {
  311.             bdwrite(bp);
  312.             reassignbuf(bp, vp);
  313.         }
  314.     }
  315.     /*
  316.      * Get the data block, allocating if necessary.
  317.      */
  318.     if (nb == 0) {
  319.         pref = blkpref(ip, lbn, i, &bap[0]);
  320.         if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) {
  321.             brelse(bp);
  322.             return (error);
  323.         }
  324.         nb = newb;
  325.         nbp = getblk(vp, lbn, fs->fs_bsize);
  326.         nbp->b_blkno = fsbtodb(fs, nb);
  327.         if (flags & B_CLRBUF)
  328.             clrbuf(nbp);
  329.         bap[i] = nb;
  330.         /*
  331.          * If required, write synchronously, otherwise use
  332.          * delayed write. If this is the first instance of
  333.          * the delayed write, reassociate the buffer with the
  334.          * file so it will be written if the file is sync'ed.
  335.          */
  336.         if (flags & B_SYNC) {
  337.             bwrite(bp);
  338.         } else if (bp->b_flags & B_DELWRI) {
  339.             bdwrite(bp);
  340.         } else {
  341.             bdwrite(bp);
  342.             reassignbuf(bp, vp);
  343.         }
  344.         *bpp = nbp;
  345.         return (0);
  346.     }
  347.     brelse(bp);
  348.     if (flags & B_CLRBUF) {
  349.         error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp);
  350.         if (error) {
  351.             brelse(nbp);
  352.             return (error);
  353.         }
  354.     } else {
  355.         nbp = getblk(vp, lbn, fs->fs_bsize);
  356.         nbp->b_blkno = fsbtodb(fs, nb);
  357.     }
  358.     *bpp = nbp;
  359.     return (0);
  360. }
  361.