ffs_subr.c revision 31561
11541Srgrimes/* 21541Srgrimes * Copyright (c) 1982, 1986, 1989, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * 51541Srgrimes * Redistribution and use in source and binary forms, with or without 61541Srgrimes * modification, are permitted provided that the following conditions 71541Srgrimes * are met: 81541Srgrimes * 1. Redistributions of source code must retain the above copyright 91541Srgrimes * notice, this list of conditions and the following disclaimer. 101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111541Srgrimes * notice, this list of conditions and the following disclaimer in the 121541Srgrimes * documentation and/or other materials provided with the distribution. 131541Srgrimes * 3. All advertising materials mentioning features or use of this software 141541Srgrimes * must display the following acknowledgement: 151541Srgrimes * This product includes software developed by the University of 161541Srgrimes * California, Berkeley and its contributors. 171541Srgrimes * 4. Neither the name of the University nor the names of its contributors 181541Srgrimes * may be used to endorse or promote products derived from this software 191541Srgrimes * without specific prior written permission. 201541Srgrimes * 211541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311541Srgrimes * SUCH DAMAGE. 321541Srgrimes * 3322521Sdyson * @(#)ffs_subr.c 8.5 (Berkeley) 3/21/95 3431561Sbde * $Id: ffs_subr.c,v 1.15 1997/11/22 08:35:46 bde Exp $ 351541Srgrimes */ 361541Srgrimes 371541Srgrimes#include <sys/param.h> 3831274Sbde#include <ufs/ffs/fs.h> 3922521Sdyson 4022521Sdyson#ifndef KERNEL 4122521Sdyson#include <ufs/ufs/dinode.h> 4222521Sdyson#else 4313228Swollman#include "opt_ddb.h" 4413228Swollman 451541Srgrimes#include <sys/systm.h> 4631561Sbde#include <sys/lock.h> 471541Srgrimes#include <sys/vnode.h> 481541Srgrimes#include <sys/buf.h> 491541Srgrimes#include <ufs/ufs/quota.h> 501541Srgrimes#include <ufs/ufs/inode.h> 5122521Sdyson#include <ufs/ffs/ffs_extern.h> 521541Srgrimes 5331352Sbde#if defined(KERNEL) && defined(DIAGNOSTIC) && defined(DDB) 5431352Sbdestatic void ffs_checkoverlap __P((struct buf *, struct inode *)); 5531352Sbde#endif 5631352Sbde 571541Srgrimes/* 581541Srgrimes * Return buffer with the contents of block "offset" from the beginning of 591541Srgrimes * directory "ip". If "res" is non-zero, fill it in with a pointer to the 601541Srgrimes * remaining space in the directory. 611541Srgrimes */ 621541Srgrimesint 6330474Sphkffs_blkatoff(vp, offset, res, bpp) 6430474Sphk struct vnode *vp; 6530474Sphk off_t offset; 6630474Sphk char **res; 6730474Sphk struct buf **bpp; 681541Srgrimes{ 691541Srgrimes struct inode *ip; 701541Srgrimes register struct fs *fs; 711541Srgrimes struct buf *bp; 7222521Sdyson ufs_daddr_t lbn; 731541Srgrimes int bsize, error; 741541Srgrimes 7530474Sphk ip = VTOI(vp); 761541Srgrimes fs = ip->i_fs; 7730474Sphk lbn = lblkno(fs, offset); 781541Srgrimes bsize = blksize(fs, ip, lbn); 791541Srgrimes 8030474Sphk *bpp = NULL; 8130474Sphk error = bread(vp, lbn, bsize, NOCRED, &bp); 823487Sphk if (error) { 831541Srgrimes brelse(bp); 841541Srgrimes return (error); 851541Srgrimes } 8630474Sphk if (res) 8730474Sphk *res = (char *)bp->b_data + blkoff(fs, offset); 8830474Sphk *bpp = bp; 891541Srgrimes return (0); 901541Srgrimes} 911541Srgrimes#endif 921541Srgrimes 931541Srgrimes/* 948876Srgrimes * Update the frsum fields to reflect addition or deletion 951541Srgrimes * of some frags. 961541Srgrimes */ 971541Srgrimesvoid 981541Srgrimesffs_fragacct(fs, fragmap, fraglist, cnt) 991541Srgrimes struct fs *fs; 1001541Srgrimes int fragmap; 10122521Sdyson int32_t fraglist[]; 1021541Srgrimes int cnt; 1031541Srgrimes{ 1041541Srgrimes int inblk; 1051541Srgrimes register int field, subfield; 1061541Srgrimes register int siz, pos; 1071541Srgrimes 1081541Srgrimes inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; 1091541Srgrimes fragmap <<= 1; 1101541Srgrimes for (siz = 1; siz < fs->fs_frag; siz++) { 1111541Srgrimes if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) 1121541Srgrimes continue; 1131541Srgrimes field = around[siz]; 1141541Srgrimes subfield = inside[siz]; 1151541Srgrimes for (pos = siz; pos <= fs->fs_frag; pos++) { 1161541Srgrimes if ((fragmap & field) == subfield) { 1171541Srgrimes fraglist[siz] += cnt; 1181541Srgrimes pos += siz; 1191541Srgrimes field <<= siz; 1201541Srgrimes subfield <<= siz; 1211541Srgrimes } 1221541Srgrimes field <<= 1; 1231541Srgrimes subfield <<= 1; 1241541Srgrimes } 1251541Srgrimes } 1261541Srgrimes} 1271541Srgrimes 12812911Sphk#if defined(KERNEL) && defined(DIAGNOSTIC) && defined(DDB) 12931352Sbdestatic void 1301541Srgrimesffs_checkoverlap(bp, ip) 1311541Srgrimes struct buf *bp; 1321541Srgrimes struct inode *ip; 1331541Srgrimes{ 1341541Srgrimes register struct buf *ebp, *ep; 13522521Sdyson register ufs_daddr_t start, last; 1361541Srgrimes struct vnode *vp; 1371541Srgrimes 1381541Srgrimes ebp = &buf[nbuf]; 1391541Srgrimes start = bp->b_blkno; 1401541Srgrimes last = start + btodb(bp->b_bcount) - 1; 1411541Srgrimes for (ep = buf; ep < ebp; ep++) { 1421541Srgrimes if (ep == bp || (ep->b_flags & B_INVAL) || 1431541Srgrimes ep->b_vp == NULLVP) 1441541Srgrimes continue; 14522521Sdyson if (VOP_BMAP(ep->b_vp, (ufs_daddr_t)0, &vp, (ufs_daddr_t)0, 14622539Smpp NULL, NULL)) 1471541Srgrimes continue; 1481541Srgrimes if (vp != ip->i_devvp) 1491541Srgrimes continue; 1501541Srgrimes /* look for overlap */ 1511541Srgrimes if (ep->b_bcount == 0 || ep->b_blkno > last || 1521541Srgrimes ep->b_blkno + btodb(ep->b_bcount) <= start) 1531541Srgrimes continue; 1541541Srgrimes vprint("Disk overlap", vp); 1553487Sphk (void)printf("\tstart %lu, end %lu overlap start %lu, end %lu\n", 1563487Sphk (u_long)start, (u_long)last, (u_long)ep->b_blkno, 1573487Sphk (u_long)(ep->b_blkno + btodb(ep->b_bcount) - 1)); 15823560Smpp panic("ffs_checkoverlap: Disk buffer overlap"); 1591541Srgrimes } 1601541Srgrimes} 16131274Sbde#endif /* KERNEL && DIAGNOSTIC && DDB */ 1621541Srgrimes 1631541Srgrimes/* 1641541Srgrimes * block operations 1651541Srgrimes * 1661541Srgrimes * check if a block is available 1671541Srgrimes */ 1681541Srgrimesint 1691541Srgrimesffs_isblock(fs, cp, h) 1701541Srgrimes struct fs *fs; 1711541Srgrimes unsigned char *cp; 17222521Sdyson ufs_daddr_t h; 1731541Srgrimes{ 1741541Srgrimes unsigned char mask; 1751541Srgrimes 1761541Srgrimes switch ((int)fs->fs_frag) { 1771541Srgrimes case 8: 1781541Srgrimes return (cp[h] == 0xff); 1791541Srgrimes case 4: 1801541Srgrimes mask = 0x0f << ((h & 0x1) << 2); 1811541Srgrimes return ((cp[h >> 1] & mask) == mask); 1821541Srgrimes case 2: 1831541Srgrimes mask = 0x03 << ((h & 0x3) << 1); 1841541Srgrimes return ((cp[h >> 2] & mask) == mask); 1851541Srgrimes case 1: 1861541Srgrimes mask = 0x01 << (h & 0x7); 1871541Srgrimes return ((cp[h >> 3] & mask) == mask); 1881541Srgrimes default: 1891541Srgrimes panic("ffs_isblock"); 1901541Srgrimes } 1911541Srgrimes} 1921541Srgrimes 1931541Srgrimes/* 1941541Srgrimes * take a block out of the map 1951541Srgrimes */ 1961541Srgrimesvoid 1971541Srgrimesffs_clrblock(fs, cp, h) 1981541Srgrimes struct fs *fs; 1991541Srgrimes u_char *cp; 20022521Sdyson ufs_daddr_t h; 2011541Srgrimes{ 2021541Srgrimes 2031541Srgrimes switch ((int)fs->fs_frag) { 2041541Srgrimes case 8: 2051541Srgrimes cp[h] = 0; 2061541Srgrimes return; 2071541Srgrimes case 4: 2081541Srgrimes cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 2091541Srgrimes return; 2101541Srgrimes case 2: 2111541Srgrimes cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 2121541Srgrimes return; 2131541Srgrimes case 1: 2141541Srgrimes cp[h >> 3] &= ~(0x01 << (h & 0x7)); 2151541Srgrimes return; 2161541Srgrimes default: 2171541Srgrimes panic("ffs_clrblock"); 2181541Srgrimes } 2191541Srgrimes} 2201541Srgrimes 2211541Srgrimes/* 2221541Srgrimes * put a block into the map 2231541Srgrimes */ 2241541Srgrimesvoid 2251541Srgrimesffs_setblock(fs, cp, h) 2261541Srgrimes struct fs *fs; 2271541Srgrimes unsigned char *cp; 22822521Sdyson ufs_daddr_t h; 2291541Srgrimes{ 2301541Srgrimes 2311541Srgrimes switch ((int)fs->fs_frag) { 2321541Srgrimes 2331541Srgrimes case 8: 2341541Srgrimes cp[h] = 0xff; 2351541Srgrimes return; 2361541Srgrimes case 4: 2371541Srgrimes cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 2381541Srgrimes return; 2391541Srgrimes case 2: 2401541Srgrimes cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 2411541Srgrimes return; 2421541Srgrimes case 1: 2431541Srgrimes cp[h >> 3] |= (0x01 << (h & 0x7)); 2441541Srgrimes return; 2451541Srgrimes default: 2461541Srgrimes panic("ffs_setblock"); 2471541Srgrimes } 2481541Srgrimes} 249