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