1: /*
   2:  * Copyright (c) 1986 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  *
   6:  *	@(#)ufs_bmap.c	1.2 (2.11BSD) 1996/9/19
   7:  */
   8: 
   9: #include "param.h"
  10: #include "../machine/seg.h"
  11: 
  12: #include "systm.h"
  13: #include "conf.h"
  14: #include "dir.h"
  15: #include "inode.h"
  16: #include "user.h"
  17: #include "buf.h"
  18: #include "fs.h"
  19: #include "mount.h"
  20: #include "uio.h"
  21: 
  22: /*
  23:  * Bmap defines the structure of file system storage
  24:  * by returning the physical block number on a device given the
  25:  * inode and the logical block number in a file.
  26:  * When convenient, it also leaves the physical
  27:  * block number of the next block of the file in rablock
  28:  * for use in read-ahead.
  29:  */
  30: daddr_t
  31: bmap(ip, bn, rwflg, flags)
  32:     register struct inode *ip;
  33:     daddr_t bn;
  34:     int rwflg, flags;
  35: {
  36:     register int i;
  37:     register struct buf *bp;
  38:     struct buf *nbp;
  39:     int j, sh;
  40:     daddr_t nb, *bap, ra;
  41:     int async = ip->i_fs->fs_flags & MNT_ASYNC;
  42: 
  43:     if (bn < 0) {
  44:         u.u_error = EFBIG;
  45:         return((daddr_t)0);
  46:     }
  47:     ra = rablock = 0;
  48: 
  49:     /*
  50: 	 * blocks 0..NADDR-4 are direct blocks
  51: 	 */
  52:     if (bn < NADDR-3) {
  53:         i = bn;
  54:         nb = ip->i_addr[i];
  55:         if (nb == 0) {
  56:             if (rwflg == B_READ || (bp = balloc(ip, flags)) == NULL)
  57:                 return((daddr_t)-1);
  58:             nb = dbtofsb(bp->b_blkno);
  59: /*
  60:  * directory blocks are usually the only thing written synchronously at this
  61:  * point (so they never appear with garbage in them on the disk).  This is
  62:  * overridden if the filesystem was mounted 'async'.
  63: */
  64:             if (flags & B_SYNC)
  65:                 bwrite(bp);
  66:             else
  67:                 bdwrite(bp);
  68:             ip->i_addr[i] = nb;
  69:             ip->i_flag |= IUPD|ICHG;
  70:         }
  71:         if (i < NADDR-4)
  72:             rablock = ip->i_addr[i+1];
  73:         return(nb);
  74:     }
  75: 
  76:     /*
  77: 	 * addresses NADDR-3, NADDR-2, and NADDR-1
  78: 	 * have single, double, triple indirect blocks.
  79: 	 * the first step is to determine
  80: 	 * how many levels of indirection.
  81: 	 */
  82:     sh = 0;
  83:     nb = 1;
  84:     bn -= NADDR-3;
  85:     for (j = 3;j > 0;j--) {
  86:         sh += NSHIFT;
  87:         nb <<= NSHIFT;
  88:         if (bn < nb)
  89:             break;
  90:         bn -= nb;
  91:     }
  92:     if (j == 0) {
  93:         u.u_error = EFBIG;
  94:         return((daddr_t)0);
  95:     }
  96: 
  97:     /*
  98: 	 * fetch the first indirect block
  99: 	 */
 100:     nb = ip->i_addr[NADDR-j];
 101:     if (nb == 0) {
 102:         if (rwflg == B_READ || (bp = balloc(ip, flags | B_CLRBUF)) == NULL)
 103:             return((daddr_t) -1);
 104:         nb = dbtofsb(bp->b_blkno);
 105:         /*
 106: 		 * Write synchronously if requested so that indirect blocks
 107: 		 * never point at garbage.
 108: 		 */
 109:         if (async)
 110:             bdwrite(bp);
 111:         else
 112:             bwrite(bp);
 113:         ip->i_addr[NADDR-j] = nb;
 114:         ip->i_flag |= IUPD|ICHG;
 115:     }
 116: 
 117:     /*
 118: 	 * fetch through the indirect blocks
 119: 	 */
 120:     for(;j <= 3;j++) {
 121:         bp = bread(ip->i_dev, nb);
 122:         if ((bp->b_flags & B_ERROR) || bp->b_resid) {
 123:             brelse(bp);
 124:             return((daddr_t)0);
 125:         }
 126:         bap = (daddr_t *) mapin(bp);
 127:         sh -= NSHIFT;
 128:         i = (bn>>sh) & NMASK;
 129:         nb = bap[i];
 130:         /*
 131: 		 * calculate read-ahead
 132: 		 */
 133:         if (i < NINDIR-1)
 134:             ra = bap[i+1];
 135:         mapout(bp);
 136:         if (nb == 0) {
 137:             if (rwflg == B_READ || (nbp = balloc(ip, flags | B_CLRBUF)) == NULL) {
 138:                 brelse(bp);
 139:                 return((daddr_t) -1);
 140:             }
 141:             nb = dbtofsb(nbp->b_blkno);
 142: /*
 143:  * Write synchronously so indirect blocks never point at garbage and blocks
 144:  * in directories never contain garbage.  This check used to be based on the
 145:  * type of inode, if it was a directory then 'sync' writes were done.  See the
 146:  * comments earlier about filesystems being mounted 'async'.
 147: */
 148:             if (!async && (j < 3 || (flags & B_SYNC)))
 149:                 bwrite(nbp);
 150:             else
 151:                 bdwrite(nbp);
 152:             bap = (daddr_t *) mapin(bp);
 153:             bap[i] = nb;
 154:             mapout(bp);
 155:             bdwrite(bp);
 156:         } else
 157:             brelse(bp);
 158:     }
 159:     rablock = ra;
 160:     return(nb);
 161: }

Defined functions

Last modified: 1996-09-20
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2700
Valid CSS Valid XHTML 1.0 Strict