1 /* 2 * Copyright (c) 1982, 1986, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)ffs_subr.c 8.5 (Berkeley) 3/21/95 34 */ 35 36 #include <sys/cdefs.h> 37 __FBSDID("$FreeBSD$"); 38 39 #include <sys/param.h> 40 41 #ifndef _KERNEL 42 #include <ufs/ufs/dinode.h> 43 #include <ufs/ffs/fs.h> 44 #include "fsck.h" 45 #else 46 #include "opt_ddb.h" 47 48 #include <sys/systm.h> 49 #include <sys/lock.h> 50 #include <sys/malloc.h> 51 #include <sys/mount.h> 52 #include <sys/vnode.h> 53 #include <sys/bio.h> 54 #include <sys/buf.h> 55 #include <sys/ucred.h> 56 57 #include <ufs/ufs/quota.h> 58 #include <ufs/ufs/inode.h> 59 #include <ufs/ufs/extattr.h> 60 #include <ufs/ufs/ufsmount.h> 61 #include <ufs/ufs/ufs_extern.h> 62 #include <ufs/ffs/ffs_extern.h> 63 #include <ufs/ffs/fs.h> 64 65 #ifdef DDB 66 void ffs_checkoverlap(struct buf *, struct inode *); 67 #endif 68 69 /* 70 * Return buffer with the contents of block "offset" from the beginning of 71 * directory "ip". If "res" is non-zero, fill it in with a pointer to the 72 * remaining space in the directory. 73 */ 74 int 75 ffs_blkatoff(vp, offset, res, bpp) 76 struct vnode *vp; 77 off_t offset; 78 char **res; 79 struct buf **bpp; 80 { 81 struct inode *ip; 82 struct fs *fs; 83 struct buf *bp; 84 ufs_lbn_t lbn; 85 int bsize, error; 86 87 ip = VTOI(vp); 88 fs = ip->i_fs; 89 lbn = lblkno(fs, offset); 90 bsize = blksize(fs, ip, lbn); 91 92 *bpp = NULL; 93 error = bread(vp, lbn, bsize, NOCRED, &bp); 94 if (error) { 95 brelse(bp); 96 return (error); 97 } 98 if (res) 99 *res = (char *)bp->b_data + blkoff(fs, offset); 100 *bpp = bp; 101 return (0); 102 } 103 104 /* 105 * Load up the contents of an inode and copy the appropriate pieces 106 * to the incore copy. 107 */ 108 void 109 ffs_load_inode(bp, ip, fs, ino) 110 struct buf *bp; 111 struct inode *ip; 112 struct fs *fs; 113 ino_t ino; 114 { 115 116 if (ip->i_ump->um_fstype == UFS1) { 117 *ip->i_din1 = 118 *((struct ufs1_dinode *)bp->b_data + ino_to_fsbo(fs, ino)); 119 ip->i_mode = ip->i_din1->di_mode; 120 ip->i_nlink = ip->i_din1->di_nlink; 121 ip->i_size = ip->i_din1->di_size; 122 ip->i_flags = ip->i_din1->di_flags; 123 ip->i_gen = ip->i_din1->di_gen; 124 ip->i_uid = ip->i_din1->di_uid; 125 ip->i_gid = ip->i_din1->di_gid; 126 } else { 127 *ip->i_din2 = 128 *((struct ufs2_dinode *)bp->b_data + ino_to_fsbo(fs, ino)); 129 ip->i_mode = ip->i_din2->di_mode; 130 ip->i_nlink = ip->i_din2->di_nlink; 131 ip->i_size = ip->i_din2->di_size; 132 ip->i_flags = ip->i_din2->di_flags; 133 ip->i_gen = ip->i_din2->di_gen; 134 ip->i_uid = ip->i_din2->di_uid; 135 ip->i_gid = ip->i_din2->di_gid; 136 } 137 } 138 #endif /* KERNEL */ 139 140 /* 141 * Update the frsum fields to reflect addition or deletion 142 * of some frags. 143 */ 144 void 145 ffs_fragacct(fs, fragmap, fraglist, cnt) 146 struct fs *fs; 147 int fragmap; 148 int32_t fraglist[]; 149 int cnt; 150 { 151 int inblk; 152 int field, subfield; 153 int siz, pos; 154 155 inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; 156 fragmap <<= 1; 157 for (siz = 1; siz < fs->fs_frag; siz++) { 158 if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) 159 continue; 160 field = around[siz]; 161 subfield = inside[siz]; 162 for (pos = siz; pos <= fs->fs_frag; pos++) { 163 if ((fragmap & field) == subfield) { 164 fraglist[siz] += cnt; 165 pos += siz; 166 field <<= siz; 167 subfield <<= siz; 168 } 169 field <<= 1; 170 subfield <<= 1; 171 } 172 } 173 } 174 175 #ifdef DDB 176 void 177 ffs_checkoverlap(bp, ip) 178 struct buf *bp; 179 struct inode *ip; 180 { 181 struct buf *ebp, *ep; 182 ufs2_daddr_t start, last; 183 struct vnode *vp; 184 185 ebp = &buf[nbuf]; 186 start = bp->b_blkno; 187 last = start + btodb(bp->b_bcount) - 1; 188 for (ep = buf; ep < ebp; ep++) { 189 if (ep == bp || (ep->b_flags & B_INVAL) || 190 ep->b_vp == NULLVP) 191 continue; 192 vp = ip->i_devvp; 193 /* look for overlap */ 194 if (ep->b_bcount == 0 || ep->b_blkno > last || 195 ep->b_blkno + btodb(ep->b_bcount) <= start) 196 continue; 197 vprint("Disk overlap", vp); 198 printf("\tstart %jd, end %jd overlap start %jd, end %jd\n", 199 (intmax_t)start, (intmax_t)last, (intmax_t)ep->b_blkno, 200 (intmax_t)(ep->b_blkno + btodb(ep->b_bcount) - 1)); 201 panic("ffs_checkoverlap: Disk buffer overlap"); 202 } 203 } 204 #endif /* DDB */ 205 206 /* 207 * block operations 208 * 209 * check if a block is available 210 */ 211 int 212 ffs_isblock(fs, cp, h) 213 struct fs *fs; 214 unsigned char *cp; 215 ufs1_daddr_t h; 216 { 217 unsigned char mask; 218 219 switch ((int)fs->fs_frag) { 220 case 8: 221 return (cp[h] == 0xff); 222 case 4: 223 mask = 0x0f << ((h & 0x1) << 2); 224 return ((cp[h >> 1] & mask) == mask); 225 case 2: 226 mask = 0x03 << ((h & 0x3) << 1); 227 return ((cp[h >> 2] & mask) == mask); 228 case 1: 229 mask = 0x01 << (h & 0x7); 230 return ((cp[h >> 3] & mask) == mask); 231 default: 232 panic("ffs_isblock"); 233 } 234 return (0); 235 } 236 237 /* 238 * take a block out of the map 239 */ 240 void 241 ffs_clrblock(fs, cp, h) 242 struct fs *fs; 243 u_char *cp; 244 ufs1_daddr_t h; 245 { 246 247 switch ((int)fs->fs_frag) { 248 case 8: 249 cp[h] = 0; 250 return; 251 case 4: 252 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 253 return; 254 case 2: 255 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 256 return; 257 case 1: 258 cp[h >> 3] &= ~(0x01 << (h & 0x7)); 259 return; 260 default: 261 panic("ffs_clrblock"); 262 } 263 } 264 265 /* 266 * put a block into the map 267 */ 268 void 269 ffs_setblock(fs, cp, h) 270 struct fs *fs; 271 unsigned char *cp; 272 ufs1_daddr_t h; 273 { 274 275 switch ((int)fs->fs_frag) { 276 277 case 8: 278 cp[h] = 0xff; 279 return; 280 case 4: 281 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 282 return; 283 case 2: 284 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 285 return; 286 case 1: 287 cp[h >> 3] |= (0x01 << (h & 0x7)); 288 return; 289 default: 290 panic("ffs_setblock"); 291 } 292 } 293