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
bmap
defined in line
30; used 8 times