1 /* 2 * Copyright (c) 1982, 1986, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)ffs_subr.c 8.5 (Berkeley) 03/21/95 8 */ 9 10 #include <sys/param.h> 11 #ifndef KERNEL 12 #include <ufs/ufs/dinode.h> 13 #include <ufs/ffs/fs.h> 14 #else 15 16 #include <sys/systm.h> 17 #include <sys/vnode.h> 18 #include <sys/buf.h> 19 #include <ufs/ufs/quota.h> 20 #include <ufs/ufs/inode.h> 21 #include <ufs/ffs/fs.h> 22 #include <ufs/ffs/ffs_extern.h> 23 24 /* 25 * Return buffer with the contents of block "offset" from the beginning of 26 * directory "ip". If "res" is non-zero, fill it in with a pointer to the 27 * remaining space in the directory. 28 */ 29 int 30 ffs_blkatoff(ap) 31 struct vop_blkatoff_args /* { 32 struct vnode *a_vp; 33 off_t a_offset; 34 char **a_res; 35 struct buf **a_bpp; 36 } */ *ap; 37 { 38 struct inode *ip; 39 register struct fs *fs; 40 struct buf *bp; 41 ufs_daddr_t lbn; 42 int bsize, error; 43 44 ip = VTOI(ap->a_vp); 45 fs = ip->i_fs; 46 lbn = lblkno(fs, ap->a_offset); 47 bsize = blksize(fs, ip, lbn); 48 49 *ap->a_bpp = NULL; 50 if (error = bread(ap->a_vp, lbn, bsize, NOCRED, &bp)) { 51 brelse(bp); 52 return (error); 53 } 54 if (ap->a_res) 55 *ap->a_res = (char *)bp->b_data + blkoff(fs, ap->a_offset); 56 *ap->a_bpp = bp; 57 return (0); 58 } 59 #endif 60 61 /* 62 * Update the frsum fields to reflect addition or deletion 63 * of some frags. 64 */ 65 void 66 ffs_fragacct(fs, fragmap, fraglist, cnt) 67 struct fs *fs; 68 int fragmap; 69 int32_t fraglist[]; 70 int cnt; 71 { 72 int inblk; 73 register int field, subfield; 74 register int siz, pos; 75 76 inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; 77 fragmap <<= 1; 78 for (siz = 1; siz < fs->fs_frag; siz++) { 79 if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) 80 continue; 81 field = around[siz]; 82 subfield = inside[siz]; 83 for (pos = siz; pos <= fs->fs_frag; pos++) { 84 if ((fragmap & field) == subfield) { 85 fraglist[siz] += cnt; 86 pos += siz; 87 field <<= siz; 88 subfield <<= siz; 89 } 90 field <<= 1; 91 subfield <<= 1; 92 } 93 } 94 } 95 96 #if defined(KERNEL) && defined(DIAGNOSTIC) 97 void 98 ffs_checkoverlap(bp, ip) 99 struct buf *bp; 100 struct inode *ip; 101 { 102 register struct buf *ebp, *ep; 103 register ufs_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, (ufs_daddr_t)0, &vp, (ufs_daddr_t)0, 114 NULL)) 115 continue; 116 if (vp != ip->i_devvp) 117 continue; 118 /* look for overlap */ 119 if (ep->b_bcount == 0 || ep->b_blkno > last || 120 ep->b_blkno + btodb(ep->b_bcount) <= start) 121 continue; 122 vprint("Disk overlap", vp); 123 (void)printf("\tstart %d, end %d overlap start %d, end %d\n", 124 start, last, ep->b_blkno, 125 ep->b_blkno + btodb(ep->b_bcount) - 1); 126 panic("Disk buffer overlap"); 127 } 128 } 129 #endif /* DIAGNOSTIC */ 130 131 /* 132 * block operations 133 * 134 * check if a block is available 135 */ 136 int 137 ffs_isblock(fs, cp, h) 138 struct fs *fs; 139 unsigned char *cp; 140 ufs_daddr_t h; 141 { 142 unsigned char mask; 143 144 switch ((int)fs->fs_frag) { 145 case 8: 146 return (cp[h] == 0xff); 147 case 4: 148 mask = 0x0f << ((h & 0x1) << 2); 149 return ((cp[h >> 1] & mask) == mask); 150 case 2: 151 mask = 0x03 << ((h & 0x3) << 1); 152 return ((cp[h >> 2] & mask) == mask); 153 case 1: 154 mask = 0x01 << (h & 0x7); 155 return ((cp[h >> 3] & mask) == mask); 156 default: 157 panic("ffs_isblock"); 158 } 159 } 160 161 /* 162 * take a block out of the map 163 */ 164 void 165 ffs_clrblock(fs, cp, h) 166 struct fs *fs; 167 u_char *cp; 168 ufs_daddr_t h; 169 { 170 171 switch ((int)fs->fs_frag) { 172 case 8: 173 cp[h] = 0; 174 return; 175 case 4: 176 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 177 return; 178 case 2: 179 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 180 return; 181 case 1: 182 cp[h >> 3] &= ~(0x01 << (h & 0x7)); 183 return; 184 default: 185 panic("ffs_clrblock"); 186 } 187 } 188 189 /* 190 * put a block into the map 191 */ 192 void 193 ffs_setblock(fs, cp, h) 194 struct fs *fs; 195 unsigned char *cp; 196 ufs_daddr_t h; 197 { 198 199 switch ((int)fs->fs_frag) { 200 201 case 8: 202 cp[h] = 0xff; 203 return; 204 case 4: 205 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 206 return; 207 case 2: 208 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 209 return; 210 case 1: 211 cp[h >> 3] |= (0x01 << (h & 0x7)); 212 return; 213 default: 214 panic("ffs_setblock"); 215 } 216 } 217