123402Smckusick /* 2*37737Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3*37737Smckusick * All rights reserved. 423402Smckusick * 5*37737Smckusick * Redistribution and use in source and binary forms are permitted 6*37737Smckusick * provided that the above copyright notice and this paragraph are 7*37737Smckusick * duplicated in all such forms and that any documentation, 8*37737Smckusick * advertising materials, and other materials related to such 9*37737Smckusick * distribution and use acknowledge that the software was developed 10*37737Smckusick * by the University of California, Berkeley. The name of the 11*37737Smckusick * University may not be used to endorse or promote products derived 12*37737Smckusick * from this software without specific prior written permission. 13*37737Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*37737Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*37737Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16*37737Smckusick * 17*37737Smckusick * @(#)ffs_subr.c 7.8 (Berkeley) 05/09/89 1823402Smckusick */ 198719Sroot 208719Sroot #ifdef KERNEL 2117101Sbloom #include "param.h" 2217101Sbloom #include "systm.h" 2317101Sbloom #include "buf.h" 24*37737Smckusick #include "time.h" 2517101Sbloom #include "kernel.h" 26*37737Smckusick #include "file.h" 27*37737Smckusick #include "mount.h" 28*37737Smckusick #include "vnode.h" 29*37737Smckusick #include "../ufs/inode.h" 30*37737Smckusick #include "../ufs/ufsmount.h" 31*37737Smckusick #include "../ufs/fs.h" 32*37737Smckusick #include "../ufs/quota.h" 338719Sroot #else 348719Sroot #include <sys/param.h> 359167Ssam #include <sys/systm.h> 36*37737Smckusick #include <sys/buf.h> 37*37737Smckusick #include <sys/time.h> 38*37737Smckusick #include <sys/file.h> 399167Ssam #include <sys/mount.h> 40*37737Smckusick #include <sys/vnode.h> 41*37737Smckusick #include <ufs/inode.h> 42*37737Smckusick #include <ufs/ufsmount.h> 43*37737Smckusick #include <ufs/fs.h> 44*37737Smckusick #include <ufs/quota.h> 458719Sroot #endif 468719Sroot 479167Ssam #ifdef KERNEL 489167Ssam /* 499167Ssam * Flush all the blocks associated with an inode. 5016861Smckusick * There are two strategies based on the size of the file; 5116861Smckusick * large files are those with more than (nbuf / 2) blocks. 5216861Smckusick * Large files 5316861Smckusick * Walk through the buffer pool and push any dirty pages 5416861Smckusick * associated with the device on which the file resides. 5516861Smckusick * Small files 5616861Smckusick * Look up each block in the file to see if it is in the 5716861Smckusick * buffer pool writing any that are found to disk. 5816861Smckusick * Note that we make a more stringent check of 5916861Smckusick * writing out any block in the buffer pool that may 6016861Smckusick * overlap the inode. This brings the inode up to 6116861Smckusick * date with recent mods to the cooked device. 629167Ssam */ 639167Ssam syncip(ip) 649167Ssam register struct inode *ip; 659167Ssam { 669167Ssam register struct fs *fs; 6716861Smckusick register struct buf *bp; 6816861Smckusick struct buf *lastbufp; 6926274Skarels long lbn, lastlbn; 70*37737Smckusick int s, error, allerror = 0; 719167Ssam daddr_t blkno; 729167Ssam 739167Ssam fs = ip->i_fs; 749167Ssam lastlbn = howmany(ip->i_size, fs->fs_bsize); 7516861Smckusick if (lastlbn < nbuf / 2) { 7616861Smckusick for (lbn = 0; lbn < lastlbn; lbn++) { 77*37737Smckusick error = bmap(ip, lbn, &blkno, (daddr_t *)0, (int *)0); 78*37737Smckusick if (error) 79*37737Smckusick allerror = error; 80*37737Smckusick if (error = blkflush(ip->i_devvp, blkno, 81*37737Smckusick blksize(fs, ip, lbn))) 82*37737Smckusick allerror = error; 8316861Smckusick } 8416861Smckusick } else { 8516861Smckusick lastbufp = &buf[nbuf]; 8616861Smckusick for (bp = buf; bp < lastbufp; bp++) { 8716861Smckusick if (bp->b_dev != ip->i_dev || 8816861Smckusick (bp->b_flags & B_DELWRI) == 0) 8916861Smckusick continue; 9026274Skarels s = splbio(); 9116861Smckusick if (bp->b_flags & B_BUSY) { 9216861Smckusick bp->b_flags |= B_WANTED; 9316861Smckusick sleep((caddr_t)bp, PRIBIO+1); 9416861Smckusick splx(s); 9516861Smckusick bp--; 9616861Smckusick continue; 9716861Smckusick } 9816861Smckusick splx(s); 9916861Smckusick notavail(bp); 100*37737Smckusick if (error = bwrite(bp)) 101*37737Smckusick allerror = error; 10216861Smckusick } 1039167Ssam } 104*37737Smckusick if (error = iupdat(ip, &time, &time, 1)) 105*37737Smckusick allerror = error; 106*37737Smckusick return (allerror); 1079167Ssam } 108*37737Smckusick #endif KERNEL 1099167Ssam 1108719Sroot extern int around[9]; 1118719Sroot extern int inside[9]; 1128719Sroot extern u_char *fragtbl[]; 1138719Sroot 1148719Sroot /* 1158719Sroot * Update the frsum fields to reflect addition or deletion 1168719Sroot * of some frags. 1178719Sroot */ 1188719Sroot fragacct(fs, fragmap, fraglist, cnt) 1198719Sroot struct fs *fs; 1208719Sroot int fragmap; 1218719Sroot long fraglist[]; 1228719Sroot int cnt; 1238719Sroot { 1248719Sroot int inblk; 1258719Sroot register int field, subfield; 1268719Sroot register int siz, pos; 1278719Sroot 1288719Sroot inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; 1298719Sroot fragmap <<= 1; 1308719Sroot for (siz = 1; siz < fs->fs_frag; siz++) { 1318719Sroot if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) 1328719Sroot continue; 1338719Sroot field = around[siz]; 1348719Sroot subfield = inside[siz]; 1358719Sroot for (pos = siz; pos <= fs->fs_frag; pos++) { 1368719Sroot if ((fragmap & field) == subfield) { 1378719Sroot fraglist[siz] += cnt; 1388719Sroot pos += siz; 1398719Sroot field <<= siz; 1408719Sroot subfield <<= siz; 1418719Sroot } 1428719Sroot field <<= 1; 1438719Sroot subfield <<= 1; 1448719Sroot } 1458719Sroot } 1468719Sroot } 1478719Sroot 1488719Sroot #ifdef KERNEL 1498719Sroot /* 1508719Sroot * Check that a specified block number is in range. 1518719Sroot */ 1528719Sroot badblock(fs, bn) 1538719Sroot register struct fs *fs; 1548719Sroot daddr_t bn; 1558719Sroot { 1568719Sroot 1578719Sroot if ((unsigned)bn >= fs->fs_size) { 1588719Sroot printf("bad block %d, ", bn); 1598719Sroot fserr(fs, "bad block"); 1608719Sroot return (1); 1618719Sroot } 1628719Sroot return (0); 1638719Sroot } 1648719Sroot #endif 1658719Sroot 1668719Sroot /* 1678719Sroot * block operations 1688719Sroot * 1698719Sroot * check if a block is available 1708719Sroot */ 1718719Sroot isblock(fs, cp, h) 1728719Sroot struct fs *fs; 1738719Sroot unsigned char *cp; 1748719Sroot daddr_t h; 1758719Sroot { 1768719Sroot unsigned char mask; 1778719Sroot 17826309Skarels switch ((int)fs->fs_frag) { 1798719Sroot case 8: 1808719Sroot return (cp[h] == 0xff); 1818719Sroot case 4: 1828719Sroot mask = 0x0f << ((h & 0x1) << 2); 1838719Sroot return ((cp[h >> 1] & mask) == mask); 1848719Sroot case 2: 1858719Sroot mask = 0x03 << ((h & 0x3) << 1); 1868719Sroot return ((cp[h >> 2] & mask) == mask); 1878719Sroot case 1: 1888719Sroot mask = 0x01 << (h & 0x7); 1898719Sroot return ((cp[h >> 3] & mask) == mask); 1908719Sroot default: 1918719Sroot panic("isblock"); 1928719Sroot return (NULL); 1938719Sroot } 1948719Sroot } 1958719Sroot 1968719Sroot /* 1978719Sroot * take a block out of the map 1988719Sroot */ 1998719Sroot clrblock(fs, cp, h) 2008719Sroot struct fs *fs; 2018770Sroot u_char *cp; 2028719Sroot daddr_t h; 2038719Sroot { 2048719Sroot 20526309Skarels switch ((int)fs->fs_frag) { 2068719Sroot case 8: 2078719Sroot cp[h] = 0; 2088719Sroot return; 2098719Sroot case 4: 2108719Sroot cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 2118719Sroot return; 2128719Sroot case 2: 2138719Sroot cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 2148719Sroot return; 2158719Sroot case 1: 2168719Sroot cp[h >> 3] &= ~(0x01 << (h & 0x7)); 2178719Sroot return; 2188719Sroot default: 2198719Sroot panic("clrblock"); 2208719Sroot } 2218719Sroot } 2228719Sroot 2238719Sroot /* 2248719Sroot * put a block into the map 2258719Sroot */ 2268719Sroot setblock(fs, cp, h) 2278719Sroot struct fs *fs; 2288719Sroot unsigned char *cp; 2298719Sroot daddr_t h; 2308719Sroot { 2318719Sroot 23226309Skarels switch ((int)fs->fs_frag) { 2338719Sroot 2348719Sroot case 8: 2358719Sroot cp[h] = 0xff; 2368719Sroot return; 2378719Sroot case 4: 2388719Sroot cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 2398719Sroot return; 2408719Sroot case 2: 2418719Sroot cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 2428719Sroot return; 2438719Sroot case 1: 2448719Sroot cp[h >> 3] |= (0x01 << (h & 0x7)); 2458719Sroot return; 2468719Sroot default: 2478719Sroot panic("setblock"); 2488719Sroot } 2498719Sroot } 2509167Ssam 2519167Ssam #ifdef KERNEL 2529167Ssam /* 2539167Ssam * Getfs maps a device number into a pointer to the incore super block. 2549167Ssam * 2559167Ssam * The algorithm is a linear search through the mount table. A 2569167Ssam * consistency check of the super block magic number is performed. 25734356Skarels * Filesystems still working on a mount are skipped. 2589167Ssam * 2599167Ssam * panic: no fs -- the device is not mounted. 2609167Ssam * this "cannot happen" 2619167Ssam */ 2629167Ssam struct fs * 2639167Ssam getfs(dev) 2649167Ssam dev_t dev; 2659167Ssam { 266*37737Smckusick register struct ufsmount *mp; 2679167Ssam register struct fs *fs; 2689167Ssam 269*37737Smckusick for (mp = &mounttab[0]; mp < &mounttab[NMOUNT]; mp++) { 270*37737Smckusick if (mp->um_fs == NULL || mp->um_dev != dev || 271*37737Smckusick mp->um_fs == (struct fs *)1) /* XXX */ 2729167Ssam continue; 273*37737Smckusick fs = mp->um_fs; 2749167Ssam if (fs->fs_magic != FS_MAGIC) { 2759167Ssam printf("dev = 0x%x, fs = %s\n", dev, fs->fs_fsmnt); 2769167Ssam panic("getfs: bad magic"); 2779167Ssam } 2789167Ssam return (fs); 2799167Ssam } 2809167Ssam printf("dev = 0x%x\n", dev); 2819167Ssam panic("getfs: no fs"); 2829167Ssam return (NULL); 2839167Ssam } 2849167Ssam 2859167Ssam /* 2869167Ssam * Getfsx returns the index in the file system 2879167Ssam * table of the specified device. The swap device 2889167Ssam * is also assigned a pseudo-index. The index may 2899167Ssam * be used as a compressed indication of the location 2909167Ssam * of a block, recording 2919167Ssam * <getfsx(dev),blkno> 2929167Ssam * rather than 2939167Ssam * <dev, blkno> 2949167Ssam * provided the information need remain valid only 2959167Ssam * as long as the file system is mounted. 2969167Ssam */ 2979167Ssam getfsx(dev) 2989167Ssam dev_t dev; 2999167Ssam { 300*37737Smckusick register struct ufsmount *mp; 3019167Ssam 3029167Ssam if (dev == swapdev) 3039167Ssam return (MSWAPX); 304*37737Smckusick for(mp = &mounttab[0]; mp < &mounttab[NMOUNT]; mp++) 305*37737Smckusick if (mp->um_dev == dev) 306*37737Smckusick return (mp - &mounttab[0]); 3079167Ssam return (-1); 3089167Ssam } 3099167Ssam #endif 31021090Smckusick 31137574Sbostic #if (!defined(vax) && !defined(tahoe)) || defined(VAX630) || defined(VAX650) 31221090Smckusick /* 31329947Skarels * C definitions of special instructions. 31429947Skarels * Normally expanded with inline. 31521090Smckusick */ 31621090Smckusick scanc(size, cp, table, mask) 31721090Smckusick u_int size; 31821090Smckusick register u_char *cp, table[]; 31921090Smckusick register u_char mask; 32021090Smckusick { 32121090Smckusick register u_char *end = &cp[size]; 32221090Smckusick 32321090Smckusick while (cp < end && (table[*cp] & mask) == 0) 32421090Smckusick cp++; 32521090Smckusick return (end - cp); 32621090Smckusick } 32727476Skridle #endif 32827476Skridle 32929947Skarels #if !defined(vax) && !defined(tahoe) 33021090Smckusick skpc(mask, size, cp) 33121090Smckusick register u_char mask; 33221090Smckusick u_int size; 33321090Smckusick register u_char *cp; 33421090Smckusick { 33521090Smckusick register u_char *end = &cp[size]; 33621090Smckusick 33721090Smckusick while (cp < end && *cp == mask) 33821090Smckusick cp++; 33921090Smckusick return (end - cp); 34021090Smckusick } 34121090Smckusick 34221090Smckusick locc(mask, size, cp) 34321090Smckusick register u_char mask; 34421090Smckusick u_int size; 34521090Smckusick register u_char *cp; 34621090Smckusick { 34721090Smckusick register u_char *end = &cp[size]; 34821090Smckusick 34921090Smckusick while (cp < end && *cp != mask) 35021090Smckusick cp++; 35121090Smckusick return (end - cp); 35221090Smckusick } 35329947Skarels #endif 354