1139825Simp/*- 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 * 4. Neither the name of the University nor the names of its contributors 141541Srgrimes * may be used to endorse or promote products derived from this software 151541Srgrimes * without specific prior written permission. 161541Srgrimes * 171541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271541Srgrimes * SUCH DAMAGE. 281541Srgrimes * 2922521Sdyson * @(#)ffs_subr.c 8.5 (Berkeley) 3/21/95 301541Srgrimes */ 311541Srgrimes 32116192Sobrien#include <sys/cdefs.h> 33116192Sobrien__FBSDID("$FreeBSD$"); 34116192Sobrien 351541Srgrimes#include <sys/param.h> 3622521Sdyson 3755206Speter#ifndef _KERNEL 3822521Sdyson#include <ufs/ufs/dinode.h> 3998542Smckusick#include <ufs/ffs/fs.h> 4022521Sdyson#else 411541Srgrimes#include <sys/systm.h> 4231561Sbde#include <sys/lock.h> 4398542Smckusick#include <sys/malloc.h> 4498542Smckusick#include <sys/mount.h> 451541Srgrimes#include <sys/vnode.h> 4660041Sphk#include <sys/bio.h> 471541Srgrimes#include <sys/buf.h> 4834924Sbde#include <sys/ucred.h> 4934924Sbde 501541Srgrimes#include <ufs/ufs/quota.h> 511541Srgrimes#include <ufs/ufs/inode.h> 5298542Smckusick#include <ufs/ufs/extattr.h> 5398542Smckusick#include <ufs/ufs/ufsmount.h> 5498542Smckusick#include <ufs/ufs/ufs_extern.h> 5522521Sdyson#include <ufs/ffs/ffs_extern.h> 5698542Smckusick#include <ufs/ffs/fs.h> 571541Srgrimes 58131907Smarcel#ifdef KDB 5992728Salfredvoid ffs_checkoverlap(struct buf *, struct inode *); 6031352Sbde#endif 6131352Sbde 621541Srgrimes/* 631541Srgrimes * Return buffer with the contents of block "offset" from the beginning of 641541Srgrimes * directory "ip". If "res" is non-zero, fill it in with a pointer to the 651541Srgrimes * remaining space in the directory. 661541Srgrimes */ 671541Srgrimesint 6830474Sphkffs_blkatoff(vp, offset, res, bpp) 6930474Sphk struct vnode *vp; 7030474Sphk off_t offset; 7130474Sphk char **res; 7230474Sphk struct buf **bpp; 731541Srgrimes{ 741541Srgrimes struct inode *ip; 7596506Sphk struct fs *fs; 761541Srgrimes struct buf *bp; 7798542Smckusick ufs_lbn_t lbn; 781541Srgrimes int bsize, error; 791541Srgrimes 8030474Sphk ip = VTOI(vp); 811541Srgrimes fs = ip->i_fs; 8230474Sphk lbn = lblkno(fs, offset); 831541Srgrimes bsize = blksize(fs, ip, lbn); 841541Srgrimes 8530474Sphk *bpp = NULL; 8630474Sphk error = bread(vp, lbn, bsize, NOCRED, &bp); 873487Sphk if (error) { 881541Srgrimes brelse(bp); 891541Srgrimes return (error); 901541Srgrimes } 9130474Sphk if (res) 9230474Sphk *res = (char *)bp->b_data + blkoff(fs, offset); 9330474Sphk *bpp = bp; 941541Srgrimes return (0); 951541Srgrimes} 961541Srgrimes 971541Srgrimes/* 9898542Smckusick * Load up the contents of an inode and copy the appropriate pieces 9998542Smckusick * to the incore copy. 10098542Smckusick */ 10198542Smckusickvoid 102108315Sphkffs_load_inode(bp, ip, fs, ino) 10398542Smckusick struct buf *bp; 10498542Smckusick struct inode *ip; 10598542Smckusick struct fs *fs; 10698542Smckusick ino_t ino; 10798542Smckusick{ 10898542Smckusick 10998542Smckusick if (ip->i_ump->um_fstype == UFS1) { 11098542Smckusick *ip->i_din1 = 11198542Smckusick *((struct ufs1_dinode *)bp->b_data + ino_to_fsbo(fs, ino)); 11298542Smckusick ip->i_mode = ip->i_din1->di_mode; 11398542Smckusick ip->i_nlink = ip->i_din1->di_nlink; 11498542Smckusick ip->i_size = ip->i_din1->di_size; 11598542Smckusick ip->i_flags = ip->i_din1->di_flags; 11698542Smckusick ip->i_gen = ip->i_din1->di_gen; 11798542Smckusick ip->i_uid = ip->i_din1->di_uid; 11898542Smckusick ip->i_gid = ip->i_din1->di_gid; 11998542Smckusick } else { 12098542Smckusick *ip->i_din2 = 12198542Smckusick *((struct ufs2_dinode *)bp->b_data + ino_to_fsbo(fs, ino)); 12298542Smckusick ip->i_mode = ip->i_din2->di_mode; 12398542Smckusick ip->i_nlink = ip->i_din2->di_nlink; 12498542Smckusick ip->i_size = ip->i_din2->di_size; 12598542Smckusick ip->i_flags = ip->i_din2->di_flags; 12698542Smckusick ip->i_gen = ip->i_din2->di_gen; 12798542Smckusick ip->i_uid = ip->i_din2->di_uid; 12898542Smckusick ip->i_gid = ip->i_din2->di_gid; 12998542Smckusick } 13098542Smckusick} 13198542Smckusick#endif /* KERNEL */ 13298542Smckusick 13398542Smckusick/* 1348876Srgrimes * Update the frsum fields to reflect addition or deletion 1351541Srgrimes * of some frags. 1361541Srgrimes */ 1371541Srgrimesvoid 1381541Srgrimesffs_fragacct(fs, fragmap, fraglist, cnt) 1391541Srgrimes struct fs *fs; 1401541Srgrimes int fragmap; 14122521Sdyson int32_t fraglist[]; 1421541Srgrimes int cnt; 1431541Srgrimes{ 1441541Srgrimes int inblk; 14596506Sphk int field, subfield; 14696506Sphk int siz, pos; 1471541Srgrimes 1481541Srgrimes inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; 1491541Srgrimes fragmap <<= 1; 1501541Srgrimes for (siz = 1; siz < fs->fs_frag; siz++) { 1511541Srgrimes if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) 1521541Srgrimes continue; 1531541Srgrimes field = around[siz]; 1541541Srgrimes subfield = inside[siz]; 1551541Srgrimes for (pos = siz; pos <= fs->fs_frag; pos++) { 1561541Srgrimes if ((fragmap & field) == subfield) { 1571541Srgrimes fraglist[siz] += cnt; 1581541Srgrimes pos += siz; 1591541Srgrimes field <<= siz; 1601541Srgrimes subfield <<= siz; 1611541Srgrimes } 1621541Srgrimes field <<= 1; 1631541Srgrimes subfield <<= 1; 1641541Srgrimes } 1651541Srgrimes } 1661541Srgrimes} 1671541Srgrimes 168131907Smarcel#ifdef KDB 16942567Seivindvoid 1701541Srgrimesffs_checkoverlap(bp, ip) 1711541Srgrimes struct buf *bp; 1721541Srgrimes struct inode *ip; 1731541Srgrimes{ 17496506Sphk struct buf *ebp, *ep; 17598542Smckusick ufs2_daddr_t start, last; 1761541Srgrimes struct vnode *vp; 1771541Srgrimes 1781541Srgrimes ebp = &buf[nbuf]; 1791541Srgrimes start = bp->b_blkno; 1801541Srgrimes last = start + btodb(bp->b_bcount) - 1; 1811541Srgrimes for (ep = buf; ep < ebp; ep++) { 1821541Srgrimes if (ep == bp || (ep->b_flags & B_INVAL) || 1831541Srgrimes ep->b_vp == NULLVP) 1841541Srgrimes continue; 18576173Sphk vp = ip->i_devvp; 1861541Srgrimes /* look for overlap */ 1871541Srgrimes if (ep->b_bcount == 0 || ep->b_blkno > last || 1881541Srgrimes ep->b_blkno + btodb(ep->b_bcount) <= start) 1891541Srgrimes continue; 1901541Srgrimes vprint("Disk overlap", vp); 19198687Smux printf("\tstart %jd, end %jd overlap start %jd, end %jd\n", 19298542Smckusick (intmax_t)start, (intmax_t)last, (intmax_t)ep->b_blkno, 19398542Smckusick (intmax_t)(ep->b_blkno + btodb(ep->b_bcount) - 1)); 19423560Smpp panic("ffs_checkoverlap: Disk buffer overlap"); 1951541Srgrimes } 1961541Srgrimes} 197131907Smarcel#endif /* KDB */ 1981541Srgrimes 1991541Srgrimes/* 2001541Srgrimes * block operations 2011541Srgrimes * 2021541Srgrimes * check if a block is available 2031541Srgrimes */ 2041541Srgrimesint 2051541Srgrimesffs_isblock(fs, cp, h) 2061541Srgrimes struct fs *fs; 2071541Srgrimes unsigned char *cp; 20898542Smckusick ufs1_daddr_t h; 2091541Srgrimes{ 2101541Srgrimes unsigned char mask; 2111541Srgrimes 2121541Srgrimes switch ((int)fs->fs_frag) { 2131541Srgrimes case 8: 2141541Srgrimes return (cp[h] == 0xff); 2151541Srgrimes case 4: 2161541Srgrimes mask = 0x0f << ((h & 0x1) << 2); 2171541Srgrimes return ((cp[h >> 1] & mask) == mask); 2181541Srgrimes case 2: 2191541Srgrimes mask = 0x03 << ((h & 0x3) << 1); 2201541Srgrimes return ((cp[h >> 2] & mask) == mask); 2211541Srgrimes case 1: 2221541Srgrimes mask = 0x01 << (h & 0x7); 2231541Srgrimes return ((cp[h >> 3] & mask) == mask); 2241541Srgrimes default: 225207141Sjeff#ifdef _KERNEL 2261541Srgrimes panic("ffs_isblock"); 227207141Sjeff#endif 228207141Sjeff break; 2291541Srgrimes } 23073942Smckusick return (0); 2311541Srgrimes} 2321541Srgrimes 2331541Srgrimes/* 234207141Sjeff * check if a block is free 235207141Sjeff */ 236207141Sjeffint 237207141Sjeffffs_isfreeblock(fs, cp, h) 238207141Sjeff struct fs *fs; 239207141Sjeff u_char *cp; 240207141Sjeff ufs1_daddr_t h; 241207141Sjeff{ 242207141Sjeff 243207141Sjeff switch ((int)fs->fs_frag) { 244207141Sjeff case 8: 245207141Sjeff return (cp[h] == 0); 246207141Sjeff case 4: 247207141Sjeff return ((cp[h >> 1] & (0x0f << ((h & 0x1) << 2))) == 0); 248207141Sjeff case 2: 249207141Sjeff return ((cp[h >> 2] & (0x03 << ((h & 0x3) << 1))) == 0); 250207141Sjeff case 1: 251207141Sjeff return ((cp[h >> 3] & (0x01 << (h & 0x7))) == 0); 252207141Sjeff default: 253207141Sjeff#ifdef _KERNEL 254207141Sjeff panic("ffs_isfreeblock"); 255207141Sjeff#endif 256207141Sjeff break; 257207141Sjeff } 258207141Sjeff return (0); 259207141Sjeff} 260207141Sjeff 261207141Sjeff/* 2621541Srgrimes * take a block out of the map 2631541Srgrimes */ 2641541Srgrimesvoid 2651541Srgrimesffs_clrblock(fs, cp, h) 2661541Srgrimes struct fs *fs; 2671541Srgrimes u_char *cp; 26898542Smckusick ufs1_daddr_t h; 2691541Srgrimes{ 2701541Srgrimes 2711541Srgrimes switch ((int)fs->fs_frag) { 2721541Srgrimes case 8: 2731541Srgrimes cp[h] = 0; 2741541Srgrimes return; 2751541Srgrimes case 4: 2761541Srgrimes cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 2771541Srgrimes return; 2781541Srgrimes case 2: 2791541Srgrimes cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 2801541Srgrimes return; 2811541Srgrimes case 1: 2821541Srgrimes cp[h >> 3] &= ~(0x01 << (h & 0x7)); 2831541Srgrimes return; 2841541Srgrimes default: 285207141Sjeff#ifdef _KERNEL 2861541Srgrimes panic("ffs_clrblock"); 287207141Sjeff#endif 288207141Sjeff break; 2891541Srgrimes } 2901541Srgrimes} 2911541Srgrimes 2921541Srgrimes/* 2931541Srgrimes * put a block into the map 2941541Srgrimes */ 2951541Srgrimesvoid 2961541Srgrimesffs_setblock(fs, cp, h) 2971541Srgrimes struct fs *fs; 2981541Srgrimes unsigned char *cp; 29998542Smckusick ufs1_daddr_t h; 3001541Srgrimes{ 3011541Srgrimes 3021541Srgrimes switch ((int)fs->fs_frag) { 3031541Srgrimes 3041541Srgrimes case 8: 3051541Srgrimes cp[h] = 0xff; 3061541Srgrimes return; 3071541Srgrimes case 4: 3081541Srgrimes cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 3091541Srgrimes return; 3101541Srgrimes case 2: 3111541Srgrimes cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 3121541Srgrimes return; 3131541Srgrimes case 1: 3141541Srgrimes cp[h >> 3] |= (0x01 << (h & 0x7)); 3151541Srgrimes return; 3161541Srgrimes default: 317207141Sjeff#ifdef _KERNEL 3181541Srgrimes panic("ffs_setblock"); 319207141Sjeff#endif 320207141Sjeff break; 3211541Srgrimes } 3221541Srgrimes} 323207141Sjeff 324207141Sjeff/* 325207141Sjeff * Update the cluster map because of an allocation or free. 326207141Sjeff * 327207141Sjeff * Cnt == 1 means free; cnt == -1 means allocating. 328207141Sjeff */ 329207141Sjeffvoid 330207141Sjeffffs_clusteracct(fs, cgp, blkno, cnt) 331207141Sjeff struct fs *fs; 332207141Sjeff struct cg *cgp; 333207141Sjeff ufs1_daddr_t blkno; 334207141Sjeff int cnt; 335207141Sjeff{ 336207141Sjeff int32_t *sump; 337207141Sjeff int32_t *lp; 338207141Sjeff u_char *freemapp, *mapp; 339207141Sjeff int i, start, end, forw, back, map, bit; 340207141Sjeff 341207141Sjeff if (fs->fs_contigsumsize <= 0) 342207141Sjeff return; 343207141Sjeff freemapp = cg_clustersfree(cgp); 344207141Sjeff sump = cg_clustersum(cgp); 345207141Sjeff /* 346207141Sjeff * Allocate or clear the actual block. 347207141Sjeff */ 348207141Sjeff if (cnt > 0) 349207141Sjeff setbit(freemapp, blkno); 350207141Sjeff else 351207141Sjeff clrbit(freemapp, blkno); 352207141Sjeff /* 353207141Sjeff * Find the size of the cluster going forward. 354207141Sjeff */ 355207141Sjeff start = blkno + 1; 356207141Sjeff end = start + fs->fs_contigsumsize; 357207141Sjeff if (end >= cgp->cg_nclusterblks) 358207141Sjeff end = cgp->cg_nclusterblks; 359207141Sjeff mapp = &freemapp[start / NBBY]; 360207141Sjeff map = *mapp++; 361207141Sjeff bit = 1 << (start % NBBY); 362207141Sjeff for (i = start; i < end; i++) { 363207141Sjeff if ((map & bit) == 0) 364207141Sjeff break; 365207141Sjeff if ((i & (NBBY - 1)) != (NBBY - 1)) { 366207141Sjeff bit <<= 1; 367207141Sjeff } else { 368207141Sjeff map = *mapp++; 369207141Sjeff bit = 1; 370207141Sjeff } 371207141Sjeff } 372207141Sjeff forw = i - start; 373207141Sjeff /* 374207141Sjeff * Find the size of the cluster going backward. 375207141Sjeff */ 376207141Sjeff start = blkno - 1; 377207141Sjeff end = start - fs->fs_contigsumsize; 378207141Sjeff if (end < 0) 379207141Sjeff end = -1; 380207141Sjeff mapp = &freemapp[start / NBBY]; 381207141Sjeff map = *mapp--; 382207141Sjeff bit = 1 << (start % NBBY); 383207141Sjeff for (i = start; i > end; i--) { 384207141Sjeff if ((map & bit) == 0) 385207141Sjeff break; 386207141Sjeff if ((i & (NBBY - 1)) != 0) { 387207141Sjeff bit >>= 1; 388207141Sjeff } else { 389207141Sjeff map = *mapp--; 390207141Sjeff bit = 1 << (NBBY - 1); 391207141Sjeff } 392207141Sjeff } 393207141Sjeff back = start - i; 394207141Sjeff /* 395207141Sjeff * Account for old cluster and the possibly new forward and 396207141Sjeff * back clusters. 397207141Sjeff */ 398207141Sjeff i = back + forw + 1; 399207141Sjeff if (i > fs->fs_contigsumsize) 400207141Sjeff i = fs->fs_contigsumsize; 401207141Sjeff sump[i] += cnt; 402207141Sjeff if (back > 0) 403207141Sjeff sump[back] -= cnt; 404207141Sjeff if (forw > 0) 405207141Sjeff sump[forw] -= cnt; 406207141Sjeff /* 407207141Sjeff * Update cluster summary information. 408207141Sjeff */ 409207141Sjeff lp = &sump[fs->fs_contigsumsize]; 410207141Sjeff for (i = fs->fs_contigsumsize; i > 0; i--) 411207141Sjeff if (*lp-- > 0) 412207141Sjeff break; 413207141Sjeff fs->fs_maxcluster[cgp->cg_cgx] = i; 414207141Sjeff} 415