1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)ffs_subr.c 7.19 (Berkeley) 05/14/92 8 */ 9 10 #include <sys/param.h> 11 #include <sys/vnode.h> 12 #include <ufs/ffs/fs.h> 13 #include <ufs/ffs/ffs_extern.h> 14 15 #ifdef KERNEL 16 #include <sys/buf.h> 17 #include <ufs/ufs/quota.h> 18 #include <ufs/ufs/inode.h> 19 20 /* 21 * Return buffer with the contents of block "offset" from the beginning of 22 * directory "ip". If "res" is non-zero, fill it in with a pointer to the 23 * remaining space in the directory. 24 */ 25 int 26 ffs_blkatoff (ap) 27 struct vop_blkatoff_args *ap; 28 #define vp (ap->a_vp) 29 #define offset (ap->a_offset) 30 #define res (ap->a_res) 31 #define bpp (ap->a_bpp) 32 { 33 struct inode *ip; 34 register struct fs *fs; 35 struct buf *bp; 36 daddr_t lbn; 37 int bsize, error; 38 39 ip = VTOI(vp); 40 fs = ip->i_fs; 41 lbn = lblkno(fs, offset); 42 bsize = blksize(fs, ip, lbn); 43 44 *bpp = NULL; 45 if (error = bread(vp, lbn, bsize, NOCRED, &bp)) { 46 brelse(bp); 47 return (error); 48 } 49 if (res) 50 *res = bp->b_un.b_addr + blkoff(fs, offset); 51 *bpp = bp; 52 return (0); 53 } 54 #undef vp 55 #undef offset 56 #undef res 57 #undef bpp 58 #endif 59 60 /* 61 * Update the frsum fields to reflect addition or deletion 62 * of some frags. 63 */ 64 void 65 ffs_fragacct(fs, fragmap, fraglist, cnt) 66 struct fs *fs; 67 int fragmap; 68 long fraglist[]; 69 int cnt; 70 { 71 int inblk; 72 register int field, subfield; 73 register int siz, pos; 74 75 inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; 76 fragmap <<= 1; 77 for (siz = 1; siz < fs->fs_frag; siz++) { 78 if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) 79 continue; 80 field = around[siz]; 81 subfield = inside[siz]; 82 for (pos = siz; pos <= fs->fs_frag; pos++) { 83 if ((fragmap & field) == subfield) { 84 fraglist[siz] += cnt; 85 pos += siz; 86 field <<= siz; 87 subfield <<= siz; 88 } 89 field <<= 1; 90 subfield <<= 1; 91 } 92 } 93 } 94 95 #if defined(KERNEL) && defined(DIAGNOSTIC) 96 void 97 ffs_checkoverlap(bp, ip) 98 struct buf *bp; 99 struct inode *ip; 100 { 101 USES_VOP_BMAP; 102 register struct buf *ebp, *ep; 103 register daddr_t start, last; 104 struct vnode *vp; 105 106 ebp = &buf[nbuf]; 107 start = bp->b_blkno; 108 last = start + btodb(bp->b_bcount) - 1; 109 for (ep = buf; ep < ebp; ep++) { 110 if (ep == bp || (ep->b_flags & B_INVAL) || 111 ep->b_vp == NULLVP) 112 continue; 113 if (VOP_BMAP(ep->b_vp, (daddr_t)0, &vp, (daddr_t)0)) 114 continue; 115 if (vp != ip->i_devvp) 116 continue; 117 /* look for overlap */ 118 if (ep->b_bcount == 0 || ep->b_blkno > last || 119 ep->b_blkno + btodb(ep->b_bcount) <= start) 120 continue; 121 vprint("Disk overlap", vp); 122 (void)printf("\tstart %d, end %d overlap start %d, end %d\n", 123 start, last, ep->b_blkno, 124 ep->b_blkno + btodb(ep->b_bcount) - 1); 125 panic("Disk buffer overlap"); 126 } 127 } 128 #endif /* DIAGNOSTIC */ 129 130 /* 131 * block operations 132 * 133 * check if a block is available 134 */ 135 int 136 ffs_isblock(fs, cp, h) 137 struct fs *fs; 138 unsigned char *cp; 139 daddr_t h; 140 { 141 unsigned char mask; 142 143 switch ((int)fs->fs_frag) { 144 case 8: 145 return (cp[h] == 0xff); 146 case 4: 147 mask = 0x0f << ((h & 0x1) << 2); 148 return ((cp[h >> 1] & mask) == mask); 149 case 2: 150 mask = 0x03 << ((h & 0x3) << 1); 151 return ((cp[h >> 2] & mask) == mask); 152 case 1: 153 mask = 0x01 << (h & 0x7); 154 return ((cp[h >> 3] & mask) == mask); 155 default: 156 panic("ffs_isblock"); 157 } 158 } 159 160 /* 161 * take a block out of the map 162 */ 163 void 164 ffs_clrblock(fs, cp, h) 165 struct fs *fs; 166 u_char *cp; 167 daddr_t h; 168 { 169 170 switch ((int)fs->fs_frag) { 171 case 8: 172 cp[h] = 0; 173 return; 174 case 4: 175 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 176 return; 177 case 2: 178 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 179 return; 180 case 1: 181 cp[h >> 3] &= ~(0x01 << (h & 0x7)); 182 return; 183 default: 184 panic("ffs_clrblock"); 185 } 186 } 187 188 /* 189 * put a block into the map 190 */ 191 void 192 ffs_setblock(fs, cp, h) 193 struct fs *fs; 194 unsigned char *cp; 195 daddr_t h; 196 { 197 198 switch ((int)fs->fs_frag) { 199 200 case 8: 201 cp[h] = 0xff; 202 return; 203 case 4: 204 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 205 return; 206 case 2: 207 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 208 return; 209 case 1: 210 cp[h >> 3] |= (0x01 << (h & 0x7)); 211 return; 212 default: 213 panic("ffs_setblock"); 214 } 215 } 216 217 #if (!defined(vax) && !defined(tahoe) && !defined(hp300)) \ 218 || defined(VAX630) || defined(VAX650) 219 /* 220 * C definitions of special instructions. 221 * Normally expanded with inline. 222 */ 223 int 224 scanc(size, cp, table, mask) 225 u_int size; 226 register u_char *cp, table[]; 227 register u_char mask; 228 { 229 register u_char *end = &cp[size]; 230 231 while (cp < end && (table[*cp] & mask) == 0) 232 cp++; 233 return (end - cp); 234 } 235 #endif 236 237 #if !defined(vax) && !defined(tahoe) && !defined(hp300) 238 int 239 skpc(mask, size, cp) 240 register u_char mask; 241 u_int size; 242 register u_char *cp; 243 { 244 register u_char *end = &cp[size]; 245 246 while (cp < end && *cp == mask) 247 cp++; 248 return (end - cp); 249 } 250 251 int 252 locc(mask, size, cp) 253 register u_char mask; 254 u_int size; 255 register u_char *cp; 256 { 257 register u_char *end = &cp[size]; 258 259 while (cp < end && *cp != mask) 260 cp++; 261 return (end - cp); 262 } 263 #endif 264