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