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 * @(#)ffs_subr.c 8.2 (Berkeley) 9/21/93 38 * $FreeBSD$ 39 */ 40 41 #include <sys/param.h> 42 43 #include <sys/proc.h> 44 #include <sys/systm.h> 45 #include <sys/bio.h> 46 #include <sys/buf2.h> 47 #include <sys/lock.h> 48 #include <sys/ucred.h> 49 #include <sys/vnode.h> 50 #include <sys/mount.h> 51 #include <sys/malloc.h> 52 53 #include <vfs/ext2fs/fs.h> 54 #include <vfs/ext2fs/inode.h> 55 #include <vfs/ext2fs/ext2fs.h> 56 #include <vfs/ext2fs/ext2_extern.h> 57 #include <vfs/ext2fs/fs.h> 58 #include <vfs/ext2fs/ext2_extents.h> 59 #include <vfs/ext2fs/ext2_mount.h> 60 #include <vfs/ext2fs/ext2_dinode.h> 61 62 void 63 ext2_free(void *addr, struct malloc_type *type, const char *func) 64 { 65 if (addr == NULL) { 66 printf("%s: trying to free NULL pointer\n", func); 67 return; 68 } 69 kfree(addr, type); 70 } 71 72 int 73 ext2_bread(struct vnode *vp, off_t loffset, int size, struct buf **bpp) 74 { 75 struct buf *bp; 76 int error; 77 78 *bpp = NULL; 79 error = bread(vp, loffset, size, &bp); 80 if (error) { 81 ext2_brelse(bp); 82 return (error); 83 } 84 85 *bpp = bp; 86 return (0); 87 } 88 89 int 90 ext2_breadn(struct vnode *vp, off_t loffset, int size, off_t *raoffset, 91 int *rabsize, int cnt, struct buf **bpp) 92 { 93 struct buf *bp; 94 int error; 95 96 *bpp = NULL; 97 error = breadn(vp, loffset, size, raoffset, rabsize, cnt, &bp); 98 if (error) { 99 ext2_brelse(bp); 100 return (error); 101 } 102 103 *bpp = bp; 104 return (0); 105 } 106 107 int 108 ext2_cluster_read(struct vnode *vp, off_t filesize, off_t loffset, int blksize, 109 size_t minreq, size_t maxreq, struct buf **bpp) 110 { 111 struct buf *bp; 112 int error; 113 114 *bpp = NULL; 115 error = cluster_read(vp, filesize, loffset, blksize, minreq, maxreq, 116 &bp); 117 if (error) { 118 ext2_brelse(bp); 119 return (error); 120 } 121 122 *bpp = bp; 123 return (0); 124 } 125 126 void 127 ext2_brelse(struct buf *bp) 128 { 129 if (bp == NULL) 130 return; 131 brelse(bp); 132 } 133 134 void 135 ext2_bqrelse(struct buf *bp) 136 { 137 if (bp == NULL) 138 return; 139 bqrelse(bp); 140 } 141 142 /* 143 * Return buffer with the contents of block "offset" from the beginning of 144 * directory "ip". If "res" is non-zero, fill it in with a pointer to the 145 * remaining space in the directory. 146 */ 147 int 148 ext2_blkatoff(struct vnode *vp, off_t offset, char **res, struct buf **bpp) 149 { 150 struct inode *ip; 151 struct m_ext2fs *fs; 152 struct buf *bp; 153 e2fs_lbn_t lbn; 154 int error, bsize; 155 156 ip = VTOI(vp); 157 fs = ip->i_e2fs; 158 lbn = lblkno(fs, offset); 159 bsize = blksize(fs, ip, lbn); 160 161 if ((error = ext2_bread(vp, lblktodoff(fs, lbn), bsize, &bp)) != 0) { 162 ext2_brelse(bp); 163 return (error); 164 } 165 error = ext2_dir_blk_csum_verify(ip, bp); 166 if (error != 0) { 167 ext2_brelse(bp); 168 return (error); 169 } 170 if (res) 171 *res = (char *)bp->b_data + blkoff(fs, offset); 172 173 *bpp = bp; 174 175 return (0); 176 } 177 178 /* 179 * Update the cluster map because of an allocation of free like ffs. 180 * 181 * Cnt == 1 means free; cnt == -1 means allocating. 182 */ 183 void 184 ext2_clusteracct(struct m_ext2fs *fs, char *bbp, int cg, e4fs_daddr_t bno, int cnt) 185 { 186 int32_t *sump = fs->e2fs_clustersum[cg].cs_sum; 187 int32_t *lp; 188 e4fs_daddr_t start, end, loc, forw, back; 189 int bit, i; 190 191 /* Initialize the cluster summary array. */ 192 if (fs->e2fs_clustersum[cg].cs_init == 0) { 193 int run = 0; 194 195 bit = 1; 196 loc = 0; 197 198 for (i = 0; i < fs->e2fs_fpg; i++) { 199 if ((bbp[loc] & bit) == 0) 200 run++; 201 else if (run != 0) { 202 if (run > fs->e2fs_contigsumsize) 203 run = fs->e2fs_contigsumsize; 204 sump[run]++; 205 run = 0; 206 } 207 if ((i & (NBBY - 1)) != (NBBY - 1)) 208 bit <<= 1; 209 else { 210 loc++; 211 bit = 1; 212 } 213 } 214 if (run != 0) { 215 if (run > fs->e2fs_contigsumsize) 216 run = fs->e2fs_contigsumsize; 217 sump[run]++; 218 } 219 fs->e2fs_clustersum[cg].cs_init = 1; 220 } 221 222 if (fs->e2fs_contigsumsize <= 0) 223 return; 224 225 /* Find the size of the cluster going forward. */ 226 start = bno + 1; 227 end = start + fs->e2fs_contigsumsize; 228 if (end > fs->e2fs_fpg) 229 end = fs->e2fs_fpg; 230 loc = start / NBBY; 231 bit = 1 << (start % NBBY); 232 for (i = start; i < end; i++) { 233 if ((bbp[loc] & bit) != 0) 234 break; 235 if ((i & (NBBY - 1)) != (NBBY - 1)) 236 bit <<= 1; 237 else { 238 loc++; 239 bit = 1; 240 } 241 } 242 forw = i - start; 243 244 /* Find the size of the cluster going backward. */ 245 start = bno - 1; 246 end = start - fs->e2fs_contigsumsize; 247 if (end < 0) 248 end = -1; 249 loc = start / NBBY; 250 bit = 1 << (start % NBBY); 251 for (i = start; i > end; i--) { 252 if ((bbp[loc] & bit) != 0) 253 break; 254 if ((i & (NBBY - 1)) != 0) 255 bit >>= 1; 256 else { 257 loc--; 258 bit = 1 << (NBBY - 1); 259 } 260 } 261 back = start - i; 262 263 /* 264 * Account for old cluster and the possibly new forward and 265 * back clusters. 266 */ 267 i = back + forw + 1; 268 if (i > fs->e2fs_contigsumsize) 269 i = fs->e2fs_contigsumsize; 270 sump[i] += cnt; 271 if (back > 0) 272 sump[back] -= cnt; 273 if (forw > 0) 274 sump[forw] -= cnt; 275 276 /* Update cluster summary information. */ 277 lp = &sump[fs->e2fs_contigsumsize]; 278 for (i = fs->e2fs_contigsumsize; i > 0; i--) 279 if (*lp-- > 0) 280 break; 281 fs->e2fs_maxcluster[cg] = i; 282 } 283