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