1*cfe60390STomohiro Kusumi /*- 2*cfe60390STomohiro Kusumi * modified for Lites 1.1 3*cfe60390STomohiro Kusumi * 4*cfe60390STomohiro Kusumi * Aug 1995, Godmar Back (gback@cs.utah.edu) 5*cfe60390STomohiro Kusumi * University of Utah, Department of Computer Science 6*cfe60390STomohiro Kusumi */ 7*cfe60390STomohiro Kusumi /*- 8*cfe60390STomohiro Kusumi * SPDX-License-Identifier: BSD-3-Clause 9*cfe60390STomohiro Kusumi * 10*cfe60390STomohiro Kusumi * Copyright (c) 1982, 1986, 1989, 1993 11*cfe60390STomohiro Kusumi * The Regents of the University of California. All rights reserved. 12*cfe60390STomohiro Kusumi * 13*cfe60390STomohiro Kusumi * Redistribution and use in source and binary forms, with or without 14*cfe60390STomohiro Kusumi * modification, are permitted provided that the following conditions 15*cfe60390STomohiro Kusumi * are met: 16*cfe60390STomohiro Kusumi * 1. Redistributions of source code must retain the above copyright 17*cfe60390STomohiro Kusumi * notice, this list of conditions and the following disclaimer. 18*cfe60390STomohiro Kusumi * 2. Redistributions in binary form must reproduce the above copyright 19*cfe60390STomohiro Kusumi * notice, this list of conditions and the following disclaimer in the 20*cfe60390STomohiro Kusumi * documentation and/or other materials provided with the distribution. 21*cfe60390STomohiro Kusumi * 3. Neither the name of the University nor the names of its contributors 22*cfe60390STomohiro Kusumi * may be used to endorse or promote products derived from this software 23*cfe60390STomohiro Kusumi * without specific prior written permission. 24*cfe60390STomohiro Kusumi * 25*cfe60390STomohiro Kusumi * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26*cfe60390STomohiro Kusumi * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27*cfe60390STomohiro Kusumi * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28*cfe60390STomohiro Kusumi * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29*cfe60390STomohiro Kusumi * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30*cfe60390STomohiro Kusumi * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31*cfe60390STomohiro Kusumi * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32*cfe60390STomohiro Kusumi * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33*cfe60390STomohiro Kusumi * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34*cfe60390STomohiro Kusumi * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35*cfe60390STomohiro Kusumi * SUCH DAMAGE. 36*cfe60390STomohiro Kusumi * 37*cfe60390STomohiro Kusumi * @(#)ffs_subr.c 8.2 (Berkeley) 9/21/93 38*cfe60390STomohiro Kusumi * $FreeBSD$ 39*cfe60390STomohiro Kusumi */ 40*cfe60390STomohiro Kusumi 41*cfe60390STomohiro Kusumi #include <sys/param.h> 42*cfe60390STomohiro Kusumi 43*cfe60390STomohiro Kusumi #include <sys/proc.h> 44*cfe60390STomohiro Kusumi #include <sys/systm.h> 45*cfe60390STomohiro Kusumi #include <sys/bio.h> 46*cfe60390STomohiro Kusumi #include <sys/buf2.h> 47*cfe60390STomohiro Kusumi #include <sys/lock.h> 48*cfe60390STomohiro Kusumi #include <sys/ucred.h> 49*cfe60390STomohiro Kusumi #include <sys/vnode.h> 50*cfe60390STomohiro Kusumi #include <sys/mount.h> 51*cfe60390STomohiro Kusumi #include <sys/malloc.h> 52*cfe60390STomohiro Kusumi 53*cfe60390STomohiro Kusumi #include <vfs/ext2fs/fs.h> 54*cfe60390STomohiro Kusumi #include <vfs/ext2fs/inode.h> 55*cfe60390STomohiro Kusumi #include <vfs/ext2fs/ext2fs.h> 56*cfe60390STomohiro Kusumi #include <vfs/ext2fs/ext2_extern.h> 57*cfe60390STomohiro Kusumi #include <vfs/ext2fs/fs.h> 58*cfe60390STomohiro Kusumi #include <vfs/ext2fs/ext2_extents.h> 59*cfe60390STomohiro Kusumi #include <vfs/ext2fs/ext2_mount.h> 60*cfe60390STomohiro Kusumi #include <vfs/ext2fs/ext2_dinode.h> 61*cfe60390STomohiro Kusumi 62*cfe60390STomohiro Kusumi void 63*cfe60390STomohiro Kusumi ext2_free(void *addr, struct malloc_type *type, const char *func) 64*cfe60390STomohiro Kusumi { 65*cfe60390STomohiro Kusumi if (addr == NULL) { 66*cfe60390STomohiro Kusumi printf("%s: trying to free NULL pointer\n", func); 67*cfe60390STomohiro Kusumi return; 68*cfe60390STomohiro Kusumi } 69*cfe60390STomohiro Kusumi kfree(addr, type); 70*cfe60390STomohiro Kusumi } 71*cfe60390STomohiro Kusumi 72*cfe60390STomohiro Kusumi int 73*cfe60390STomohiro Kusumi ext2_bread(struct vnode *vp, off_t loffset, int size, struct buf **bpp) 74*cfe60390STomohiro Kusumi { 75*cfe60390STomohiro Kusumi struct buf *bp; 76*cfe60390STomohiro Kusumi int error; 77*cfe60390STomohiro Kusumi 78*cfe60390STomohiro Kusumi *bpp = NULL; 79*cfe60390STomohiro Kusumi error = bread(vp, loffset, size, &bp); 80*cfe60390STomohiro Kusumi if (error) { 81*cfe60390STomohiro Kusumi ext2_brelse(bp); 82*cfe60390STomohiro Kusumi return (error); 83*cfe60390STomohiro Kusumi } 84*cfe60390STomohiro Kusumi 85*cfe60390STomohiro Kusumi *bpp = bp; 86*cfe60390STomohiro Kusumi return (0); 87*cfe60390STomohiro Kusumi } 88*cfe60390STomohiro Kusumi 89*cfe60390STomohiro Kusumi int 90*cfe60390STomohiro Kusumi ext2_breadn(struct vnode *vp, off_t loffset, int size, off_t *raoffset, 91*cfe60390STomohiro Kusumi int *rabsize, int cnt, struct buf **bpp) 92*cfe60390STomohiro Kusumi { 93*cfe60390STomohiro Kusumi struct buf *bp; 94*cfe60390STomohiro Kusumi int error; 95*cfe60390STomohiro Kusumi 96*cfe60390STomohiro Kusumi *bpp = NULL; 97*cfe60390STomohiro Kusumi error = breadn(vp, loffset, size, raoffset, rabsize, cnt, &bp); 98*cfe60390STomohiro Kusumi if (error) { 99*cfe60390STomohiro Kusumi ext2_brelse(bp); 100*cfe60390STomohiro Kusumi return (error); 101*cfe60390STomohiro Kusumi } 102*cfe60390STomohiro Kusumi 103*cfe60390STomohiro Kusumi *bpp = bp; 104*cfe60390STomohiro Kusumi return (0); 105*cfe60390STomohiro Kusumi } 106*cfe60390STomohiro Kusumi 107*cfe60390STomohiro Kusumi int 108*cfe60390STomohiro Kusumi ext2_cluster_read(struct vnode *vp, off_t filesize, off_t loffset, int blksize, 109*cfe60390STomohiro Kusumi size_t minreq, size_t maxreq, struct buf **bpp) 110*cfe60390STomohiro Kusumi { 111*cfe60390STomohiro Kusumi struct buf *bp; 112*cfe60390STomohiro Kusumi int error; 113*cfe60390STomohiro Kusumi 114*cfe60390STomohiro Kusumi *bpp = NULL; 115*cfe60390STomohiro Kusumi error = cluster_read(vp, filesize, loffset, blksize, minreq, maxreq, 116*cfe60390STomohiro Kusumi &bp); 117*cfe60390STomohiro Kusumi if (error) { 118*cfe60390STomohiro Kusumi ext2_brelse(bp); 119*cfe60390STomohiro Kusumi return (error); 120*cfe60390STomohiro Kusumi } 121*cfe60390STomohiro Kusumi 122*cfe60390STomohiro Kusumi *bpp = bp; 123*cfe60390STomohiro Kusumi return (0); 124*cfe60390STomohiro Kusumi } 125*cfe60390STomohiro Kusumi 126*cfe60390STomohiro Kusumi void 127*cfe60390STomohiro Kusumi ext2_brelse(struct buf *bp) 128*cfe60390STomohiro Kusumi { 129*cfe60390STomohiro Kusumi if (bp == NULL) 130*cfe60390STomohiro Kusumi return; 131*cfe60390STomohiro Kusumi brelse(bp); 132*cfe60390STomohiro Kusumi } 133*cfe60390STomohiro Kusumi 134*cfe60390STomohiro Kusumi void 135*cfe60390STomohiro Kusumi ext2_bqrelse(struct buf *bp) 136*cfe60390STomohiro Kusumi { 137*cfe60390STomohiro Kusumi if (bp == NULL) 138*cfe60390STomohiro Kusumi return; 139*cfe60390STomohiro Kusumi bqrelse(bp); 140*cfe60390STomohiro Kusumi } 141*cfe60390STomohiro Kusumi 142*cfe60390STomohiro Kusumi /* 143*cfe60390STomohiro Kusumi * Return buffer with the contents of block "offset" from the beginning of 144*cfe60390STomohiro Kusumi * directory "ip". If "res" is non-zero, fill it in with a pointer to the 145*cfe60390STomohiro Kusumi * remaining space in the directory. 146*cfe60390STomohiro Kusumi */ 147*cfe60390STomohiro Kusumi int 148*cfe60390STomohiro Kusumi ext2_blkatoff(struct vnode *vp, off_t offset, char **res, struct buf **bpp) 149*cfe60390STomohiro Kusumi { 150*cfe60390STomohiro Kusumi struct inode *ip; 151*cfe60390STomohiro Kusumi struct m_ext2fs *fs; 152*cfe60390STomohiro Kusumi struct buf *bp; 153*cfe60390STomohiro Kusumi e2fs_lbn_t lbn; 154*cfe60390STomohiro Kusumi int error, bsize; 155*cfe60390STomohiro Kusumi 156*cfe60390STomohiro Kusumi ip = VTOI(vp); 157*cfe60390STomohiro Kusumi fs = ip->i_e2fs; 158*cfe60390STomohiro Kusumi lbn = lblkno(fs, offset); 159*cfe60390STomohiro Kusumi bsize = blksize(fs, ip, lbn); 160*cfe60390STomohiro Kusumi 161*cfe60390STomohiro Kusumi if ((error = ext2_bread(vp, lblktodoff(fs, lbn), bsize, &bp)) != 0) { 162*cfe60390STomohiro Kusumi ext2_brelse(bp); 163*cfe60390STomohiro Kusumi return (error); 164*cfe60390STomohiro Kusumi } 165*cfe60390STomohiro Kusumi error = ext2_dir_blk_csum_verify(ip, bp); 166*cfe60390STomohiro Kusumi if (error != 0) { 167*cfe60390STomohiro Kusumi ext2_brelse(bp); 168*cfe60390STomohiro Kusumi return (error); 169*cfe60390STomohiro Kusumi } 170*cfe60390STomohiro Kusumi if (res) 171*cfe60390STomohiro Kusumi *res = (char *)bp->b_data + blkoff(fs, offset); 172*cfe60390STomohiro Kusumi 173*cfe60390STomohiro Kusumi *bpp = bp; 174*cfe60390STomohiro Kusumi 175*cfe60390STomohiro Kusumi return (0); 176*cfe60390STomohiro Kusumi } 177*cfe60390STomohiro Kusumi 178*cfe60390STomohiro Kusumi /* 179*cfe60390STomohiro Kusumi * Update the cluster map because of an allocation of free like ffs. 180*cfe60390STomohiro Kusumi * 181*cfe60390STomohiro Kusumi * Cnt == 1 means free; cnt == -1 means allocating. 182*cfe60390STomohiro Kusumi */ 183*cfe60390STomohiro Kusumi void 184*cfe60390STomohiro Kusumi ext2_clusteracct(struct m_ext2fs *fs, char *bbp, int cg, e4fs_daddr_t bno, int cnt) 185*cfe60390STomohiro Kusumi { 186*cfe60390STomohiro Kusumi int32_t *sump = fs->e2fs_clustersum[cg].cs_sum; 187*cfe60390STomohiro Kusumi int32_t *lp; 188*cfe60390STomohiro Kusumi e4fs_daddr_t start, end, loc, forw, back; 189*cfe60390STomohiro Kusumi int bit, i; 190*cfe60390STomohiro Kusumi 191*cfe60390STomohiro Kusumi /* Initialize the cluster summary array. */ 192*cfe60390STomohiro Kusumi if (fs->e2fs_clustersum[cg].cs_init == 0) { 193*cfe60390STomohiro Kusumi int run = 0; 194*cfe60390STomohiro Kusumi 195*cfe60390STomohiro Kusumi bit = 1; 196*cfe60390STomohiro Kusumi loc = 0; 197*cfe60390STomohiro Kusumi 198*cfe60390STomohiro Kusumi for (i = 0; i < fs->e2fs_fpg; i++) { 199*cfe60390STomohiro Kusumi if ((bbp[loc] & bit) == 0) 200*cfe60390STomohiro Kusumi run++; 201*cfe60390STomohiro Kusumi else if (run != 0) { 202*cfe60390STomohiro Kusumi if (run > fs->e2fs_contigsumsize) 203*cfe60390STomohiro Kusumi run = fs->e2fs_contigsumsize; 204*cfe60390STomohiro Kusumi sump[run]++; 205*cfe60390STomohiro Kusumi run = 0; 206*cfe60390STomohiro Kusumi } 207*cfe60390STomohiro Kusumi if ((i & (NBBY - 1)) != (NBBY - 1)) 208*cfe60390STomohiro Kusumi bit <<= 1; 209*cfe60390STomohiro Kusumi else { 210*cfe60390STomohiro Kusumi loc++; 211*cfe60390STomohiro Kusumi bit = 1; 212*cfe60390STomohiro Kusumi } 213*cfe60390STomohiro Kusumi } 214*cfe60390STomohiro Kusumi if (run != 0) { 215*cfe60390STomohiro Kusumi if (run > fs->e2fs_contigsumsize) 216*cfe60390STomohiro Kusumi run = fs->e2fs_contigsumsize; 217*cfe60390STomohiro Kusumi sump[run]++; 218*cfe60390STomohiro Kusumi } 219*cfe60390STomohiro Kusumi fs->e2fs_clustersum[cg].cs_init = 1; 220*cfe60390STomohiro Kusumi } 221*cfe60390STomohiro Kusumi 222*cfe60390STomohiro Kusumi if (fs->e2fs_contigsumsize <= 0) 223*cfe60390STomohiro Kusumi return; 224*cfe60390STomohiro Kusumi 225*cfe60390STomohiro Kusumi /* Find the size of the cluster going forward. */ 226*cfe60390STomohiro Kusumi start = bno + 1; 227*cfe60390STomohiro Kusumi end = start + fs->e2fs_contigsumsize; 228*cfe60390STomohiro Kusumi if (end > fs->e2fs_fpg) 229*cfe60390STomohiro Kusumi end = fs->e2fs_fpg; 230*cfe60390STomohiro Kusumi loc = start / NBBY; 231*cfe60390STomohiro Kusumi bit = 1 << (start % NBBY); 232*cfe60390STomohiro Kusumi for (i = start; i < end; i++) { 233*cfe60390STomohiro Kusumi if ((bbp[loc] & bit) != 0) 234*cfe60390STomohiro Kusumi break; 235*cfe60390STomohiro Kusumi if ((i & (NBBY - 1)) != (NBBY - 1)) 236*cfe60390STomohiro Kusumi bit <<= 1; 237*cfe60390STomohiro Kusumi else { 238*cfe60390STomohiro Kusumi loc++; 239*cfe60390STomohiro Kusumi bit = 1; 240*cfe60390STomohiro Kusumi } 241*cfe60390STomohiro Kusumi } 242*cfe60390STomohiro Kusumi forw = i - start; 243*cfe60390STomohiro Kusumi 244*cfe60390STomohiro Kusumi /* Find the size of the cluster going backward. */ 245*cfe60390STomohiro Kusumi start = bno - 1; 246*cfe60390STomohiro Kusumi end = start - fs->e2fs_contigsumsize; 247*cfe60390STomohiro Kusumi if (end < 0) 248*cfe60390STomohiro Kusumi end = -1; 249*cfe60390STomohiro Kusumi loc = start / NBBY; 250*cfe60390STomohiro Kusumi bit = 1 << (start % NBBY); 251*cfe60390STomohiro Kusumi for (i = start; i > end; i--) { 252*cfe60390STomohiro Kusumi if ((bbp[loc] & bit) != 0) 253*cfe60390STomohiro Kusumi break; 254*cfe60390STomohiro Kusumi if ((i & (NBBY - 1)) != 0) 255*cfe60390STomohiro Kusumi bit >>= 1; 256*cfe60390STomohiro Kusumi else { 257*cfe60390STomohiro Kusumi loc--; 258*cfe60390STomohiro Kusumi bit = 1 << (NBBY - 1); 259*cfe60390STomohiro Kusumi } 260*cfe60390STomohiro Kusumi } 261*cfe60390STomohiro Kusumi back = start - i; 262*cfe60390STomohiro Kusumi 263*cfe60390STomohiro Kusumi /* 264*cfe60390STomohiro Kusumi * Account for old cluster and the possibly new forward and 265*cfe60390STomohiro Kusumi * back clusters. 266*cfe60390STomohiro Kusumi */ 267*cfe60390STomohiro Kusumi i = back + forw + 1; 268*cfe60390STomohiro Kusumi if (i > fs->e2fs_contigsumsize) 269*cfe60390STomohiro Kusumi i = fs->e2fs_contigsumsize; 270*cfe60390STomohiro Kusumi sump[i] += cnt; 271*cfe60390STomohiro Kusumi if (back > 0) 272*cfe60390STomohiro Kusumi sump[back] -= cnt; 273*cfe60390STomohiro Kusumi if (forw > 0) 274*cfe60390STomohiro Kusumi sump[forw] -= cnt; 275*cfe60390STomohiro Kusumi 276*cfe60390STomohiro Kusumi /* Update cluster summary information. */ 277*cfe60390STomohiro Kusumi lp = &sump[fs->e2fs_contigsumsize]; 278*cfe60390STomohiro Kusumi for (i = fs->e2fs_contigsumsize; i > 0; i--) 279*cfe60390STomohiro Kusumi if (*lp-- > 0) 280*cfe60390STomohiro Kusumi break; 281*cfe60390STomohiro Kusumi fs->e2fs_maxcluster[cg] = i; 282*cfe60390STomohiro Kusumi } 283