Removed all patch kit headers, sccsid and rcsid strings, put $Id$ in, some
[unix-history] / sys / ufs / ufs_bmap.c
CommitLineData
15637ed4
RG
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 *
1eb58e01
RG
33 * from: @(#)ufs_bmap.c 7.13 (Berkeley) 5/8/91
34 * $Id$
15637ed4
RG
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 */
54bmap(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 */
129balloc(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}