1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * @(#)ffs_subr.c 7.8 (Berkeley) 05/09/89 18 */ 19 20 #ifdef KERNEL 21 #include "param.h" 22 #include "systm.h" 23 #include "buf.h" 24 #include "time.h" 25 #include "kernel.h" 26 #include "file.h" 27 #include "mount.h" 28 #include "vnode.h" 29 #include "../ufs/inode.h" 30 #include "../ufs/ufsmount.h" 31 #include "../ufs/fs.h" 32 #include "../ufs/quota.h" 33 #else 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/buf.h> 37 #include <sys/time.h> 38 #include <sys/file.h> 39 #include <sys/mount.h> 40 #include <sys/vnode.h> 41 #include <ufs/inode.h> 42 #include <ufs/ufsmount.h> 43 #include <ufs/fs.h> 44 #include <ufs/quota.h> 45 #endif 46 47 #ifdef KERNEL 48 /* 49 * Flush all the blocks associated with an inode. 50 * There are two strategies based on the size of the file; 51 * large files are those with more than (nbuf / 2) blocks. 52 * Large files 53 * Walk through the buffer pool and push any dirty pages 54 * associated with the device on which the file resides. 55 * Small files 56 * Look up each block in the file to see if it is in the 57 * buffer pool writing any that are found to disk. 58 * Note that we make a more stringent check of 59 * writing out any block in the buffer pool that may 60 * overlap the inode. This brings the inode up to 61 * date with recent mods to the cooked device. 62 */ 63 syncip(ip) 64 register struct inode *ip; 65 { 66 register struct fs *fs; 67 register struct buf *bp; 68 struct buf *lastbufp; 69 long lbn, lastlbn; 70 int s, error, allerror = 0; 71 daddr_t blkno; 72 73 fs = ip->i_fs; 74 lastlbn = howmany(ip->i_size, fs->fs_bsize); 75 if (lastlbn < nbuf / 2) { 76 for (lbn = 0; lbn < lastlbn; lbn++) { 77 error = bmap(ip, lbn, &blkno, (daddr_t *)0, (int *)0); 78 if (error) 79 allerror = error; 80 if (error = blkflush(ip->i_devvp, blkno, 81 blksize(fs, ip, lbn))) 82 allerror = error; 83 } 84 } else { 85 lastbufp = &buf[nbuf]; 86 for (bp = buf; bp < lastbufp; bp++) { 87 if (bp->b_dev != ip->i_dev || 88 (bp->b_flags & B_DELWRI) == 0) 89 continue; 90 s = splbio(); 91 if (bp->b_flags & B_BUSY) { 92 bp->b_flags |= B_WANTED; 93 sleep((caddr_t)bp, PRIBIO+1); 94 splx(s); 95 bp--; 96 continue; 97 } 98 splx(s); 99 notavail(bp); 100 if (error = bwrite(bp)) 101 allerror = error; 102 } 103 } 104 if (error = iupdat(ip, &time, &time, 1)) 105 allerror = error; 106 return (allerror); 107 } 108 #endif KERNEL 109 110 extern int around[9]; 111 extern int inside[9]; 112 extern u_char *fragtbl[]; 113 114 /* 115 * Update the frsum fields to reflect addition or deletion 116 * of some frags. 117 */ 118 fragacct(fs, fragmap, fraglist, cnt) 119 struct fs *fs; 120 int fragmap; 121 long fraglist[]; 122 int cnt; 123 { 124 int inblk; 125 register int field, subfield; 126 register int siz, pos; 127 128 inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1; 129 fragmap <<= 1; 130 for (siz = 1; siz < fs->fs_frag; siz++) { 131 if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0) 132 continue; 133 field = around[siz]; 134 subfield = inside[siz]; 135 for (pos = siz; pos <= fs->fs_frag; pos++) { 136 if ((fragmap & field) == subfield) { 137 fraglist[siz] += cnt; 138 pos += siz; 139 field <<= siz; 140 subfield <<= siz; 141 } 142 field <<= 1; 143 subfield <<= 1; 144 } 145 } 146 } 147 148 #ifdef KERNEL 149 /* 150 * Check that a specified block number is in range. 151 */ 152 badblock(fs, bn) 153 register struct fs *fs; 154 daddr_t bn; 155 { 156 157 if ((unsigned)bn >= fs->fs_size) { 158 printf("bad block %d, ", bn); 159 fserr(fs, "bad block"); 160 return (1); 161 } 162 return (0); 163 } 164 #endif 165 166 /* 167 * block operations 168 * 169 * check if a block is available 170 */ 171 isblock(fs, cp, h) 172 struct fs *fs; 173 unsigned char *cp; 174 daddr_t h; 175 { 176 unsigned char mask; 177 178 switch ((int)fs->fs_frag) { 179 case 8: 180 return (cp[h] == 0xff); 181 case 4: 182 mask = 0x0f << ((h & 0x1) << 2); 183 return ((cp[h >> 1] & mask) == mask); 184 case 2: 185 mask = 0x03 << ((h & 0x3) << 1); 186 return ((cp[h >> 2] & mask) == mask); 187 case 1: 188 mask = 0x01 << (h & 0x7); 189 return ((cp[h >> 3] & mask) == mask); 190 default: 191 panic("isblock"); 192 return (NULL); 193 } 194 } 195 196 /* 197 * take a block out of the map 198 */ 199 clrblock(fs, cp, h) 200 struct fs *fs; 201 u_char *cp; 202 daddr_t h; 203 { 204 205 switch ((int)fs->fs_frag) { 206 case 8: 207 cp[h] = 0; 208 return; 209 case 4: 210 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 211 return; 212 case 2: 213 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 214 return; 215 case 1: 216 cp[h >> 3] &= ~(0x01 << (h & 0x7)); 217 return; 218 default: 219 panic("clrblock"); 220 } 221 } 222 223 /* 224 * put a block into the map 225 */ 226 setblock(fs, cp, h) 227 struct fs *fs; 228 unsigned char *cp; 229 daddr_t h; 230 { 231 232 switch ((int)fs->fs_frag) { 233 234 case 8: 235 cp[h] = 0xff; 236 return; 237 case 4: 238 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 239 return; 240 case 2: 241 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 242 return; 243 case 1: 244 cp[h >> 3] |= (0x01 << (h & 0x7)); 245 return; 246 default: 247 panic("setblock"); 248 } 249 } 250 251 #ifdef KERNEL 252 /* 253 * Getfs maps a device number into a pointer to the incore super block. 254 * 255 * The algorithm is a linear search through the mount table. A 256 * consistency check of the super block magic number is performed. 257 * Filesystems still working on a mount are skipped. 258 * 259 * panic: no fs -- the device is not mounted. 260 * this "cannot happen" 261 */ 262 struct fs * 263 getfs(dev) 264 dev_t dev; 265 { 266 register struct ufsmount *mp; 267 register struct fs *fs; 268 269 for (mp = &mounttab[0]; mp < &mounttab[NMOUNT]; mp++) { 270 if (mp->um_fs == NULL || mp->um_dev != dev || 271 mp->um_fs == (struct fs *)1) /* XXX */ 272 continue; 273 fs = mp->um_fs; 274 if (fs->fs_magic != FS_MAGIC) { 275 printf("dev = 0x%x, fs = %s\n", dev, fs->fs_fsmnt); 276 panic("getfs: bad magic"); 277 } 278 return (fs); 279 } 280 printf("dev = 0x%x\n", dev); 281 panic("getfs: no fs"); 282 return (NULL); 283 } 284 285 /* 286 * Getfsx returns the index in the file system 287 * table of the specified device. The swap device 288 * is also assigned a pseudo-index. The index may 289 * be used as a compressed indication of the location 290 * of a block, recording 291 * <getfsx(dev),blkno> 292 * rather than 293 * <dev, blkno> 294 * provided the information need remain valid only 295 * as long as the file system is mounted. 296 */ 297 getfsx(dev) 298 dev_t dev; 299 { 300 register struct ufsmount *mp; 301 302 if (dev == swapdev) 303 return (MSWAPX); 304 for(mp = &mounttab[0]; mp < &mounttab[NMOUNT]; mp++) 305 if (mp->um_dev == dev) 306 return (mp - &mounttab[0]); 307 return (-1); 308 } 309 #endif 310 311 #if (!defined(vax) && !defined(tahoe)) || defined(VAX630) || defined(VAX650) 312 /* 313 * C definitions of special instructions. 314 * Normally expanded with inline. 315 */ 316 scanc(size, cp, table, mask) 317 u_int size; 318 register u_char *cp, table[]; 319 register u_char mask; 320 { 321 register u_char *end = &cp[size]; 322 323 while (cp < end && (table[*cp] & mask) == 0) 324 cp++; 325 return (end - cp); 326 } 327 #endif 328 329 #if !defined(vax) && !defined(tahoe) 330 skpc(mask, size, cp) 331 register u_char mask; 332 u_int size; 333 register u_char *cp; 334 { 335 register u_char *end = &cp[size]; 336 337 while (cp < end && *cp == mask) 338 cp++; 339 return (end - cp); 340 } 341 342 locc(mask, size, cp) 343 register u_char mask; 344 u_int size; 345 register u_char *cp; 346 { 347 register u_char *end = &cp[size]; 348 349 while (cp < end && *cp != mask) 350 cp++; 351 return (end - cp); 352 } 353 #endif 354