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