ffs_subr.c revision 185222
1185222Ssam/* $NetBSD: ffs_subr.c,v 1.32 2003/12/30 12:33:24 pk Exp $ */ 2185222Ssam 3185222Ssam/* 4185222Ssam * Copyright (c) 1982, 1986, 1989, 1993 5185222Ssam * The Regents of the University of California. All rights reserved. 6185222Ssam * 7185222Ssam * Redistribution and use in source and binary forms, with or without 8185222Ssam * modification, are permitted provided that the following conditions 9185222Ssam * are met: 10185222Ssam * 1. Redistributions of source code must retain the above copyright 11185222Ssam * notice, this list of conditions and the following disclaimer. 12185222Ssam * 2. Redistributions in binary form must reproduce the above copyright 13185222Ssam * notice, this list of conditions and the following disclaimer in the 14185222Ssam * documentation and/or other materials provided with the distribution. 15185222Ssam * 3. Neither the name of the University nor the names of its contributors 16185222Ssam * may be used to endorse or promote products derived from this software 17185222Ssam * without specific prior written permission. 18185222Ssam * 19185222Ssam * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20185222Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21185222Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22185222Ssam * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23185222Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24185222Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25185222Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26185222Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27185222Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28185222Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29185222Ssam * SUCH DAMAGE. 30185222Ssam * 31185222Ssam * @(#)ffs_subr.c 8.5 (Berkeley) 3/21/95 32185222Ssam */ 33185222Ssam 34185222Ssam#if HAVE_NBTOOL_CONFIG_H 35185222Ssam#include "nbtool_config.h" 36185222Ssam#endif 37185222Ssam 38185222Ssam#include <sys/cdefs.h> 39185222Ssam__KERNEL_RCSID(0, "$NetBSD: ffs_subr.c,v 1.32 2003/12/30 12:33:24 pk Exp $"); 40185222Ssam 41185222Ssam#include <sys/param.h> 42185222Ssam 43185222Ssam/* in ffs_tables.c */ 44185222Ssamextern const int inside[], around[]; 45185222Ssamextern const u_char * const fragtbl[]; 46185222Ssam 47185222Ssam#ifndef _KERNEL 48185222Ssam#include <ufs/ufs/dinode.h> 49185222Ssam#include <ufs/ffs/fs.h> 50185222Ssam#include <ufs/ffs/ffs_extern.h> 51185222Ssam#include <ufs/ufs/ufs_bswap.h> 52185222Ssamvoid panic __P((const char *, ...)) 53185222Ssam __attribute__((__noreturn__,__format__(__printf__,1,2))); 54185222Ssam 55185222Ssam#else /* _KERNEL */ 56185222Ssam#include <sys/systm.h> 57185222Ssam#include <sys/vnode.h> 58185222Ssam#include <sys/mount.h> 59185222Ssam#include <sys/buf.h> 60185222Ssam#include <sys/inttypes.h> 61185222Ssam#include <sys/pool.h> 62185222Ssam#include <ufs/ufs/inode.h> 63185222Ssam#include <ufs/ufs/ufsmount.h> 64185222Ssam#include <ufs/ufs/ufs_extern.h> 65185222Ssam#include <ufs/ffs/fs.h> 66185222Ssam#include <ufs/ffs/ffs_extern.h> 67185222Ssam#include <ufs/ufs/ufs_bswap.h> 68185222Ssam 69185222Ssam/* 70185222Ssam * Return buffer with the contents of block "offset" from the beginning of 71185222Ssam * directory "ip". If "res" is non-zero, fill it in with a pointer to the 72185222Ssam * remaining space in the directory. 73185222Ssam */ 74185222Ssamint 75185222Ssamffs_blkatoff(v) 76185222Ssam void *v; 77185222Ssam{ 78185222Ssam struct vop_blkatoff_args /* { 79185222Ssam struct vnode *a_vp; 80185222Ssam off_t a_offset; 81185222Ssam char **a_res; 82185222Ssam struct buf **a_bpp; 83185222Ssam } */ *ap = v; 84185222Ssam struct inode *ip; 85185222Ssam struct fs *fs; 86185222Ssam struct buf *bp; 87185222Ssam daddr_t lbn; 88185222Ssam int bsize, error; 89185222Ssam 90185222Ssam ip = VTOI(ap->a_vp); 91185222Ssam fs = ip->i_fs; 92185222Ssam lbn = lblkno(fs, ap->a_offset); 93185222Ssam bsize = blksize(fs, ip, lbn); 94185222Ssam 95185222Ssam *ap->a_bpp = NULL; 96185222Ssam if ((error = bread(ap->a_vp, lbn, bsize, NOCRED, &bp)) != 0) { 97185222Ssam brelse(bp); 98185222Ssam return (error); 99185222Ssam } 100185222Ssam if (ap->a_res) 101185222Ssam *ap->a_res = (char *)bp->b_data + blkoff(fs, ap->a_offset); 102185222Ssam *ap->a_bpp = bp; 103185222Ssam return (0); 104185222Ssam} 105185222Ssam 106185222Ssam 107185222Ssam/* 108185222Ssam * Load up the contents of an inode and copy the appropriate pieces 109185222Ssam * to the incore copy. 110185222Ssam */ 111185222Ssamvoid 112185222Ssamffs_load_inode(bp, ip, fs, ino) 113185222Ssam struct buf *bp; 114185222Ssam struct inode *ip; 115185222Ssam struct fs *fs; 116185222Ssam ino_t ino; 117185222Ssam{ 118185222Ssam struct ufs1_dinode *dp1; 119185222Ssam struct ufs2_dinode *dp2; 120185222Ssam 121185222Ssam if (ip->i_ump->um_fstype == UFS1) { 122185222Ssam dp1 = (struct ufs1_dinode *)bp->b_data + ino_to_fsbo(fs, ino); 123185222Ssam#ifdef FFS_EI 124185222Ssam if (UFS_FSNEEDSWAP(fs)) 125185222Ssam ffs_dinode1_swap(dp1, ip->i_din.ffs1_din); 126185222Ssam else 127185222Ssam#endif 128185222Ssam *ip->i_din.ffs1_din = *dp1; 129185222Ssam 130185222Ssam ip->i_mode = ip->i_ffs1_mode; 131185222Ssam ip->i_nlink = ip->i_ffs1_nlink; 132185222Ssam ip->i_size = ip->i_ffs1_size; 133185222Ssam ip->i_flags = ip->i_ffs1_flags; 134185222Ssam ip->i_gen = ip->i_ffs1_gen; 135185222Ssam ip->i_uid = ip->i_ffs1_uid; 136185222Ssam ip->i_gid = ip->i_ffs1_gid; 137185222Ssam } else { 138185222Ssam dp2 = (struct ufs2_dinode *)bp->b_data + ino_to_fsbo(fs, ino); 139185222Ssam#ifdef FFS_EI 140185222Ssam if (UFS_FSNEEDSWAP(fs)) 141185222Ssam ffs_dinode2_swap(dp2, ip->i_din.ffs2_din); 142185222Ssam else 143185222Ssam#endif 144185222Ssam *ip->i_din.ffs2_din = *dp2; 145185222Ssam 146185222Ssam ip->i_mode = ip->i_ffs2_mode; 147185222Ssam ip->i_nlink = ip->i_ffs2_nlink; 148185222Ssam ip->i_size = ip->i_ffs2_size; 149185222Ssam ip->i_flags = ip->i_ffs2_flags; 150185222Ssam ip->i_gen = ip->i_ffs2_gen; 151185222Ssam ip->i_uid = ip->i_ffs2_uid; 152185222Ssam ip->i_gid = ip->i_ffs2_gid; 153185222Ssam } 154185222Ssam} 155185222Ssam 156185222Ssam#endif /* _KERNEL */ 157185222Ssam 158185222Ssam/* 159185222Ssam * Update the frsum fields to reflect addition or deletion 160185222Ssam * of some frags. 161185222Ssam */ 162185222Ssamvoid 163185222Ssamffs_fragacct(fs, fragmap, fraglist, cnt, needswap) 164185222Ssam struct fs *fs; 165185222Ssam int fragmap; 166185222Ssam int32_t fraglist[]; 167185222Ssam int cnt; 168185222Ssam int needswap; 169185222Ssam{ 170185222Ssam int inblk; 171185222Ssam int field, subfield; 172185222Ssam int siz, pos; 173185222Ssam 174185222Ssam inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; 175185222Ssam fragmap <<= 1; 176185222Ssam for (siz = 1; siz < fs->fs_frag; siz++) { 177185222Ssam if ((inblk & (1 << (siz + (fs->fs_frag & (NBBY - 1))))) == 0) 178185222Ssam continue; 179185222Ssam field = around[siz]; 180185222Ssam subfield = inside[siz]; 181185222Ssam for (pos = siz; pos <= fs->fs_frag; pos++) { 182185222Ssam if ((fragmap & field) == subfield) { 183185222Ssam fraglist[siz] = ufs_rw32( 184185222Ssam ufs_rw32(fraglist[siz], needswap) + cnt, 185185222Ssam needswap); 186185222Ssam pos += siz; 187185222Ssam field <<= siz; 188185222Ssam subfield <<= siz; 189185222Ssam } 190185222Ssam field <<= 1; 191185222Ssam subfield <<= 1; 192185222Ssam } 193185222Ssam } 194185222Ssam} 195185222Ssam 196185222Ssam#if defined(_KERNEL) && defined(DIAGNOSTIC) 197185222Ssamvoid 198185222Ssamffs_checkoverlap(bp, ip) 199185222Ssam struct buf *bp; 200185222Ssam struct inode *ip; 201185222Ssam{ 202185222Ssam#if 0 203185222Ssam struct buf *ebp, *ep; 204185222Ssam daddr_t start, last; 205185222Ssam struct vnode *vp; 206185222Ssam 207185222Ssam ebp = &buf[nbuf]; 208185222Ssam start = bp->b_blkno; 209185222Ssam last = start + btodb(bp->b_bcount) - 1; 210185222Ssam for (ep = buf; ep < ebp; ep++) { 211185222Ssam if (ep == bp || (ep->b_flags & B_INVAL) || 212185222Ssam ep->b_vp == NULLVP) 213185222Ssam continue; 214185222Ssam if (VOP_BMAP(ep->b_vp, (daddr_t)0, &vp, (daddr_t)0, NULL)) 215185222Ssam continue; 216185222Ssam if (vp != ip->i_devvp) 217185222Ssam continue; 218185222Ssam /* look for overlap */ 219185222Ssam if (ep->b_bcount == 0 || ep->b_blkno > last || 220185222Ssam ep->b_blkno + btodb(ep->b_bcount) <= start) 221185222Ssam continue; 222185222Ssam vprint("Disk overlap", vp); 223185222Ssam printf("\tstart %" PRId64 ", end %" PRId64 " overlap start " 224185222Ssam "%" PRId64 ", end %" PRId64 "\n", 225185222Ssam start, last, ep->b_blkno, 226185222Ssam ep->b_blkno + btodb(ep->b_bcount) - 1); 227185222Ssam panic("Disk buffer overlap"); 228185222Ssam } 229185222Ssam#else 230185222Ssam printf("ffs_checkoverlap disabled due to buffer cache implementation changes\n"); 231185222Ssam#endif 232185222Ssam} 233185222Ssam#endif /* _KERNEL && DIAGNOSTIC */ 234185222Ssam 235185222Ssam/* 236185222Ssam * block operations 237185222Ssam * 238185222Ssam * check if a block is available 239185222Ssam * returns true if all the correponding bits in the free map are 1 240185222Ssam * returns false if any corresponding bit in the free map is 0 241185222Ssam */ 242185222Ssamint 243185222Ssamffs_isblock(fs, cp, h) 244185222Ssam struct fs *fs; 245185222Ssam u_char *cp; 246185222Ssam int32_t h; 247185222Ssam{ 248185222Ssam u_char mask; 249185222Ssam 250185222Ssam switch ((int)fs->fs_fragshift) { 251185222Ssam case 3: 252185222Ssam return (cp[h] == 0xff); 253185222Ssam case 2: 254185222Ssam mask = 0x0f << ((h & 0x1) << 2); 255185222Ssam return ((cp[h >> 1] & mask) == mask); 256185222Ssam case 1: 257185222Ssam mask = 0x03 << ((h & 0x3) << 1); 258185222Ssam return ((cp[h >> 2] & mask) == mask); 259185222Ssam case 0: 260185222Ssam mask = 0x01 << (h & 0x7); 261185222Ssam return ((cp[h >> 3] & mask) == mask); 262185222Ssam default: 263185222Ssam panic("ffs_isblock: unknown fs_fragshift %d", 264185222Ssam (int)fs->fs_fragshift); 265185222Ssam } 266185222Ssam} 267185222Ssam 268185222Ssam/* 269185222Ssam * check if a block is completely allocated 270185222Ssam * returns true if all the corresponding bits in the free map are 0 271185222Ssam * returns false if any corresponding bit in the free map is 1 272185222Ssam */ 273185222Ssamint 274185222Ssamffs_isfreeblock(fs, cp, h) 275185222Ssam struct fs *fs; 276185222Ssam u_char *cp; 277185222Ssam int32_t h; 278185222Ssam{ 279185222Ssam 280185222Ssam switch ((int)fs->fs_fragshift) { 281185222Ssam case 3: 282185222Ssam return (cp[h] == 0); 283185222Ssam case 2: 284185222Ssam return ((cp[h >> 1] & (0x0f << ((h & 0x1) << 2))) == 0); 285185222Ssam case 1: 286185222Ssam return ((cp[h >> 2] & (0x03 << ((h & 0x3) << 1))) == 0); 287185222Ssam case 0: 288185222Ssam return ((cp[h >> 3] & (0x01 << (h & 0x7))) == 0); 289185222Ssam default: 290185222Ssam panic("ffs_isfreeblock: unknown fs_fragshift %d", 291185222Ssam (int)fs->fs_fragshift); 292185222Ssam } 293185222Ssam} 294185222Ssam 295185222Ssam/* 296185222Ssam * take a block out of the map 297185222Ssam */ 298185222Ssamvoid 299185222Ssamffs_clrblock(fs, cp, h) 300185222Ssam struct fs *fs; 301185222Ssam u_char *cp; 302185222Ssam int32_t h; 303185222Ssam{ 304185222Ssam 305185222Ssam switch ((int)fs->fs_fragshift) { 306185222Ssam case 3: 307185222Ssam cp[h] = 0; 308185222Ssam return; 309185222Ssam case 2: 310185222Ssam cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 311185222Ssam return; 312185222Ssam case 1: 313185222Ssam cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 314185222Ssam return; 315185222Ssam case 0: 316185222Ssam cp[h >> 3] &= ~(0x01 << (h & 0x7)); 317185222Ssam return; 318185222Ssam default: 319185222Ssam panic("ffs_clrblock: unknown fs_fragshift %d", 320185222Ssam (int)fs->fs_fragshift); 321185222Ssam } 322185222Ssam} 323185222Ssam 324185222Ssam/* 325185222Ssam * put a block into the map 326185222Ssam */ 327185222Ssamvoid 328185222Ssamffs_setblock(fs, cp, h) 329185222Ssam struct fs *fs; 330185222Ssam u_char *cp; 331185222Ssam int32_t h; 332185222Ssam{ 333185222Ssam 334185222Ssam switch ((int)fs->fs_fragshift) { 335185222Ssam case 3: 336185222Ssam cp[h] = 0xff; 337185222Ssam return; 338185222Ssam case 2: 339185222Ssam cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 340185222Ssam return; 341185222Ssam case 1: 342185222Ssam cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 343185222Ssam return; 344185222Ssam case 0: 345185222Ssam cp[h >> 3] |= (0x01 << (h & 0x7)); 346185222Ssam return; 347185222Ssam default: 348185222Ssam panic("ffs_setblock: unknown fs_fragshift %d", 349185222Ssam (int)fs->fs_fragshift); 350185222Ssam } 351185222Ssam} 352