1 /* $NetBSD: ffs_subr.c,v 1.45 2008/06/03 09:47:49 hannken Exp $ */ 2 3 /* 4 * Copyright (c) 1982, 1986, 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * @(#)ffs_subr.c 8.5 (Berkeley) 3/21/95 32 */ 33 34 #if HAVE_NBTOOL_CONFIG_H 35 #include "nbtool_config.h" 36 #endif 37 38 #include <sys/cdefs.h> 39 __KERNEL_RCSID(0, "$NetBSD: ffs_subr.c,v 1.45 2008/06/03 09:47:49 hannken Exp $"); 40 41 #include <sys/param.h> 42 43 /* in ffs_tables.c */ 44 extern const int inside[], around[]; 45 extern const u_char * const fragtbl[]; 46 47 #include <ufs/ffs/fs.h> 48 #include <ufs/ffs/ffs_extern.h> 49 #include <ufs/ufs/ufs_bswap.h> 50 51 #ifndef _KERNEL 52 #include <ufs/ufs/dinode.h> 53 void panic(const char *, ...) 54 __attribute__((__noreturn__,__format__(__printf__,1,2))); 55 56 #else /* _KERNEL */ 57 #include <sys/systm.h> 58 #include <sys/vnode.h> 59 #include <sys/mount.h> 60 #include <sys/buf.h> 61 #include <sys/inttypes.h> 62 #include <sys/pool.h> 63 #include <sys/fstrans.h> 64 #include <ufs/ufs/inode.h> 65 #include <ufs/ufs/ufsmount.h> 66 #include <ufs/ufs/ufs_extern.h> 67 68 /* 69 * Load up the contents of an inode and copy the appropriate pieces 70 * to the incore copy. 71 */ 72 void 73 ffs_load_inode(struct buf *bp, struct inode *ip, struct fs *fs, ino_t ino) 74 { 75 struct ufs1_dinode *dp1; 76 struct ufs2_dinode *dp2; 77 78 if (ip->i_ump->um_fstype == UFS1) { 79 dp1 = (struct ufs1_dinode *)bp->b_data + ino_to_fsbo(fs, ino); 80 #ifdef FFS_EI 81 if (UFS_FSNEEDSWAP(fs)) 82 ffs_dinode1_swap(dp1, ip->i_din.ffs1_din); 83 else 84 #endif 85 *ip->i_din.ffs1_din = *dp1; 86 87 ip->i_mode = ip->i_ffs1_mode; 88 ip->i_nlink = ip->i_ffs1_nlink; 89 ip->i_size = ip->i_ffs1_size; 90 ip->i_flags = ip->i_ffs1_flags; 91 ip->i_gen = ip->i_ffs1_gen; 92 ip->i_uid = ip->i_ffs1_uid; 93 ip->i_gid = ip->i_ffs1_gid; 94 } else { 95 dp2 = (struct ufs2_dinode *)bp->b_data + ino_to_fsbo(fs, ino); 96 #ifdef FFS_EI 97 if (UFS_FSNEEDSWAP(fs)) 98 ffs_dinode2_swap(dp2, ip->i_din.ffs2_din); 99 else 100 #endif 101 *ip->i_din.ffs2_din = *dp2; 102 103 ip->i_mode = ip->i_ffs2_mode; 104 ip->i_nlink = ip->i_ffs2_nlink; 105 ip->i_size = ip->i_ffs2_size; 106 ip->i_flags = ip->i_ffs2_flags; 107 ip->i_gen = ip->i_ffs2_gen; 108 ip->i_uid = ip->i_ffs2_uid; 109 ip->i_gid = ip->i_ffs2_gid; 110 } 111 } 112 113 int 114 ffs_getblk(struct vnode *vp, daddr_t lblkno, daddr_t blkno, int size, 115 bool clearbuf, buf_t **bpp) 116 { 117 int error = 0; 118 119 KASSERT(blkno >= 0 || blkno == FFS_NOBLK); 120 121 if ((*bpp = getblk(vp, lblkno, size, 0, 0)) == NULL) 122 return ENOMEM; 123 if (blkno != FFS_NOBLK) 124 (*bpp)->b_blkno = blkno; 125 if (clearbuf) 126 clrbuf(*bpp); 127 if ((*bpp)->b_blkno >= 0 && (error = fscow_run(*bpp, false)) != 0) 128 brelse(*bpp, BC_INVAL); 129 return error; 130 } 131 132 #endif /* _KERNEL */ 133 134 /* 135 * Update the frsum fields to reflect addition or deletion 136 * of some frags. 137 */ 138 void 139 ffs_fragacct(struct fs *fs, int fragmap, int32_t fraglist[], int cnt, 140 int needswap) 141 { 142 int inblk; 143 int field, subfield; 144 int siz, pos; 145 146 inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; 147 fragmap <<= 1; 148 for (siz = 1; siz < fs->fs_frag; siz++) { 149 if ((inblk & (1 << (siz + (fs->fs_frag & (NBBY - 1))))) == 0) 150 continue; 151 field = around[siz]; 152 subfield = inside[siz]; 153 for (pos = siz; pos <= fs->fs_frag; pos++) { 154 if ((fragmap & field) == subfield) { 155 fraglist[siz] = ufs_rw32( 156 ufs_rw32(fraglist[siz], needswap) + cnt, 157 needswap); 158 pos += siz; 159 field <<= siz; 160 subfield <<= siz; 161 } 162 field <<= 1; 163 subfield <<= 1; 164 } 165 } 166 } 167 168 /* 169 * block operations 170 * 171 * check if a block is available 172 * returns true if all the correponding bits in the free map are 1 173 * returns false if any corresponding bit in the free map is 0 174 */ 175 int 176 ffs_isblock(struct fs *fs, u_char *cp, int32_t h) 177 { 178 u_char mask; 179 180 switch ((int)fs->fs_fragshift) { 181 case 3: 182 return (cp[h] == 0xff); 183 case 2: 184 mask = 0x0f << ((h & 0x1) << 2); 185 return ((cp[h >> 1] & mask) == mask); 186 case 1: 187 mask = 0x03 << ((h & 0x3) << 1); 188 return ((cp[h >> 2] & mask) == mask); 189 case 0: 190 mask = 0x01 << (h & 0x7); 191 return ((cp[h >> 3] & mask) == mask); 192 default: 193 panic("ffs_isblock: unknown fs_fragshift %d", 194 (int)fs->fs_fragshift); 195 } 196 } 197 198 /* 199 * check if a block is completely allocated 200 * returns true if all the corresponding bits in the free map are 0 201 * returns false if any corresponding bit in the free map is 1 202 */ 203 int 204 ffs_isfreeblock(struct fs *fs, u_char *cp, int32_t h) 205 { 206 207 switch ((int)fs->fs_fragshift) { 208 case 3: 209 return (cp[h] == 0); 210 case 2: 211 return ((cp[h >> 1] & (0x0f << ((h & 0x1) << 2))) == 0); 212 case 1: 213 return ((cp[h >> 2] & (0x03 << ((h & 0x3) << 1))) == 0); 214 case 0: 215 return ((cp[h >> 3] & (0x01 << (h & 0x7))) == 0); 216 default: 217 panic("ffs_isfreeblock: unknown fs_fragshift %d", 218 (int)fs->fs_fragshift); 219 } 220 } 221 222 /* 223 * take a block out of the map 224 */ 225 void 226 ffs_clrblock(struct fs *fs, u_char *cp, int32_t h) 227 { 228 229 switch ((int)fs->fs_fragshift) { 230 case 3: 231 cp[h] = 0; 232 return; 233 case 2: 234 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 235 return; 236 case 1: 237 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 238 return; 239 case 0: 240 cp[h >> 3] &= ~(0x01 << (h & 0x7)); 241 return; 242 default: 243 panic("ffs_clrblock: unknown fs_fragshift %d", 244 (int)fs->fs_fragshift); 245 } 246 } 247 248 /* 249 * put a block into the map 250 */ 251 void 252 ffs_setblock(struct fs *fs, u_char *cp, int32_t h) 253 { 254 255 switch ((int)fs->fs_fragshift) { 256 case 3: 257 cp[h] = 0xff; 258 return; 259 case 2: 260 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 261 return; 262 case 1: 263 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 264 return; 265 case 0: 266 cp[h >> 3] |= (0x01 << (h & 0x7)); 267 return; 268 default: 269 panic("ffs_setblock: unknown fs_fragshift %d", 270 (int)fs->fs_fragshift); 271 } 272 } 273