1 /*- 2 * modified for Lites 1.1 3 * 4 * Aug 1995, Godmar Back (gback@cs.utah.edu) 5 * University of Utah, Department of Computer Science 6 */ 7 /*- 8 * SPDX-License-Identifier: BSD-3-Clause 9 * 10 * Copyright (c) 1982, 1986, 1989, 1993 11 * The Regents of the University of California. All rights reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 */ 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/endian.h> 41 #include <sys/bio.h> 42 #include <sys/buf.h> 43 #include <sys/limits.h> 44 #include <sys/lock.h> 45 #include <sys/mount.h> 46 #include <sys/vnode.h> 47 48 #include <fs/ext2fs/fs.h> 49 #include <fs/ext2fs/inode.h> 50 #include <fs/ext2fs/ext2fs.h> 51 #include <fs/ext2fs/ext2_dinode.h> 52 #include <fs/ext2fs/ext2_extern.h> 53 #include <fs/ext2fs/ext2_mount.h> 54 55 static int 56 ext2_ext_balloc(struct inode *ip, uint32_t lbn, int size, 57 struct ucred *cred, struct buf **bpp, int flags) 58 { 59 struct m_ext2fs *fs; 60 struct buf *bp = NULL; 61 struct vnode *vp = ITOV(ip); 62 daddr_t newblk; 63 int blks, error, allocated; 64 65 fs = ip->i_e2fs; 66 blks = howmany(size, fs->e2fs_bsize); 67 68 error = ext4_ext_get_blocks(ip, lbn, blks, cred, NULL, &allocated, &newblk); 69 if (error) 70 return (error); 71 72 if (allocated) { 73 bp = getblk(vp, lbn, fs->e2fs_bsize, 0, 0, 0); 74 if(!bp) 75 return (EIO); 76 } else { 77 error = bread(vp, lbn, fs->e2fs_bsize, NOCRED, &bp); 78 if (error) { 79 return (error); 80 } 81 } 82 83 bp->b_blkno = fsbtodb(fs, newblk); 84 if (flags & BA_CLRBUF) 85 vfs_bio_clrbuf(bp); 86 87 *bpp = bp; 88 89 return (error); 90 } 91 92 /* 93 * Balloc defines the structure of filesystem storage 94 * by allocating the physical blocks on a device given 95 * the inode and the logical block number in a file. 96 */ 97 int 98 ext2_balloc(struct inode *ip, e2fs_lbn_t lbn, int size, struct ucred *cred, 99 struct buf **bpp, int flags) 100 { 101 struct m_ext2fs *fs; 102 struct ext2mount *ump; 103 struct buf *bp, *nbp; 104 struct vnode *vp = ITOV(ip); 105 struct indir indirs[EXT2_NIADDR + 2]; 106 e4fs_daddr_t nb, newb; 107 e2fs_daddr_t *bap, pref; 108 int num, i, error; 109 110 *bpp = NULL; 111 if (lbn < 0) 112 return (EFBIG); 113 fs = ip->i_e2fs; 114 ump = ip->i_ump; 115 116 /* 117 * check if this is a sequential block allocation. 118 * If so, increment next_alloc fields to allow ext2_blkpref 119 * to make a good guess 120 */ 121 if (lbn == ip->i_next_alloc_block + 1) { 122 ip->i_next_alloc_block++; 123 ip->i_next_alloc_goal++; 124 } 125 126 if (ip->i_flag & IN_E4EXTENTS) 127 return (ext2_ext_balloc(ip, lbn, size, cred, bpp, flags)); 128 129 /* 130 * The first EXT2_NDADDR blocks are direct blocks 131 */ 132 if (lbn < EXT2_NDADDR) { 133 nb = ip->i_db[lbn]; 134 /* 135 * no new block is to be allocated, and no need to expand 136 * the file 137 */ 138 if (nb != 0) { 139 error = bread(vp, lbn, fs->e2fs_bsize, NOCRED, &bp); 140 if (error) { 141 return (error); 142 } 143 bp->b_blkno = fsbtodb(fs, nb); 144 if (ip->i_size >= (lbn + 1) * fs->e2fs_bsize) { 145 *bpp = bp; 146 return (0); 147 } 148 } else { 149 EXT2_LOCK(ump); 150 error = ext2_alloc(ip, lbn, 151 ext2_blkpref(ip, lbn, (int)lbn, &ip->i_db[0], 0), 152 fs->e2fs_bsize, cred, &newb); 153 if (error) 154 return (error); 155 /* 156 * If the newly allocated block exceeds 32-bit limit, 157 * we can not use it in file block maps. 158 */ 159 if (newb > UINT_MAX) 160 return (EFBIG); 161 bp = getblk(vp, lbn, fs->e2fs_bsize, 0, 0, 0); 162 bp->b_blkno = fsbtodb(fs, newb); 163 if (flags & BA_CLRBUF) 164 vfs_bio_clrbuf(bp); 165 } 166 ip->i_db[lbn] = dbtofsb(fs, bp->b_blkno); 167 ip->i_flag |= IN_CHANGE | IN_UPDATE; 168 *bpp = bp; 169 return (0); 170 } 171 /* 172 * Determine the number of levels of indirection. 173 */ 174 pref = 0; 175 if ((error = ext2_getlbns(vp, lbn, indirs, &num)) != 0) 176 return (error); 177 #ifdef INVARIANTS 178 if (num < 1) 179 panic("ext2_balloc: ext2_getlbns returned indirect block"); 180 #endif 181 /* 182 * Fetch the first indirect block allocating if necessary. 183 */ 184 --num; 185 nb = ip->i_ib[indirs[0].in_off]; 186 if (nb == 0) { 187 EXT2_LOCK(ump); 188 pref = ext2_blkpref(ip, lbn, indirs[0].in_off + 189 EXT2_NDIR_BLOCKS, &ip->i_db[0], 0); 190 if ((error = ext2_alloc(ip, lbn, pref, fs->e2fs_bsize, cred, 191 &newb))) 192 return (error); 193 if (newb > UINT_MAX) 194 return (EFBIG); 195 nb = newb; 196 bp = getblk(vp, indirs[1].in_lbn, fs->e2fs_bsize, 0, 0, 0); 197 bp->b_blkno = fsbtodb(fs, newb); 198 vfs_bio_clrbuf(bp); 199 /* 200 * Write synchronously so that indirect blocks 201 * never point at garbage. 202 */ 203 if ((error = bwrite(bp)) != 0) { 204 ext2_blkfree(ip, nb, fs->e2fs_bsize); 205 return (error); 206 } 207 ip->i_ib[indirs[0].in_off] = newb; 208 ip->i_flag |= IN_CHANGE | IN_UPDATE; 209 } 210 /* 211 * Fetch through the indirect blocks, allocating as necessary. 212 */ 213 for (i = 1;;) { 214 error = bread(vp, 215 indirs[i].in_lbn, (int)fs->e2fs_bsize, NOCRED, &bp); 216 if (error) { 217 return (error); 218 } 219 bap = (e2fs_daddr_t *)bp->b_data; 220 nb = le32toh(bap[indirs[i].in_off]); 221 if (i == num) 222 break; 223 i += 1; 224 if (nb != 0) { 225 bqrelse(bp); 226 continue; 227 } 228 EXT2_LOCK(ump); 229 if (pref == 0) 230 pref = ext2_blkpref(ip, lbn, indirs[i].in_off, bap, 231 bp->b_lblkno); 232 error = ext2_alloc(ip, lbn, pref, (int)fs->e2fs_bsize, cred, &newb); 233 if (error) { 234 brelse(bp); 235 return (error); 236 } 237 if (newb > UINT_MAX) 238 return (EFBIG); 239 nb = newb; 240 nbp = getblk(vp, indirs[i].in_lbn, fs->e2fs_bsize, 0, 0, 0); 241 nbp->b_blkno = fsbtodb(fs, nb); 242 vfs_bio_clrbuf(nbp); 243 /* 244 * Write synchronously so that indirect blocks 245 * never point at garbage. 246 */ 247 if ((error = bwrite(nbp)) != 0) { 248 ext2_blkfree(ip, nb, fs->e2fs_bsize); 249 brelse(bp); 250 return (error); 251 } 252 bap[indirs[i - 1].in_off] = htole32(nb); 253 /* 254 * If required, write synchronously, otherwise use 255 * delayed write. 256 */ 257 if (flags & IO_SYNC) { 258 bwrite(bp); 259 } else { 260 if (bp->b_bufsize == fs->e2fs_bsize) 261 bp->b_flags |= B_CLUSTEROK; 262 bdwrite(bp); 263 } 264 } 265 /* 266 * Get the data block, allocating if necessary. 267 */ 268 if (nb == 0) { 269 EXT2_LOCK(ump); 270 pref = ext2_blkpref(ip, lbn, indirs[i].in_off, &bap[0], 271 bp->b_lblkno); 272 if ((error = ext2_alloc(ip, 273 lbn, pref, (int)fs->e2fs_bsize, cred, &newb)) != 0) { 274 brelse(bp); 275 return (error); 276 } 277 if (newb > UINT_MAX) 278 return (EFBIG); 279 nb = newb; 280 nbp = getblk(vp, lbn, fs->e2fs_bsize, 0, 0, 0); 281 nbp->b_blkno = fsbtodb(fs, nb); 282 if (flags & BA_CLRBUF) 283 vfs_bio_clrbuf(nbp); 284 bap[indirs[i].in_off] = htole32(nb); 285 /* 286 * If required, write synchronously, otherwise use 287 * delayed write. 288 */ 289 if (flags & IO_SYNC) { 290 bwrite(bp); 291 } else { 292 if (bp->b_bufsize == fs->e2fs_bsize) 293 bp->b_flags |= B_CLUSTEROK; 294 bdwrite(bp); 295 } 296 *bpp = nbp; 297 return (0); 298 } 299 brelse(bp); 300 if (flags & BA_CLRBUF) { 301 int seqcount = (flags & BA_SEQMASK) >> BA_SEQSHIFT; 302 303 if (seqcount && (vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) { 304 error = cluster_read(vp, ip->i_size, lbn, 305 (int)fs->e2fs_bsize, NOCRED, 306 MAXBSIZE, seqcount, 0, &nbp); 307 } else { 308 error = bread(vp, lbn, (int)fs->e2fs_bsize, NOCRED, &nbp); 309 } 310 if (error) { 311 brelse(nbp); 312 return (error); 313 } 314 } else { 315 nbp = getblk(vp, lbn, fs->e2fs_bsize, 0, 0, 0); 316 nbp->b_blkno = fsbtodb(fs, nb); 317 } 318 *bpp = nbp; 319 return (0); 320 } 321