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