1df8bae1dSRodney W. Grimes /* 2df8bae1dSRodney W. Grimes * Copyright (c) 1982, 1986, 1989, 1993 3df8bae1dSRodney W. Grimes * The Regents of the University of California. All rights reserved. 4df8bae1dSRodney W. Grimes * 5df8bae1dSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 6df8bae1dSRodney W. Grimes * modification, are permitted provided that the following conditions 7df8bae1dSRodney W. Grimes * are met: 8df8bae1dSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 9df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 10df8bae1dSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 11df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 12df8bae1dSRodney W. Grimes * documentation and/or other materials provided with the distribution. 13df8bae1dSRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 14df8bae1dSRodney W. Grimes * must display the following acknowledgement: 15df8bae1dSRodney W. Grimes * This product includes software developed by the University of 16df8bae1dSRodney W. Grimes * California, Berkeley and its contributors. 17df8bae1dSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 18df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 19df8bae1dSRodney W. Grimes * without specific prior written permission. 20df8bae1dSRodney W. Grimes * 21df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31df8bae1dSRodney W. Grimes * SUCH DAMAGE. 32df8bae1dSRodney W. Grimes * 33df8bae1dSRodney W. Grimes * @(#)ffs_subr.c 8.2 (Berkeley) 9/21/93 34df8bae1dSRodney W. Grimes */ 35df8bae1dSRodney W. Grimes 36df8bae1dSRodney W. Grimes #include <sys/param.h> 37df8bae1dSRodney W. Grimes #include <ufs/ffs/fs.h> 38df8bae1dSRodney W. Grimes 39df8bae1dSRodney W. Grimes #ifdef KERNEL 40df8bae1dSRodney W. Grimes #include <sys/systm.h> 41df8bae1dSRodney W. Grimes #include <sys/vnode.h> 42df8bae1dSRodney W. Grimes #include <ufs/ffs/ffs_extern.h> 43df8bae1dSRodney W. Grimes #include <sys/buf.h> 44df8bae1dSRodney W. Grimes #include <ufs/ufs/quota.h> 45df8bae1dSRodney W. Grimes #include <ufs/ufs/inode.h> 46df8bae1dSRodney W. Grimes 47df8bae1dSRodney W. Grimes /* 48df8bae1dSRodney W. Grimes * Return buffer with the contents of block "offset" from the beginning of 49df8bae1dSRodney W. Grimes * directory "ip". If "res" is non-zero, fill it in with a pointer to the 50df8bae1dSRodney W. Grimes * remaining space in the directory. 51df8bae1dSRodney W. Grimes */ 52df8bae1dSRodney W. Grimes int 53df8bae1dSRodney W. Grimes ffs_blkatoff(ap) 54df8bae1dSRodney W. Grimes struct vop_blkatoff_args /* { 55df8bae1dSRodney W. Grimes struct vnode *a_vp; 56df8bae1dSRodney W. Grimes off_t a_offset; 57df8bae1dSRodney W. Grimes char **a_res; 58df8bae1dSRodney W. Grimes struct buf **a_bpp; 59df8bae1dSRodney W. Grimes } */ *ap; 60df8bae1dSRodney W. Grimes { 61df8bae1dSRodney W. Grimes struct inode *ip; 62df8bae1dSRodney W. Grimes register struct fs *fs; 63df8bae1dSRodney W. Grimes struct buf *bp; 64df8bae1dSRodney W. Grimes daddr_t lbn; 65df8bae1dSRodney W. Grimes int bsize, error; 66df8bae1dSRodney W. Grimes 67df8bae1dSRodney W. Grimes ip = VTOI(ap->a_vp); 68df8bae1dSRodney W. Grimes fs = ip->i_fs; 69df8bae1dSRodney W. Grimes lbn = lblkno(fs, ap->a_offset); 70df8bae1dSRodney W. Grimes bsize = blksize(fs, ip, lbn); 71df8bae1dSRodney W. Grimes 72df8bae1dSRodney W. Grimes *ap->a_bpp = NULL; 73df8bae1dSRodney W. Grimes if (error = bread(ap->a_vp, lbn, bsize, NOCRED, &bp)) { 74df8bae1dSRodney W. Grimes brelse(bp); 75df8bae1dSRodney W. Grimes return (error); 76df8bae1dSRodney W. Grimes } 77df8bae1dSRodney W. Grimes if (ap->a_res) 78df8bae1dSRodney W. Grimes *ap->a_res = (char *)bp->b_data + blkoff(fs, ap->a_offset); 79df8bae1dSRodney W. Grimes *ap->a_bpp = bp; 80df8bae1dSRodney W. Grimes return (0); 81df8bae1dSRodney W. Grimes } 82df8bae1dSRodney W. Grimes #endif 83df8bae1dSRodney W. Grimes 84df8bae1dSRodney W. Grimes /* 85df8bae1dSRodney W. Grimes * Update the frsum fields to reflect addition or deletion 86df8bae1dSRodney W. Grimes * of some frags. 87df8bae1dSRodney W. Grimes */ 88df8bae1dSRodney W. Grimes void 89df8bae1dSRodney W. Grimes ffs_fragacct(fs, fragmap, fraglist, cnt) 90df8bae1dSRodney W. Grimes struct fs *fs; 91df8bae1dSRodney W. Grimes int fragmap; 92df8bae1dSRodney W. Grimes long fraglist[]; 93df8bae1dSRodney W. Grimes int cnt; 94df8bae1dSRodney W. Grimes { 95df8bae1dSRodney W. Grimes int inblk; 96df8bae1dSRodney W. Grimes register int field, subfield; 97df8bae1dSRodney W. Grimes register int siz, pos; 98df8bae1dSRodney W. Grimes 99df8bae1dSRodney W. Grimes inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; 100df8bae1dSRodney W. Grimes fragmap <<= 1; 101df8bae1dSRodney W. Grimes for (siz = 1; siz < fs->fs_frag; siz++) { 102df8bae1dSRodney W. Grimes if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) 103df8bae1dSRodney W. Grimes continue; 104df8bae1dSRodney W. Grimes field = around[siz]; 105df8bae1dSRodney W. Grimes subfield = inside[siz]; 106df8bae1dSRodney W. Grimes for (pos = siz; pos <= fs->fs_frag; pos++) { 107df8bae1dSRodney W. Grimes if ((fragmap & field) == subfield) { 108df8bae1dSRodney W. Grimes fraglist[siz] += cnt; 109df8bae1dSRodney W. Grimes pos += siz; 110df8bae1dSRodney W. Grimes field <<= siz; 111df8bae1dSRodney W. Grimes subfield <<= siz; 112df8bae1dSRodney W. Grimes } 113df8bae1dSRodney W. Grimes field <<= 1; 114df8bae1dSRodney W. Grimes subfield <<= 1; 115df8bae1dSRodney W. Grimes } 116df8bae1dSRodney W. Grimes } 117df8bae1dSRodney W. Grimes } 118df8bae1dSRodney W. Grimes 119df8bae1dSRodney W. Grimes #if defined(KERNEL) && defined(DIAGNOSTIC) 120df8bae1dSRodney W. Grimes void 121df8bae1dSRodney W. Grimes ffs_checkoverlap(bp, ip) 122df8bae1dSRodney W. Grimes struct buf *bp; 123df8bae1dSRodney W. Grimes struct inode *ip; 124df8bae1dSRodney W. Grimes { 125df8bae1dSRodney W. Grimes register struct buf *ebp, *ep; 126df8bae1dSRodney W. Grimes register daddr_t start, last; 127df8bae1dSRodney W. Grimes struct vnode *vp; 128df8bae1dSRodney W. Grimes 129df8bae1dSRodney W. Grimes ebp = &buf[nbuf]; 130df8bae1dSRodney W. Grimes start = bp->b_blkno; 131df8bae1dSRodney W. Grimes last = start + btodb(bp->b_bcount) - 1; 132df8bae1dSRodney W. Grimes for (ep = buf; ep < ebp; ep++) { 133df8bae1dSRodney W. Grimes if (ep == bp || (ep->b_flags & B_INVAL) || 134df8bae1dSRodney W. Grimes ep->b_vp == NULLVP) 135df8bae1dSRodney W. Grimes continue; 136df8bae1dSRodney W. Grimes if (VOP_BMAP(ep->b_vp, (daddr_t)0, &vp, (daddr_t)0, NULL)) 137df8bae1dSRodney W. Grimes continue; 138df8bae1dSRodney W. Grimes if (vp != ip->i_devvp) 139df8bae1dSRodney W. Grimes continue; 140df8bae1dSRodney W. Grimes /* look for overlap */ 141df8bae1dSRodney W. Grimes if (ep->b_bcount == 0 || ep->b_blkno > last || 142df8bae1dSRodney W. Grimes ep->b_blkno + btodb(ep->b_bcount) <= start) 143df8bae1dSRodney W. Grimes continue; 144df8bae1dSRodney W. Grimes vprint("Disk overlap", vp); 145df8bae1dSRodney W. Grimes (void)printf("\tstart %d, end %d overlap start %d, end %d\n", 146df8bae1dSRodney W. Grimes start, last, ep->b_blkno, 147df8bae1dSRodney W. Grimes ep->b_blkno + btodb(ep->b_bcount) - 1); 148df8bae1dSRodney W. Grimes panic("Disk buffer overlap"); 149df8bae1dSRodney W. Grimes } 150df8bae1dSRodney W. Grimes } 151df8bae1dSRodney W. Grimes #endif /* DIAGNOSTIC */ 152df8bae1dSRodney W. Grimes 153df8bae1dSRodney W. Grimes /* 154df8bae1dSRodney W. Grimes * block operations 155df8bae1dSRodney W. Grimes * 156df8bae1dSRodney W. Grimes * check if a block is available 157df8bae1dSRodney W. Grimes */ 158df8bae1dSRodney W. Grimes int 159df8bae1dSRodney W. Grimes ffs_isblock(fs, cp, h) 160df8bae1dSRodney W. Grimes struct fs *fs; 161df8bae1dSRodney W. Grimes unsigned char *cp; 162df8bae1dSRodney W. Grimes daddr_t h; 163df8bae1dSRodney W. Grimes { 164df8bae1dSRodney W. Grimes unsigned char mask; 165df8bae1dSRodney W. Grimes 166df8bae1dSRodney W. Grimes switch ((int)fs->fs_frag) { 167df8bae1dSRodney W. Grimes case 8: 168df8bae1dSRodney W. Grimes return (cp[h] == 0xff); 169df8bae1dSRodney W. Grimes case 4: 170df8bae1dSRodney W. Grimes mask = 0x0f << ((h & 0x1) << 2); 171df8bae1dSRodney W. Grimes return ((cp[h >> 1] & mask) == mask); 172df8bae1dSRodney W. Grimes case 2: 173df8bae1dSRodney W. Grimes mask = 0x03 << ((h & 0x3) << 1); 174df8bae1dSRodney W. Grimes return ((cp[h >> 2] & mask) == mask); 175df8bae1dSRodney W. Grimes case 1: 176df8bae1dSRodney W. Grimes mask = 0x01 << (h & 0x7); 177df8bae1dSRodney W. Grimes return ((cp[h >> 3] & mask) == mask); 178df8bae1dSRodney W. Grimes default: 179df8bae1dSRodney W. Grimes panic("ffs_isblock"); 180df8bae1dSRodney W. Grimes } 181df8bae1dSRodney W. Grimes } 182df8bae1dSRodney W. Grimes 183df8bae1dSRodney W. Grimes /* 184df8bae1dSRodney W. Grimes * take a block out of the map 185df8bae1dSRodney W. Grimes */ 186df8bae1dSRodney W. Grimes void 187df8bae1dSRodney W. Grimes ffs_clrblock(fs, cp, h) 188df8bae1dSRodney W. Grimes struct fs *fs; 189df8bae1dSRodney W. Grimes u_char *cp; 190df8bae1dSRodney W. Grimes daddr_t h; 191df8bae1dSRodney W. Grimes { 192df8bae1dSRodney W. Grimes 193df8bae1dSRodney W. Grimes switch ((int)fs->fs_frag) { 194df8bae1dSRodney W. Grimes case 8: 195df8bae1dSRodney W. Grimes cp[h] = 0; 196df8bae1dSRodney W. Grimes return; 197df8bae1dSRodney W. Grimes case 4: 198df8bae1dSRodney W. Grimes cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 199df8bae1dSRodney W. Grimes return; 200df8bae1dSRodney W. Grimes case 2: 201df8bae1dSRodney W. Grimes cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 202df8bae1dSRodney W. Grimes return; 203df8bae1dSRodney W. Grimes case 1: 204df8bae1dSRodney W. Grimes cp[h >> 3] &= ~(0x01 << (h & 0x7)); 205df8bae1dSRodney W. Grimes return; 206df8bae1dSRodney W. Grimes default: 207df8bae1dSRodney W. Grimes panic("ffs_clrblock"); 208df8bae1dSRodney W. Grimes } 209df8bae1dSRodney W. Grimes } 210df8bae1dSRodney W. Grimes 211df8bae1dSRodney W. Grimes /* 212df8bae1dSRodney W. Grimes * put a block into the map 213df8bae1dSRodney W. Grimes */ 214df8bae1dSRodney W. Grimes void 215df8bae1dSRodney W. Grimes ffs_setblock(fs, cp, h) 216df8bae1dSRodney W. Grimes struct fs *fs; 217df8bae1dSRodney W. Grimes unsigned char *cp; 218df8bae1dSRodney W. Grimes daddr_t h; 219df8bae1dSRodney W. Grimes { 220df8bae1dSRodney W. Grimes 221df8bae1dSRodney W. Grimes switch ((int)fs->fs_frag) { 222df8bae1dSRodney W. Grimes 223df8bae1dSRodney W. Grimes case 8: 224df8bae1dSRodney W. Grimes cp[h] = 0xff; 225df8bae1dSRodney W. Grimes return; 226df8bae1dSRodney W. Grimes case 4: 227df8bae1dSRodney W. Grimes cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 228df8bae1dSRodney W. Grimes return; 229df8bae1dSRodney W. Grimes case 2: 230df8bae1dSRodney W. Grimes cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 231df8bae1dSRodney W. Grimes return; 232df8bae1dSRodney W. Grimes case 1: 233df8bae1dSRodney W. Grimes cp[h >> 3] |= (0x01 << (h & 0x7)); 234df8bae1dSRodney W. Grimes return; 235df8bae1dSRodney W. Grimes default: 236df8bae1dSRodney W. Grimes panic("ffs_setblock"); 237df8bae1dSRodney W. Grimes } 238df8bae1dSRodney W. Grimes } 239