1 /* $OpenBSD: ffs_subr.c,v 1.35 2024/10/08 02:58:26 jsg 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 daddr_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, &bp)) != 0) { 72 brelse(bp); 73 return (error); 74 } 75 buf_adjcnt(bp, 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 *, daddr_t); 85 int ffs_isblock(struct fs *, u_char *, daddr_t); 86 void ffs_clrblock(struct fs *, u_char *, daddr_t); 87 void ffs_setblock(struct fs *, u_char *, daddr_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 /* 123 * block operations 124 * 125 * check if a block is available 126 */ 127 int 128 ffs_isblock(struct fs *fs, u_char *cp, daddr_t h) 129 { 130 u_char mask; 131 132 switch (fs->fs_frag) { 133 default: 134 case 8: 135 return (cp[h] == 0xff); 136 case 4: 137 mask = 0x0f << ((h & 0x1) << 2); 138 return ((cp[h >> 1] & mask) == mask); 139 case 2: 140 mask = 0x03 << ((h & 0x3) << 1); 141 return ((cp[h >> 2] & mask) == mask); 142 case 1: 143 mask = 0x01 << (h & 0x7); 144 return ((cp[h >> 3] & mask) == mask); 145 } 146 } 147 148 /* 149 * take a block out of the map 150 */ 151 void 152 ffs_clrblock(struct fs *fs, u_char *cp, daddr_t h) 153 { 154 155 switch (fs->fs_frag) { 156 default: 157 case 8: 158 cp[h] = 0; 159 return; 160 case 4: 161 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 162 return; 163 case 2: 164 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 165 return; 166 case 1: 167 cp[h >> 3] &= ~(0x01 << (h & 0x7)); 168 return; 169 } 170 } 171 172 /* 173 * put a block into the map 174 */ 175 void 176 ffs_setblock(struct fs *fs, u_char *cp, daddr_t h) 177 { 178 179 switch (fs->fs_frag) { 180 default: 181 case 8: 182 cp[h] = 0xff; 183 return; 184 case 4: 185 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 186 return; 187 case 2: 188 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 189 return; 190 case 1: 191 cp[h >> 3] |= (0x01 << (h & 0x7)); 192 return; 193 } 194 } 195 196 /* 197 * check if a block is free 198 */ 199 int 200 ffs_isfreeblock(struct fs *fs, u_char *cp, daddr_t h) 201 { 202 203 switch (fs->fs_frag) { 204 default: 205 case 8: 206 return (cp[h] == 0); 207 case 4: 208 return ((cp[h >> 1] & (0x0f << ((h & 0x1) << 2))) == 0); 209 case 2: 210 return ((cp[h >> 2] & (0x03 << ((h & 0x3) << 1))) == 0); 211 case 1: 212 return ((cp[h >> 3] & (0x01 << (h & 0x7))) == 0); 213 } 214 } 215 216 #ifdef _KERNEL 217 /* 218 * Initialize the vnode associated with a new inode, handle aliased 219 * vnodes. 220 */ 221 int 222 ffs_vinit(struct mount *mntp, struct vnode **vpp) 223 { 224 struct inode *ip; 225 struct vnode *vp, *nvp; 226 struct timeval mtv; 227 228 vp = *vpp; 229 ip = VTOI(vp); 230 switch(vp->v_type = IFTOVT(DIP(ip, mode))) { 231 case VCHR: 232 case VBLK: 233 vp->v_op = &ffs_specvops; 234 if ((nvp = checkalias(vp, DIP(ip, rdev), mntp)) != NULL) { 235 /* 236 * Discard unneeded vnode, but save its inode. 237 * Note that the lock is carried over in the inode 238 * to the replacement vnode. 239 */ 240 nvp->v_data = vp->v_data; 241 vp->v_data = NULL; 242 vp->v_op = &spec_vops; 243 #ifdef VFSLCKDEBUG 244 vp->v_flag &= ~VLOCKSWORK; 245 #endif 246 vrele(vp); 247 vgone(vp); 248 /* 249 * Reinitialize aliased inode. 250 */ 251 vp = nvp; 252 ip->i_vnode = vp; 253 } 254 break; 255 case VFIFO: 256 #ifdef FIFO 257 vp->v_op = &ffs_fifovops; 258 break; 259 #else 260 return (EOPNOTSUPP); 261 #endif 262 case VNON: 263 case VBAD: 264 case VSOCK: 265 case VLNK: 266 case VDIR: 267 case VREG: 268 break; 269 } 270 if (ip->i_number == ROOTINO) 271 vp->v_flag |= VROOT; 272 /* 273 * Initialize modrev times 274 */ 275 getmicrouptime(&mtv); 276 ip->i_modrev = (u_quad_t)mtv.tv_sec << 32; 277 ip->i_modrev |= (u_quad_t)mtv.tv_usec * 4294; 278 *vpp = vp; 279 return (0); 280 } 281 #endif /* _KERNEL */ 282