|
|
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: *
1.1.1.2 ! root 33: * from: @(#)ufs_bmap.c 7.13 (Berkeley) 5/8/91
! 34: * ufs_bmap.c,v 1.2 1993/05/20 03:53:34 cgd Exp
1.1 root 35: */
36:
37: #include "param.h"
38: #include "systm.h"
39: #include "buf.h"
40: #include "proc.h"
41: #include "file.h"
42: #include "vnode.h"
43:
44: #include "quota.h"
45: #include "inode.h"
46: #include "fs.h"
47:
48: /*
49: * Bmap converts a the logical block number of a file
50: * to its physical block number on the disk. The conversion
51: * is done by using the logical block number to index into
52: * the array of block pointers described by the dinode.
53: */
54: bmap(ip, bn, bnp)
55: register struct inode *ip;
56: register daddr_t bn;
57: daddr_t *bnp;
58: {
59: register struct fs *fs;
60: register daddr_t nb;
61: struct buf *bp;
62: daddr_t *bap;
63: int i, j, sh;
64: int error;
65:
66: if (bn < 0)
67: return (EFBIG);
68: fs = ip->i_fs;
69:
70: /*
71: * The first NDADDR blocks are direct blocks
72: */
73: if (bn < NDADDR) {
74: nb = ip->i_db[bn];
75: if (nb == 0) {
76: *bnp = (daddr_t)-1;
77: return (0);
78: }
79: *bnp = fsbtodb(fs, nb);
80: return (0);
81: }
82: /*
83: * Determine the number of levels of indirection.
84: */
85: sh = 1;
86: bn -= NDADDR;
87: for (j = NIADDR; j > 0; j--) {
88: sh *= NINDIR(fs);
89: if (bn < sh)
90: break;
91: bn -= sh;
92: }
93: if (j == 0)
94: return (EFBIG);
95: /*
96: * Fetch through the indirect blocks.
97: */
98: nb = ip->i_ib[NIADDR - j];
99: if (nb == 0) {
100: *bnp = (daddr_t)-1;
101: return (0);
102: }
103: for (; j <= NIADDR; j++) {
104: if (error = bread(ip->i_devvp, fsbtodb(fs, nb),
105: (int)fs->fs_bsize, NOCRED, &bp)) {
106: brelse(bp);
107: return (error);
108: }
109: bap = bp->b_un.b_daddr;
110: sh /= NINDIR(fs);
111: i = (bn / sh) % NINDIR(fs);
112: nb = bap[i];
113: if (nb == 0) {
114: *bnp = (daddr_t)-1;
115: brelse(bp);
116: return (0);
117: }
118: brelse(bp);
119: }
120: *bnp = fsbtodb(fs, nb);
121: return (0);
122: }
123:
124: /*
125: * Balloc defines the structure of file system storage
126: * by allocating the physical blocks on a device given
127: * the inode and the logical block number in a file.
128: */
129: balloc(ip, bn, size, bpp, flags)
130: register struct inode *ip;
131: register daddr_t bn;
132: int size;
133: struct buf **bpp;
134: int flags;
135: {
136: register struct fs *fs;
137: register daddr_t nb;
138: struct buf *bp, *nbp;
139: struct vnode *vp = ITOV(ip);
140: int osize, nsize, i, j, sh, error;
141: daddr_t newb, lbn, *bap, pref, blkpref();
142:
143: *bpp = (struct buf *)0;
144: if (bn < 0)
145: return (EFBIG);
146: fs = ip->i_fs;
147:
148: /*
149: * If the next write will extend the file into a new block,
150: * and the file is currently composed of a fragment
151: * this fragment has to be extended to be a full block.
152: */
153: nb = lblkno(fs, ip->i_size);
154: if (nb < NDADDR && nb < bn) {
155: osize = blksize(fs, ip, nb);
156: if (osize < fs->fs_bsize && osize > 0) {
157: error = realloccg(ip, nb,
158: blkpref(ip, nb, (int)nb, &ip->i_db[0]),
159: osize, (int)fs->fs_bsize, &bp);
160: if (error)
161: return (error);
162: ip->i_size = (nb + 1) * fs->fs_bsize;
163: vnode_pager_setsize(ITOV(ip), (u_long)ip->i_size);
164: ip->i_db[nb] = dbtofsb(fs, bp->b_blkno);
165: ip->i_flag |= IUPD|ICHG;
166: if (flags & B_SYNC)
167: bwrite(bp);
168: else
169: bawrite(bp);
170: }
171: }
172: /*
173: * The first NDADDR blocks are direct blocks
174: */
175: if (bn < NDADDR) {
176: nb = ip->i_db[bn];
177: if (nb != 0 && ip->i_size >= (bn + 1) * fs->fs_bsize) {
178: error = bread(vp, bn, fs->fs_bsize, NOCRED, &bp);
179: if (error) {
180: brelse(bp);
181: return (error);
182: }
183: *bpp = bp;
184: return (0);
185: }
186: if (nb != 0) {
187: /*
188: * Consider need to reallocate a fragment.
189: */
190: osize = fragroundup(fs, blkoff(fs, ip->i_size));
191: nsize = fragroundup(fs, size);
192: if (nsize <= osize) {
193: error = bread(vp, bn, osize, NOCRED, &bp);
194: if (error) {
195: brelse(bp);
196: return (error);
197: }
198: } else {
199: error = realloccg(ip, bn,
200: blkpref(ip, bn, (int)bn, &ip->i_db[0]),
201: osize, nsize, &bp);
202: if (error)
203: return (error);
204: }
205: } else {
206: if (ip->i_size < (bn + 1) * fs->fs_bsize)
207: nsize = fragroundup(fs, size);
208: else
209: nsize = fs->fs_bsize;
210: error = alloc(ip, bn,
211: blkpref(ip, bn, (int)bn, &ip->i_db[0]),
212: nsize, &newb);
213: if (error)
214: return (error);
215: bp = getblk(vp, bn, nsize);
216: bp->b_blkno = fsbtodb(fs, newb);
217: if (flags & B_CLRBUF)
218: clrbuf(bp);
219: }
220: ip->i_db[bn] = dbtofsb(fs, bp->b_blkno);
221: ip->i_flag |= IUPD|ICHG;
222: *bpp = bp;
223: return (0);
224: }
225: /*
226: * Determine the number of levels of indirection.
227: */
228: pref = 0;
229: sh = 1;
230: lbn = bn;
231: bn -= NDADDR;
232: for (j = NIADDR; j > 0; j--) {
233: sh *= NINDIR(fs);
234: if (bn < sh)
235: break;
236: bn -= sh;
237: }
238: if (j == 0)
239: return (EFBIG);
240: /*
241: * Fetch the first indirect block allocating if necessary.
242: */
243: nb = ip->i_ib[NIADDR - j];
244: if (nb == 0) {
245: pref = blkpref(ip, lbn, 0, (daddr_t *)0);
246: if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb))
247: return (error);
248: nb = newb;
249: bp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize);
250: clrbuf(bp);
251: /*
252: * Write synchronously so that indirect blocks
253: * never point at garbage.
254: */
255: if (error = bwrite(bp)) {
256: blkfree(ip, nb, fs->fs_bsize);
257: return (error);
258: }
259: ip->i_ib[NIADDR - j] = nb;
260: ip->i_flag |= IUPD|ICHG;
261: }
262: /*
263: * Fetch through the indirect blocks, allocating as necessary.
264: */
265: for (; ; j++) {
266: error = bread(ip->i_devvp, fsbtodb(fs, nb),
267: (int)fs->fs_bsize, NOCRED, &bp);
268: if (error) {
269: brelse(bp);
270: return (error);
271: }
272: bap = bp->b_un.b_daddr;
273: sh /= NINDIR(fs);
274: i = (bn / sh) % NINDIR(fs);
275: nb = bap[i];
276: if (j == NIADDR)
277: break;
278: if (nb != 0) {
279: brelse(bp);
280: continue;
281: }
282: if (pref == 0)
283: pref = blkpref(ip, lbn, 0, (daddr_t *)0);
284: if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) {
285: brelse(bp);
286: return (error);
287: }
288: nb = newb;
289: nbp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize);
290: clrbuf(nbp);
291: /*
292: * Write synchronously so that indirect blocks
293: * never point at garbage.
294: */
295: if (error = bwrite(nbp)) {
296: blkfree(ip, nb, fs->fs_bsize);
297: brelse(bp);
298: return (error);
299: }
300: bap[i] = nb;
301: /*
302: * If required, write synchronously, otherwise use
303: * delayed write. If this is the first instance of
304: * the delayed write, reassociate the buffer with the
305: * file so it will be written if the file is sync'ed.
306: */
307: if (flags & B_SYNC) {
308: bwrite(bp);
309: } else if (bp->b_flags & B_DELWRI) {
310: bdwrite(bp);
311: } else {
312: bdwrite(bp);
313: reassignbuf(bp, vp);
314: }
315: }
316: /*
317: * Get the data block, allocating if necessary.
318: */
319: if (nb == 0) {
320: pref = blkpref(ip, lbn, i, &bap[0]);
321: if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) {
322: brelse(bp);
323: return (error);
324: }
325: nb = newb;
326: nbp = getblk(vp, lbn, fs->fs_bsize);
327: nbp->b_blkno = fsbtodb(fs, nb);
328: if (flags & B_CLRBUF)
329: clrbuf(nbp);
330: bap[i] = nb;
331: /*
332: * If required, write synchronously, otherwise use
333: * delayed write. If this is the first instance of
334: * the delayed write, reassociate the buffer with the
335: * file so it will be written if the file is sync'ed.
336: */
337: if (flags & B_SYNC) {
338: bwrite(bp);
339: } else if (bp->b_flags & B_DELWRI) {
340: bdwrite(bp);
341: } else {
342: bdwrite(bp);
343: reassignbuf(bp, vp);
344: }
345: *bpp = nbp;
346: return (0);
347: }
348: brelse(bp);
349: if (flags & B_CLRBUF) {
350: error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp);
351: if (error) {
352: brelse(nbp);
353: return (error);
354: }
355: } else {
356: nbp = getblk(vp, lbn, fs->fs_bsize);
357: nbp->b_blkno = fsbtodb(fs, nb);
358: }
359: *bpp = nbp;
360: return (0);
361: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.