1: /*
   2:  * Copyright (c) 1982, 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	7.1 (Berkeley) 6/5/86
   7:  */
   8: 
   9: #include "param.h"
  10: #include "systm.h"
  11: #include "inode.h"
  12: #include "dir.h"
  13: #include "user.h"
  14: #include "buf.h"
  15: #include "proc.h"
  16: #include "fs.h"
  17: 
  18: /*
  19:  * Bmap defines the structure of file system storage
  20:  * by returning the physical block number on a device given the
  21:  * inode and the logical block number in a file.
  22:  * When convenient, it also leaves the physical
  23:  * block number of the next block of the file in rablock
  24:  * for use in read-ahead.
  25:  */
  26: /*VARARGS3*/
  27: daddr_t
  28: bmap(ip, bn, rwflg, size)
  29:     register struct inode *ip;
  30:     daddr_t bn;
  31:     int rwflg;
  32:     int size;   /* supplied only when rwflg == B_WRITE */
  33: {
  34:     register int i;
  35:     int osize, nsize;
  36:     struct buf *bp, *nbp;
  37:     struct fs *fs;
  38:     int j, sh;
  39:     daddr_t nb, lbn, *bap, pref, blkpref();
  40: 
  41:     if (bn < 0) {
  42:         u.u_error = EFBIG;
  43:         return ((daddr_t)0);
  44:     }
  45:     fs = ip->i_fs;
  46:     rablock = 0;
  47:     rasize = 0;     /* conservative */
  48: 
  49:     /*
  50: 	 * If the next write will extend the file into a new block,
  51: 	 * and the file is currently composed of a fragment
  52: 	 * this fragment has to be extended to be a full block.
  53: 	 */
  54:     nb = lblkno(fs, ip->i_size);
  55:     if (rwflg == B_WRITE && nb < NDADDR && nb < bn) {
  56:         osize = blksize(fs, ip, nb);
  57:         if (osize < fs->fs_bsize && osize > 0) {
  58:             bp = realloccg(ip, ip->i_db[nb],
  59:                 blkpref(ip, nb, (int)nb, &ip->i_db[0]),
  60:                 osize, (int)fs->fs_bsize);
  61:             if (bp == NULL)
  62:                 return ((daddr_t)-1);
  63:             ip->i_size = (nb + 1) * fs->fs_bsize;
  64:             ip->i_db[nb] = dbtofsb(fs, bp->b_blkno);
  65:             ip->i_flag |= IUPD|ICHG;
  66:             bdwrite(bp);
  67:         }
  68:     }
  69:     /*
  70: 	 * The first NDADDR blocks are direct blocks
  71: 	 */
  72:     if (bn < NDADDR) {
  73:         nb = ip->i_db[bn];
  74:         if (rwflg == B_READ) {
  75:             if (nb == 0)
  76:                 return ((daddr_t)-1);
  77:             goto gotit;
  78:         }
  79:         if (nb == 0 || ip->i_size < (bn + 1) * fs->fs_bsize) {
  80:             if (nb != 0) {
  81:                 /* consider need to reallocate a frag */
  82:                 osize = fragroundup(fs, blkoff(fs, ip->i_size));
  83:                 nsize = fragroundup(fs, size);
  84:                 if (nsize <= osize)
  85:                     goto gotit;
  86:                 bp = realloccg(ip, nb,
  87:                     blkpref(ip, bn, (int)bn, &ip->i_db[0]),
  88:                     osize, nsize);
  89:             } else {
  90:                 if (ip->i_size < (bn + 1) * fs->fs_bsize)
  91:                     nsize = fragroundup(fs, size);
  92:                 else
  93:                     nsize = fs->fs_bsize;
  94:                 bp = alloc(ip,
  95:                     blkpref(ip, bn, (int)bn, &ip->i_db[0]),
  96:                     nsize);
  97:             }
  98:             if (bp == NULL)
  99:                 return ((daddr_t)-1);
 100:             nb = dbtofsb(fs, bp->b_blkno);
 101:             if ((ip->i_mode&IFMT) == IFDIR)
 102:                 /*
 103: 				 * Write directory blocks synchronously
 104: 				 * so they never appear with garbage in
 105: 				 * them on the disk.
 106: 				 */
 107:                 bwrite(bp);
 108:             else
 109:                 bdwrite(bp);
 110:             ip->i_db[bn] = nb;
 111:             ip->i_flag |= IUPD|ICHG;
 112:         }
 113: gotit:
 114:         if (bn < NDADDR - 1) {
 115:             rablock = fsbtodb(fs, ip->i_db[bn + 1]);
 116:             rasize = blksize(fs, ip, bn + 1);
 117:         }
 118:         return (nb);
 119:     }
 120: 
 121:     /*
 122: 	 * Determine how many levels of indirection.
 123: 	 */
 124:     pref = 0;
 125:     sh = 1;
 126:     lbn = bn;
 127:     bn -= NDADDR;
 128:     for (j = NIADDR; j>0; j--) {
 129:         sh *= NINDIR(fs);
 130:         if (bn < sh)
 131:             break;
 132:         bn -= sh;
 133:     }
 134:     if (j == 0) {
 135:         u.u_error = EFBIG;
 136:         return ((daddr_t)0);
 137:     }
 138: 
 139:     /*
 140: 	 * fetch the first indirect block
 141: 	 */
 142:     nb = ip->i_ib[NIADDR - j];
 143:     if (nb == 0) {
 144:         if (rwflg == B_READ)
 145:             return ((daddr_t)-1);
 146:         pref = blkpref(ip, lbn, 0, (daddr_t *)0);
 147:             bp = alloc(ip, pref, (int)fs->fs_bsize);
 148:         if (bp == NULL)
 149:             return ((daddr_t)-1);
 150:         nb = dbtofsb(fs, bp->b_blkno);
 151:         /*
 152: 		 * Write synchronously so that indirect blocks
 153: 		 * never point at garbage.
 154: 		 */
 155:         bwrite(bp);
 156:         ip->i_ib[NIADDR - j] = nb;
 157:         ip->i_flag |= IUPD|ICHG;
 158:     }
 159: 
 160:     /*
 161: 	 * fetch through the indirect blocks
 162: 	 */
 163:     for (; j <= NIADDR; j++) {
 164:         bp = bread(ip->i_dev, fsbtodb(fs, nb), (int)fs->fs_bsize);
 165:         if (bp->b_flags & B_ERROR) {
 166:             brelse(bp);
 167:             return ((daddr_t)0);
 168:         }
 169:         bap = bp->b_un.b_daddr;
 170:         sh /= NINDIR(fs);
 171:         i = (bn / sh) % NINDIR(fs);
 172:         nb = bap[i];
 173:         if (nb == 0) {
 174:             if (rwflg==B_READ) {
 175:                 brelse(bp);
 176:                 return ((daddr_t)-1);
 177:             }
 178:             if (pref == 0)
 179:                 if (j < NIADDR)
 180:                     pref = blkpref(ip, lbn, 0,
 181:                         (daddr_t *)0);
 182:                 else
 183:                     pref = blkpref(ip, lbn, i, &bap[0]);
 184:                 nbp = alloc(ip, pref, (int)fs->fs_bsize);
 185:             if (nbp == NULL) {
 186:                 brelse(bp);
 187:                 return ((daddr_t)-1);
 188:             }
 189:             nb = dbtofsb(fs, nbp->b_blkno);
 190:             if (j < NIADDR || (ip->i_mode&IFMT) == IFDIR)
 191:                 /*
 192: 				 * Write synchronously so indirect blocks
 193: 				 * never point at garbage and blocks
 194: 				 * in directories never contain garbage.
 195: 				 */
 196:                 bwrite(nbp);
 197:             else
 198:                 bdwrite(nbp);
 199:             bap[i] = nb;
 200:             bdwrite(bp);
 201:         } else
 202:             brelse(bp);
 203:     }
 204: 
 205:     /*
 206: 	 * calculate read-ahead.
 207: 	 */
 208:     if (i < NINDIR(fs) - 1) {
 209:         rablock = fsbtodb(fs, bap[i+1]);
 210:         rasize = fs->fs_bsize;
 211:     }
 212:     return (nb);
 213: }
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1054
Valid CSS Valid XHTML 1.0 Strict