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