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