ext2_subr.c revision 311231
1139778Simp/*- 212115Sdyson * modified for Lites 1.1 312115Sdyson * 412115Sdyson * Aug 1995, Godmar Back (gback@cs.utah.edu) 512115Sdyson * University of Utah, Department of Computer Science 612115Sdyson */ 7139778Simp/*- 812115Sdyson * Copyright (c) 1982, 1986, 1989, 1993 912115Sdyson * The Regents of the University of California. All rights reserved. 1012115Sdyson * 1112115Sdyson * Redistribution and use in source and binary forms, with or without 1212115Sdyson * modification, are permitted provided that the following conditions 1312115Sdyson * are met: 1412115Sdyson * 1. Redistributions of source code must retain the above copyright 1512115Sdyson * notice, this list of conditions and the following disclaimer. 1612115Sdyson * 2. Redistributions in binary form must reproduce the above copyright 1712115Sdyson * notice, this list of conditions and the following disclaimer in the 1812115Sdyson * documentation and/or other materials provided with the distribution. 1912115Sdyson * 4. Neither the name of the University nor the names of its contributors 2012115Sdyson * may be used to endorse or promote products derived from this software 2112115Sdyson * without specific prior written permission. 2212115Sdyson * 2312115Sdyson * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2412115Sdyson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2512115Sdyson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2612115Sdyson * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2712115Sdyson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2812115Sdyson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2912115Sdyson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3012115Sdyson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3112115Sdyson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3212115Sdyson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3312115Sdyson * SUCH DAMAGE. 3412115Sdyson * 3593015Sbde * @(#)ffs_subr.c 8.2 (Berkeley) 9/21/93 3660041Sphk * $FreeBSD: stable/11/sys/fs/ext2fs/ext2_subr.c 311231 2017-01-04 02:42:17Z pfg $ 3712115Sdyson */ 3812115Sdyson 3912115Sdyson#include <sys/param.h> 4012115Sdyson 4176166Smarkm#include <sys/proc.h> 4276166Smarkm#include <sys/systm.h> 4376166Smarkm#include <sys/bio.h> 4476166Smarkm#include <sys/buf.h> 4531561Sbde#include <sys/lock.h> 4669517Sbde#include <sys/ucred.h> 4712115Sdyson#include <sys/vnode.h> 4876166Smarkm 49202283Slulf#include <fs/ext2fs/inode.h> 50202283Slulf#include <fs/ext2fs/ext2_extern.h> 51202283Slulf#include <fs/ext2fs/ext2fs.h> 52202283Slulf#include <fs/ext2fs/fs.h> 53254260Spfg#include <fs/ext2fs/ext2_extents.h> 54254260Spfg#include <fs/ext2fs/ext2_mount.h> 55254260Spfg#include <fs/ext2fs/ext2_dinode.h> 5676166Smarkm 5712115Sdyson/* 5812115Sdyson * Return buffer with the contents of block "offset" from the beginning of 5912115Sdyson * directory "ip". If "res" is non-zero, fill it in with a pointer to the 6012115Sdyson * remaining space in the directory. 6112115Sdyson */ 6212115Sdysonint 63246634Spfgext2_blkatoff(struct vnode *vp, off_t offset, char **res, struct buf **bpp) 6412115Sdyson{ 6512115Sdyson struct inode *ip; 66202283Slulf struct m_ext2fs *fs; 6712115Sdyson struct buf *bp; 68252103Spfg e2fs_lbn_t lbn; 6912115Sdyson int bsize, error; 70254260Spfg daddr_t newblk; 71254260Spfg struct ext4_extent *ep; 72254260Spfg struct ext4_extent_path path; 7312115Sdyson 7430474Sphk ip = VTOI(vp); 7512115Sdyson fs = ip->i_e2fs; 7630474Sphk lbn = lblkno(fs, offset); 7712115Sdyson bsize = blksize(fs, ip, lbn); 78254260Spfg *bpp = NULL; 7912115Sdyson 80254260Spfg /* 81261235Spfg * IN_E4EXTENTS requires special treatment as we can otherwise fall 82260988Spfg * back to the normal path. 83254260Spfg */ 84261235Spfg if (!(ip->i_flag & IN_E4EXTENTS)) 85254260Spfg goto normal; 86254260Spfg 87254260Spfg memset(&path, 0, sizeof(path)); 88254260Spfg if (ext4_ext_find_extent(fs, ip, lbn, &path) == NULL) 89254260Spfg goto normal; 90254260Spfg ep = path.ep_ext; 91254260Spfg if (ep == NULL) 92254260Spfg goto normal; 93254260Spfg 94254260Spfg newblk = lbn - ep->e_blk + 95254260Spfg (ep->e_start_lo | (daddr_t)ep->e_start_hi << 32); 96254260Spfg 97254260Spfg if (path.ep_bp != NULL) { 98254260Spfg brelse(path.ep_bp); 99254260Spfg path.ep_bp = NULL; 100254260Spfg } 101254260Spfg error = bread(ip->i_devvp, fsbtodb(fs, newblk), bsize, NOCRED, &bp); 102254260Spfg if (error != 0) { 10312115Sdyson brelse(bp); 10412115Sdyson return (error); 10512115Sdyson } 10630474Sphk if (res) 10730474Sphk *res = (char *)bp->b_data + blkoff(fs, offset); 108254260Spfg /* 109261235Spfg * If IN_E4EXTENTS is enabled we would get a wrong offset so 110254260Spfg * reset b_offset here. 111254260Spfg */ 112254260Spfg bp->b_offset = lbn * bsize; 11330474Sphk *bpp = bp; 11412115Sdyson return (0); 115254260Spfg 116254260Spfgnormal: 117254260Spfg if (*bpp == NULL) { 118254260Spfg if ((error = bread(vp, lbn, bsize, NOCRED, &bp)) != 0) { 119254260Spfg brelse(bp); 120254260Spfg return (error); 121254260Spfg } 122254260Spfg if (res) 123254260Spfg *res = (char *)bp->b_data + blkoff(fs, offset); 124254260Spfg *bpp = bp; 125254260Spfg } 126254260Spfg return (0); 12712115Sdyson} 12812115Sdyson 129228539Spfg/* 130228539Spfg * Update the cluster map because of an allocation of free like ffs. 131228539Spfg * 132228539Spfg * Cnt == 1 means free; cnt == -1 means allocating. 133228539Spfg */ 134228539Spfgvoid 135228539Spfgext2_clusteracct(struct m_ext2fs *fs, char *bbp, int cg, daddr_t bno, int cnt) 136228539Spfg{ 137228539Spfg int32_t *sump = fs->e2fs_clustersum[cg].cs_sum; 138228539Spfg int32_t *lp; 139228539Spfg int back, bit, end, forw, i, loc, start; 140228539Spfg 141228539Spfg /* Initialize the cluster summary array. */ 142228539Spfg if (fs->e2fs_clustersum[cg].cs_init == 0) { 143228539Spfg int run = 0; 144311231Spfg 145228539Spfg bit = 1; 146228539Spfg loc = 0; 147228539Spfg 148228539Spfg for (i = 0; i < fs->e2fs->e2fs_fpg; i++) { 149228539Spfg if ((bbp[loc] & bit) == 0) 150228539Spfg run++; 151228539Spfg else if (run != 0) { 152228539Spfg if (run > fs->e2fs_contigsumsize) 153228539Spfg run = fs->e2fs_contigsumsize; 154228539Spfg sump[run]++; 155228539Spfg run = 0; 156228539Spfg } 157228539Spfg if ((i & (NBBY - 1)) != (NBBY - 1)) 158228539Spfg bit <<= 1; 159228539Spfg else { 160228539Spfg loc++; 161228539Spfg bit = 1; 162228539Spfg } 163228539Spfg } 164228539Spfg if (run != 0) { 165228539Spfg if (run > fs->e2fs_contigsumsize) 166228539Spfg run = fs->e2fs_contigsumsize; 167228539Spfg sump[run]++; 168228539Spfg } 169228539Spfg fs->e2fs_clustersum[cg].cs_init = 1; 170228539Spfg } 171228539Spfg 172228539Spfg if (fs->e2fs_contigsumsize <= 0) 173228539Spfg return; 174228539Spfg 175228539Spfg /* Find the size of the cluster going forward. */ 176228539Spfg start = bno + 1; 177228539Spfg end = start + fs->e2fs_contigsumsize; 178228539Spfg if (end > fs->e2fs->e2fs_fpg) 179228539Spfg end = fs->e2fs->e2fs_fpg; 180228539Spfg loc = start / NBBY; 181228539Spfg bit = 1 << (start % NBBY); 182228539Spfg for (i = start; i < end; i++) { 183228539Spfg if ((bbp[loc] & bit) != 0) 184228539Spfg break; 185228539Spfg if ((i & (NBBY - 1)) != (NBBY - 1)) 186228539Spfg bit <<= 1; 187228539Spfg else { 188228539Spfg loc++; 189228539Spfg bit = 1; 190228539Spfg } 191228539Spfg } 192228539Spfg forw = i - start; 193228539Spfg 194228539Spfg /* Find the size of the cluster going backward. */ 195228539Spfg start = bno - 1; 196228539Spfg end = start - fs->e2fs_contigsumsize; 197228539Spfg if (end < 0) 198228539Spfg end = -1; 199228539Spfg loc = start / NBBY; 200228539Spfg bit = 1 << (start % NBBY); 201228539Spfg for (i = start; i > end; i--) { 202228539Spfg if ((bbp[loc] & bit) != 0) 203228539Spfg break; 204228539Spfg if ((i & (NBBY - 1)) != 0) 205228539Spfg bit >>= 1; 206228539Spfg else { 207228539Spfg loc--; 208228539Spfg bit = 1 << (NBBY - 1); 209228539Spfg } 210228539Spfg } 211228539Spfg back = start - i; 212228539Spfg 213228539Spfg /* 214228539Spfg * Account for old cluster and the possibly new forward and 215228539Spfg * back clusters. 216228539Spfg */ 217228539Spfg i = back + forw + 1; 218228539Spfg if (i > fs->e2fs_contigsumsize) 219228539Spfg i = fs->e2fs_contigsumsize; 220228539Spfg sump[i] += cnt; 221228539Spfg if (back > 0) 222228539Spfg sump[back] -= cnt; 223228539Spfg if (forw > 0) 224228539Spfg sump[forw] -= cnt; 225228539Spfg 226228539Spfg /* Update cluster summary information. */ 227228539Spfg lp = &sump[fs->e2fs_contigsumsize]; 228228539Spfg for (i = fs->e2fs_contigsumsize; i > 0; i--) 229228539Spfg if (*lp-- > 0) 230228539Spfg break; 231228539Spfg fs->e2fs_maxcluster[cg] = i; 232228539Spfg} 233