1: /*
   2:  *	SCCS id	@(#)subr.c	2.1 (Berkeley)	9/4/83
   3:  */
   4: 
   5: #include "param.h"
   6: #include <sys/systm.h>
   7: #include <sys/conf.h>
   8: #include <sys/inode.h>
   9: #include <sys/dir.h>
  10: #include <sys/user.h>
  11: #include <sys/buf.h>
  12: #include <sys/quota.h>
  13: 
  14: #ifndef UCB_QUOTAS
  15: #define qalloc(x,y) alloc(y)
  16: #endif
  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: daddr_t
  27: bmap(ip, bn, rwflg)
  28: register struct inode *ip;
  29: daddr_t bn;
  30: {
  31:     register i;
  32:     register struct buf *bp, *nbp;
  33:     int j, sh;
  34:     daddr_t nb, *bap, ra;
  35:     dev_t dev;
  36: 
  37:     if(bn < 0) {
  38:         u.u_error = EFBIG;
  39:         return((daddr_t)0);
  40:     }
  41:     dev = ip->i_dev;
  42:     ra = rablock = 0;
  43: 
  44:     /*
  45: 	 * blocks 0..NADDR-4 are direct blocks
  46: 	 */
  47:     if(bn < NADDR-3) {
  48:         i = bn;
  49:         nb = ip->i_un.i_addr[i];
  50:         if (nb == 0) {
  51:             if (rwflg == B_READ || (bp = qalloc(ip, dev)) == NULL)
  52:                 return((daddr_t)-1);
  53:             nb = dbtofsb(bp->b_blkno);
  54: #ifdef UCB_FSFIX
  55:             if ((ip->i_mode&IFMT) == IFDIR)
  56:                 /*
  57: 				 * Write directory blocks synchronously
  58: 				 * so they never appear with garbage in
  59: 				 * them on the disk.
  60: 				 */
  61:                 bwrite(bp);
  62:             else
  63: #endif
  64:                 bdwrite(bp);
  65:             ip->i_un.i_addr[i] = nb;
  66:             ip->i_flag |= IUPD|ICHG;
  67:         }
  68:         if(i < NADDR-4)
  69:             rablock = ip->i_un.i_addr[i+1];
  70:         return(nb);
  71:     }
  72: 
  73:     /*
  74: 	 * addresses NADDR-3, NADDR-2, and NADDR-1
  75: 	 * have single, double, triple indirect blocks.
  76: 	 * the first step is to determine
  77: 	 * how many levels of indirection.
  78: 	 */
  79:     sh = 0;
  80:     nb = 1;
  81:     bn -= NADDR-3;
  82:     for(j=3; j>0; j--) {
  83:         sh += NSHIFT;
  84:         nb <<= NSHIFT;
  85:         if(bn < nb)
  86:             break;
  87:         bn -= nb;
  88:     }
  89:     if(j == 0) {
  90:         u.u_error = EFBIG;
  91:         return((daddr_t)0);
  92:     }
  93: 
  94:     /*
  95: 	 * fetch the first indirect block
  96: 	 */
  97:     nb = ip->i_un.i_addr[NADDR-j];
  98:     if(nb == 0) {
  99:         if (rwflg == B_READ || (bp = qalloc(ip, dev)) == NULL)
 100:             return((daddr_t) -1);
 101:         nb = dbtofsb(bp->b_blkno);
 102: #ifdef UCB_FSFIX
 103:         /*
 104: 		 * Write synchronously so that indirect blocks
 105: 		 * never point at garbage.
 106: 		 */
 107:         bwrite(bp);
 108: #else
 109:         bdwrite(bp);
 110: #endif
 111:         ip->i_un.i_addr[NADDR-j] = nb;
 112:         ip->i_flag |= IUPD|ICHG;
 113:     }
 114: 
 115:     /*
 116: 	 * fetch through the indirect blocks
 117: 	 */
 118:     for(; j<=3; j++) {
 119:         bp = bread(dev, nb);
 120:         if((bp->b_flags & B_ERROR) || bp->b_resid) {
 121:             brelse(bp);
 122:             return((daddr_t)0);
 123:         }
 124:         bap = (daddr_t *) mapin(bp);
 125:         sh -= NSHIFT;
 126:         i = (bn>>sh) & NMASK;
 127:         nb = bap[i];
 128:         /*
 129: 		 * calculate read-ahead
 130: 		 */
 131:         if(i < NINDIR-1)
 132:             ra = bap[i+1];
 133:         mapout(bp);
 134:         if(nb == 0) {
 135:             if(rwflg == B_READ || (nbp = qalloc(ip, dev)) == NULL) {
 136:                 brelse(bp);
 137:                 return((daddr_t) -1);
 138:             }
 139:             nb = dbtofsb(nbp->b_blkno);
 140: #ifdef UCB_FSFIX
 141:             if (j < 3 || (ip->i_mode&IFMT) == IFDIR)
 142:                 /*
 143: 				 * Write synchronously so indirect blocks
 144: 				 * never point at garbage and blocks
 145: 				 * in directories never contain garbage.
 146: 				 */
 147:                 bwrite(nbp);
 148:             else
 149: #endif
 150:                 bdwrite(nbp);
 151:             bap = (daddr_t) mapin(bp);
 152:             bap[i] = nb;
 153:             mapout(bp);
 154:             bdwrite(bp);
 155:         } else
 156:             brelse(bp);
 157:     }
 158: 
 159:     rablock = ra;
 160:     return(nb);
 161: }
 162: 
 163: /*
 164:  * Pass back  c  to the user at his location u_base;
 165:  * update u_base, u_count, and u_offset.  Return -1
 166:  * on the last character of the user's read.
 167:  * u_base is in the user address space unless u_segflg is 1.
 168:  */
 169: passc(c)
 170: register c;
 171: {
 172:     register id;
 173: 
 174:     if((id = u.u_segflg) == 1)
 175:         *u.u_base = c;
 176:     else
 177:         if(id?suibyte(u.u_base, c):subyte(u.u_base, c) < 0) {
 178:             u.u_error = EFAULT;
 179:             return(-1);
 180:         }
 181:     u.u_count--;
 182:     u.u_offset++;
 183:     u.u_base++;
 184:     return(u.u_count == 0? -1: 0);
 185: }
 186: 
 187: /*
 188:  * Pick up and return the next character from the user's
 189:  * write call at location u_base;
 190:  * update u_base, u_count, and u_offset.  Return -1
 191:  * when u_count is exhausted.  u_base is in the user's
 192:  * address space unless u_segflg is 1.
 193:  */
 194: cpass()
 195: {
 196:     register c, id;
 197: 
 198:     if(u.u_count == 0)
 199:         return(-1);
 200:     if((id = u.u_segflg) == 1)
 201:         c = *u.u_base;
 202:     else
 203:         if((c = id==0?fubyte(u.u_base):fuibyte(u.u_base)) < 0) {
 204:             u.u_error = EFAULT;
 205:             return(-1);
 206:         }
 207:     u.u_count--;
 208:     u.u_offset++;
 209:     u.u_base++;
 210:     return(c&0377);
 211: }
 212: 
 213: /*
 214:  * Routine which sets a user error; placed in
 215:  * illegal entries in the bdevsw and cdevsw tables.
 216:  */
 217: nodev()
 218: {
 219: 
 220:     u.u_error = ENODEV;
 221: }
 222: 
 223: /*
 224:  * copy count bytes from from to to.
 225:  */
 226: bcopy(from, to, count)
 227: register caddr_t from, to;
 228: register count;
 229: {
 230:     if ((from|to|count) & 1)     /* copy by bytes */
 231:         while (count--)
 232:             *to++ = *from++;
 233:     else {              /* copy by words */
 234:         count >>= 1;
 235:         while (count--)
 236:             *((short *)to)++ = *((short *)from)++;
 237:     }
 238: }

Defined functions

bmap defined in line 26; used 5 times
cpass defined in line 194; used 4 times
nodev defined in line 217; used 310 times

Defined macros

qalloc defined in line 15; used 3 times
Last modified: 1983-09-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 852
Valid CSS Valid XHTML 1.0 Strict