hang_addrlist and free_addrlist move in from nfs/nfs_socket.c
[unix-history] / usr / src / sys / ufs / ffs / ffs_balloc.c
CommitLineData
da7c5cc6 1/*
7188ac27
KM
2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3 * All rights reserved.
da7c5cc6 4 *
b702c21d 5 * %sccs.include.redist.c%
7188ac27 6 *
406c9a0d 7 * @(#)ffs_balloc.c 7.21 (Berkeley) %G%
da7c5cc6 8 */
52212483 9
0cb5c176
KB
10#include <sys/param.h>
11#include <sys/systm.h>
12#include <sys/buf.h>
13#include <sys/proc.h>
14#include <sys/file.h>
15#include <sys/vnode.h>
c6f5111d 16
80e9de4e
KM
17#include <vm/vm.h>
18
0cb5c176
KB
19#include <ufs/ufs/quota.h>
20#include <ufs/ufs/inode.h>
21
22#include <ufs/ffs/fs.h>
23#include <ufs/ffs/ffs_extern.h>
52212483
BJ
24
25/*
a3257f3c
KM
26 * Bmap converts a the logical block number of a file
27 * to its physical block number on the disk. The conversion
28 * is done by using the logical block number to index into
29 * the array of block pointers described by the dinode.
52212483 30 */
a9013e03 31int
9342689a
JH
32ffs_bmap (ap)
33 struct vop_bmap_args *ap;
52212483 34{
406c9a0d 35 register daddr_t bn = ap->a_bn;
a9013e03 36 register struct inode *ip;
7188ac27
KM
37 register struct fs *fs;
38 register daddr_t nb;
39 struct buf *bp;
40 daddr_t *bap;
41 int i, j, sh;
42 int error;
43
a9013e03
KM
44 /*
45 * Check for underlying vnode requests and ensure that logical
46 * to physical mapping is requested.
47 */
e1b76915
JH
48 ip = VTOI(ap->a_vp);
49 if (ap->a_vpp != NULL)
50 *ap->a_vpp = ip->i_devvp;
51 if (ap->a_bnp == NULL)
a9013e03 52 return (0);
406c9a0d 53 if (bn < 0)
7188ac27
KM
54 return (EFBIG);
55 fs = ip->i_fs;
56
57 /*
58 * The first NDADDR blocks are direct blocks
59 */
406c9a0d
JH
60 if (bn < NDADDR) {
61 nb = ip->i_db[bn];
7188ac27 62 if (nb == 0) {
e1b76915 63 *ap->a_bnp = (daddr_t)-1;
7188ac27
KM
64 return (0);
65 }
e1b76915 66 *ap->a_bnp = fsbtodb(fs, nb);
7188ac27
KM
67 return (0);
68 }
7188ac27 69 /*
9b392e39 70 * Determine the number of levels of indirection.
7188ac27
KM
71 */
72 sh = 1;
406c9a0d 73 bn -= NDADDR;
7188ac27
KM
74 for (j = NIADDR; j > 0; j--) {
75 sh *= NINDIR(fs);
406c9a0d 76 if (bn < sh)
7188ac27 77 break;
406c9a0d 78 bn -= sh;
7188ac27
KM
79 }
80 if (j == 0)
81 return (EFBIG);
7188ac27 82 /*
9b392e39 83 * Fetch through the indirect blocks.
7188ac27
KM
84 */
85 nb = ip->i_ib[NIADDR - j];
86 if (nb == 0) {
e1b76915 87 *ap->a_bnp = (daddr_t)-1;
7188ac27 88 return (0);
52212483 89 }
7188ac27
KM
90 for (; j <= NIADDR; j++) {
91 if (error = bread(ip->i_devvp, fsbtodb(fs, nb),
a937f856 92 (int)fs->fs_bsize, NOCRED, &bp)) {
7188ac27
KM
93 brelse(bp);
94 return (error);
95 }
96 bap = bp->b_un.b_daddr;
97 sh /= NINDIR(fs);
406c9a0d 98 i = (bn / sh) % NINDIR(fs);
7188ac27
KM
99 nb = bap[i];
100 if (nb == 0) {
e1b76915 101 *ap->a_bnp = (daddr_t)-1;
7188ac27
KM
102 brelse(bp);
103 return (0);
104 }
9b392e39 105 brelse(bp);
7188ac27 106 }
e1b76915 107 *ap->a_bnp = fsbtodb(fs, nb);
7188ac27
KM
108 return (0);
109}
110
111/*
112 * Balloc defines the structure of file system storage
9b392e39
KM
113 * by allocating the physical blocks on a device given
114 * the inode and the logical block number in a file.
7188ac27 115 */
9438887a 116ffs_balloc(ip, bn, size, cred, bpp, flags)
7188ac27
KM
117 register struct inode *ip;
118 register daddr_t bn;
119 int size;
9438887a 120 struct ucred *cred;
9b392e39 121 struct buf **bpp;
7188ac27
KM
122 int flags;
123{
124 register struct fs *fs;
125 register daddr_t nb;
126 struct buf *bp, *nbp;
9b392e39 127 struct vnode *vp = ITOV(ip);
7188ac27 128 int osize, nsize, i, j, sh, error;
0cb5c176 129 daddr_t newb, lbn, *bap, pref;
7188ac27 130
9b392e39 131 *bpp = (struct buf *)0;
7188ac27
KM
132 if (bn < 0)
133 return (EFBIG);
52212483 134 fs = ip->i_fs;
52212483
BJ
135
136 /*
137 * If the next write will extend the file into a new block,
138 * and the file is currently composed of a fragment
139 * this fragment has to be extended to be a full block.
140 */
141 nb = lblkno(fs, ip->i_size);
7188ac27 142 if (nb < NDADDR && nb < bn) {
52212483
BJ
143 osize = blksize(fs, ip, nb);
144 if (osize < fs->fs_bsize && osize > 0) {
0cb5c176
KB
145 error = ffs_realloccg(ip, nb,
146 ffs_blkpref(ip, nb, (int)nb, &ip->i_db[0]),
9438887a 147 osize, (int)fs->fs_bsize, cred, &bp);
9b392e39 148 if (error)
7188ac27 149 return (error);
52212483 150 ip->i_size = (nb + 1) * fs->fs_bsize;
995d2177 151 vnode_pager_setsize(vp, (u_long)ip->i_size);
52212483
BJ
152 ip->i_db[nb] = dbtofsb(fs, bp->b_blkno);
153 ip->i_flag |= IUPD|ICHG;
9b392e39
KM
154 if (flags & B_SYNC)
155 bwrite(bp);
156 else
157 bawrite(bp);
52212483
BJ
158 }
159 }
160 /*
161 * The first NDADDR blocks are direct blocks
162 */
163 if (bn < NDADDR) {
a6e7e3c6 164 nb = ip->i_db[bn];
9b392e39
KM
165 if (nb != 0 && ip->i_size >= (bn + 1) * fs->fs_bsize) {
166 error = bread(vp, bn, fs->fs_bsize, NOCRED, &bp);
7188ac27 167 if (error) {
9b392e39 168 brelse(bp);
7188ac27 169 return (error);
52212483 170 }
9b392e39
KM
171 *bpp = bp;
172 return (0);
173 }
174 if (nb != 0) {
175 /*
176 * Consider need to reallocate a fragment.
177 */
178 osize = fragroundup(fs, blkoff(fs, ip->i_size));
179 nsize = fragroundup(fs, size);
180 if (nsize <= osize) {
181 error = bread(vp, bn, osize, NOCRED, &bp);
182 if (error) {
183 brelse(bp);
184 return (error);
185 }
186 } else {
0cb5c176
KB
187 error = ffs_realloccg(ip, bn,
188 ffs_blkpref(ip, bn, (int)bn, &ip->i_db[0]),
9438887a 189 osize, nsize, cred, &bp);
9b392e39
KM
190 if (error)
191 return (error);
192 }
193 } else {
194 if (ip->i_size < (bn + 1) * fs->fs_bsize)
195 nsize = fragroundup(fs, size);
52212483 196 else
9b392e39 197 nsize = fs->fs_bsize;
0cb5c176
KB
198 error = ffs_alloc(ip, bn,
199 ffs_blkpref(ip, bn, (int)bn, &ip->i_db[0]),
9438887a 200 nsize, cred, &newb);
9b392e39
KM
201 if (error)
202 return (error);
203 bp = getblk(vp, bn, nsize);
204 bp->b_blkno = fsbtodb(fs, newb);
205 if (flags & B_CLRBUF)
206 clrbuf(bp);
52212483 207 }
9b392e39
KM
208 ip->i_db[bn] = dbtofsb(fs, bp->b_blkno);
209 ip->i_flag |= IUPD|ICHG;
210 *bpp = bp;
7188ac27 211 return (0);
52212483 212 }
52212483 213 /*
9b392e39 214 * Determine the number of levels of indirection.
52212483 215 */
a6e7e3c6 216 pref = 0;
52212483 217 sh = 1;
a6e7e3c6 218 lbn = bn;
52212483 219 bn -= NDADDR;
7188ac27 220 for (j = NIADDR; j > 0; j--) {
52212483
BJ
221 sh *= NINDIR(fs);
222 if (bn < sh)
223 break;
224 bn -= sh;
225 }
7188ac27
KM
226 if (j == 0)
227 return (EFBIG);
52212483 228 /*
9b392e39 229 * Fetch the first indirect block allocating if necessary.
52212483
BJ
230 */
231 nb = ip->i_ib[NIADDR - j];
232 if (nb == 0) {
0cb5c176 233 pref = ffs_blkpref(ip, lbn, 0, (daddr_t *)0);
9438887a
KM
234 if (error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize,
235 cred, &newb))
7188ac27 236 return (error);
9b392e39
KM
237 nb = newb;
238 bp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize);
239 clrbuf(bp);
52212483
BJ
240 /*
241 * Write synchronously so that indirect blocks
242 * never point at garbage.
243 */
9b392e39 244 if (error = bwrite(bp)) {
0cb5c176 245 ffs_blkfree(ip, nb, fs->fs_bsize);
9b392e39
KM
246 return (error);
247 }
52212483
BJ
248 ip->i_ib[NIADDR - j] = nb;
249 ip->i_flag |= IUPD|ICHG;
250 }
52212483 251 /*
9b392e39 252 * Fetch through the indirect blocks, allocating as necessary.
52212483 253 */
9b392e39
KM
254 for (; ; j++) {
255 error = bread(ip->i_devvp, fsbtodb(fs, nb),
256 (int)fs->fs_bsize, NOCRED, &bp);
257 if (error) {
52212483 258 brelse(bp);
7188ac27 259 return (error);
52212483
BJ
260 }
261 bap = bp->b_un.b_daddr;
262 sh /= NINDIR(fs);
263 i = (bn / sh) % NINDIR(fs);
264 nb = bap[i];
9b392e39
KM
265 if (j == NIADDR)
266 break;
267 if (nb != 0) {
268 brelse(bp);
269 continue;
270 }
271 if (pref == 0)
0cb5c176
KB
272 pref = ffs_blkpref(ip, lbn, 0, (daddr_t *)0);
273 if (error =
9438887a 274 ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, &newb)) {
9b392e39
KM
275 brelse(bp);
276 return (error);
277 }
278 nb = newb;
279 nbp = getblk(ip->i_devvp, fsbtodb(fs, nb), fs->fs_bsize);
280 clrbuf(nbp);
9b392e39
KM
281 /*
282 * Write synchronously so that indirect blocks
283 * never point at garbage.
284 */
285 if (error = bwrite(nbp)) {
0cb5c176 286 ffs_blkfree(ip, nb, fs->fs_bsize);
9b392e39
KM
287 brelse(bp);
288 return (error);
289 }
290 bap[i] = nb;
3cf3d516
KM
291 /*
292 * If required, write synchronously, otherwise use
293 * delayed write. If this is the first instance of
294 * the delayed write, reassociate the buffer with the
295 * file so it will be written if the file is sync'ed.
296 */
297 if (flags & B_SYNC) {
9b392e39 298 bwrite(bp);
3cf3d516 299 } else if (bp->b_flags & B_DELWRI) {
52212483 300 bdwrite(bp);
3cf3d516
KM
301 } else {
302 bdwrite(bp);
303 reassignbuf(bp, vp);
304 }
9b392e39
KM
305 }
306 /*
307 * Get the data block, allocating if necessary.
308 */
309 if (nb == 0) {
0cb5c176
KB
310 pref = ffs_blkpref(ip, lbn, i, &bap[0]);
311 if (error =
9438887a 312 ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, &newb)) {
52212483 313 brelse(bp);
9b392e39
KM
314 return (error);
315 }
316 nb = newb;
317 nbp = getblk(vp, lbn, fs->fs_bsize);
318 nbp->b_blkno = fsbtodb(fs, nb);
319 if (flags & B_CLRBUF)
320 clrbuf(nbp);
321 bap[i] = nb;
3cf3d516
KM
322 /*
323 * If required, write synchronously, otherwise use
324 * delayed write. If this is the first instance of
325 * the delayed write, reassociate the buffer with the
326 * file so it will be written if the file is sync'ed.
327 */
328 if (flags & B_SYNC) {
9b392e39 329 bwrite(bp);
3cf3d516 330 } else if (bp->b_flags & B_DELWRI) {
9b392e39 331 bdwrite(bp);
3cf3d516
KM
332 } else {
333 bdwrite(bp);
334 reassignbuf(bp, vp);
335 }
9b392e39
KM
336 *bpp = nbp;
337 return (0);
52212483 338 }
9b392e39 339 brelse(bp);
0b4c7ad8 340 if (flags & B_CLRBUF) {
9b392e39
KM
341 error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp);
342 if (error) {
343 brelse(nbp);
344 return (error);
345 }
0b4c7ad8
KM
346 } else {
347 nbp = getblk(vp, lbn, fs->fs_bsize);
348 nbp->b_blkno = fsbtodb(fs, nb);
9b392e39
KM
349 }
350 *bpp = nbp;
7188ac27 351 return (0);
52212483 352}