|
|
1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.