|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution is only permitted until one year after the first shipment
6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
7: * binary forms are permitted provided that: (1) source distributions retain
8: * this entire copyright notice and comment, and (2) distributions including
9: * binaries display the following acknowledgement: This product includes
10: * software developed by the University of California, Berkeley and its
11: * contributors'' in the documentation or other materials provided with the
12: * distribution and in all advertising materials mentioning features or use
13: * of this software. Neither the name of the University nor the names of
14: * its contributors may be used to endorse or promote products derived from
15: * this software without specific prior written permission.
16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19: *
20: * @(#)ufs_bmap.c 7.10 (Berkeley) 6/28/90
21: */
22:
23: #include "param.h"
24: #include "systm.h"
25: #include "user.h"
26: #include "buf.h"
27: #include "proc.h"
28: #include "file.h"
29: #include "vnode.h"
30: #include "../ufs/quota.h"
31: #include "../ufs/inode.h"
32: #include "../ufs/fs.h"
33:
34: /*
35: * Bmap defines the structure of file system storage
36: * by returning the physical block number on a device
37: * given the inode and the logical block number in a file.
38: */
39: bmap(ip, bn, bnp)
40: register struct inode *ip;
41: register daddr_t bn;
42: daddr_t *bnp;
43: {
44: register struct fs *fs;
45: register daddr_t nb;
46: struct buf *bp;
47: daddr_t *bap;
48: int i, j, sh;
49: int error;
50:
51: if (bn < 0)
52: return (EFBIG);
53: fs = ip->i_fs;
54:
55: /*
56: * The first NDADDR blocks are direct blocks
57: */
58: if (bn < NDADDR) {
59: nb = ip->i_db[bn];
60: if (nb == 0) {
61: *bnp = (daddr_t)-1;
62: return (0);
63: }
64: *bnp = fsbtodb(fs, nb);
65: return (0);
66: }
67: /*
68: * Determine the number of levels of indirection.
69: */
70: sh = 1;
71: bn -= NDADDR;
72: for (j = NIADDR; j > 0; j--) {
73: sh *= NINDIR(fs);
74: if (bn < sh)
75: break;
76: bn -= sh;
77: }
78: if (j == 0)
79: return (EFBIG);
80: /*
81: * Fetch through the indirect blocks.
82: */
83: nb = ip->i_ib[NIADDR - j];
84: if (nb == 0) {
85: *bnp = (daddr_t)-1;
86: return (0);
87: }
88: for (; j <= NIADDR; j++) {
89: if (error = bread(ip->i_devvp, fsbtodb(fs, nb),
90: (int)fs->fs_bsize, NOCRED, &bp)) {
91: brelse(bp);
92: return (error);
93: }
94: bap = bp->b_un.b_daddr;
95: sh /= NINDIR(fs);
96: i = (bn / sh) % NINDIR(fs);
97: nb = bap[i];
98: if (nb == 0) {
99: *bnp = (daddr_t)-1;
100: brelse(bp);
101: return (0);
102: }
103: brelse(bp);
104: }
105: *bnp = fsbtodb(fs, nb);
106: return (0);
107: }
108:
109: /*
110: * Balloc defines the structure of file system storage
111: * by allocating the physical blocks on a device given
112: * the inode and the logical block number in a file.
113: */
114: balloc(ip, bn, size, bpp, flags)
115: register struct inode *ip;
116: register daddr_t bn;
117: int size;
118: struct buf **bpp;
119: int flags;
120: {
121: register struct fs *fs;
122: register daddr_t nb;
123: struct buf *bp, *nbp;
124: struct vnode *vp = ITOV(ip);
125: int osize, nsize, i, j, sh, error;
126: daddr_t newb, lbn, *bap, pref, blkpref();
127:
128: *bpp = (struct buf *)0;
129: if (bn < 0)
130: return (EFBIG);
131: fs = ip->i_fs;
132:
133: /*
134: * If the next write will extend the file into a new block,
135: * and the file is currently composed of a fragment
136: * this fragment has to be extended to be a full block.
137: */
138: nb = lblkno(fs, ip->i_size);
139: if (nb < NDADDR && nb < bn) {
140: osize = blksize(fs, ip, nb);
141: if (osize < fs->fs_bsize && osize > 0) {
142: error = realloccg(ip, nb,
143: blkpref(ip, nb, (int)nb, &ip->i_db[0]),
144: osize, (int)fs->fs_bsize, &bp);
145: if (error)
146: return (error);
147: ip->i_size = (nb + 1) * fs->fs_bsize;
148: ip->i_db[nb] = dbtofsb(fs, bp->b_blkno);
149: ip->i_flag |= IUPD|ICHG;
150: if (flags & B_SYNC)
151: bwrite(bp);
152: else
153: bawrite(bp);
154: }
155: }
156: /*
157: * The first NDADDR blocks are direct blocks
158: */
159: if (bn < NDADDR) {
160: nb = ip->i_db[bn];
161: if (nb != 0 && ip->i_size >= (bn + 1) * fs->fs_bsize) {
162: error = bread(vp, bn, fs->fs_bsize, NOCRED, &bp);
163: if (error) {
164: brelse(bp);
165: return (error);
166: }
167: *bpp = bp;
168: return (0);
169: }
170: if (nb != 0) {
171: /*
172: * Consider need to reallocate a fragment.
173: */
174: osize = fragroundup(fs, blkoff(fs, ip->i_size));
175: nsize = fragroundup(fs, size);
176: if (nsize <= osize) {
177: error = bread(vp, bn, osize, NOCRED, &bp);
178: if (error) {
179: brelse(bp);
180: return (error);
181: }
182: } else {
183: error = realloccg(ip, bn,
184: blkpref(ip, bn, (int)bn, &ip->i_db[0]),
185: osize, nsize, &bp);
186: if (error)
187: return (error);
188: }
189: } else {
190: if (ip->i_size < (bn + 1) * fs->fs_bsize)
191: nsize = fragroundup(fs, size);
192: else
193: nsize = fs->fs_bsize;
194: error = alloc(ip, bn,
195: blkpref(ip, bn, (int)bn, &ip->i_db[0]),
196: nsize, &newb);
197: if (error)
198: return (error);
199: bp = getblk(vp, bn, nsize);
200: bp->b_blkno = fsbtodb(fs, newb);
201: if (flags & B_CLRBUF)
202: clrbuf(bp);
203: }
204: ip->i_db[bn] = dbtofsb(fs, bp->b_blkno);
205: ip->i_flag |= IUPD|ICHG;
206: *bpp = bp;
207: return (0);
208: }
209: /*
210: * Determine the number of levels of indirection.
211: */
212: pref = 0;
213: sh = 1;
214: lbn = bn;
215: bn -= NDADDR;
216: for (j = NIADDR; j > 0; j--) {
217: sh *= NINDIR(fs);
218: if (bn < sh)
219: break;
220: bn -= sh;
221: }
222: if (j == 0)
223: return (EFBIG);
224: /*
225: * Fetch the first indirect block allocating if necessary.
226: */
227: nb = ip->i_ib[NIADDR - j];
228: if (nb == 0) {
229: pref = blkpref(ip, lbn, 0, (daddr_t *)0);
230: if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb))
231: return (error);
232: nb = newb;
233: bp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize);
234: clrbuf(bp);
235: /*
236: * Write synchronously so that indirect blocks
237: * never point at garbage.
238: */
239: if (error = bwrite(bp)) {
240: blkfree(ip, nb, fs->fs_bsize);
241: return (error);
242: }
243: ip->i_ib[NIADDR - j] = nb;
244: ip->i_flag |= IUPD|ICHG;
245: }
246: /*
247: * Fetch through the indirect blocks, allocating as necessary.
248: */
249: for (; ; j++) {
250: error = bread(ip->i_devvp, fsbtodb(fs, nb),
251: (int)fs->fs_bsize, NOCRED, &bp);
252: if (error) {
253: brelse(bp);
254: return (error);
255: }
256: bap = bp->b_un.b_daddr;
257: sh /= NINDIR(fs);
258: i = (bn / sh) % NINDIR(fs);
259: nb = bap[i];
260: if (j == NIADDR)
261: break;
262: if (nb != 0) {
263: brelse(bp);
264: continue;
265: }
266: if (pref == 0)
267: pref = blkpref(ip, lbn, 0, (daddr_t *)0);
268: if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) {
269: brelse(bp);
270: return (error);
271: }
272: nb = newb;
273: nbp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize);
274: clrbuf(nbp);
275: /*
276: * Write synchronously so that indirect blocks
277: * never point at garbage.
278: */
279: if (error = bwrite(nbp)) {
280: blkfree(ip, nb, fs->fs_bsize);
281: brelse(bp);
282: return (error);
283: }
284: bap[i] = nb;
285: /*
286: * If required, write synchronously, otherwise use
287: * delayed write. If this is the first instance of
288: * the delayed write, reassociate the buffer with the
289: * file so it will be written if the file is sync'ed.
290: */
291: if (flags & B_SYNC) {
292: bwrite(bp);
293: } else if (bp->b_flags & B_DELWRI) {
294: bdwrite(bp);
295: } else {
296: bdwrite(bp);
297: reassignbuf(bp, vp);
298: }
299: }
300: /*
301: * Get the data block, allocating if necessary.
302: */
303: if (nb == 0) {
304: pref = blkpref(ip, lbn, i, &bap[0]);
305: if (error = alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb)) {
306: brelse(bp);
307: return (error);
308: }
309: nb = newb;
310: nbp = getblk(vp, lbn, fs->fs_bsize);
311: nbp->b_blkno = fsbtodb(fs, nb);
312: if (flags & B_CLRBUF)
313: clrbuf(nbp);
314: bap[i] = nb;
315: /*
316: * If required, write synchronously, otherwise use
317: * delayed write. If this is the first instance of
318: * the delayed write, reassociate the buffer with the
319: * file so it will be written if the file is sync'ed.
320: */
321: if (flags & B_SYNC) {
322: bwrite(bp);
323: } else if (bp->b_flags & B_DELWRI) {
324: bdwrite(bp);
325: } else {
326: bdwrite(bp);
327: reassignbuf(bp, vp);
328: }
329: *bpp = nbp;
330: return (0);
331: }
332: brelse(bp);
333: if (flags & B_CLRBUF) {
334: error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp);
335: if (error) {
336: brelse(nbp);
337: return (error);
338: }
339: } else {
340: nbp = getblk(vp, lbn, fs->fs_bsize);
341: nbp->b_blkno = fsbtodb(fs, nb);
342: }
343: *bpp = nbp;
344: return (0);
345: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.