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