1 /* $OpenBSD: ffs_vfsops.c,v 1.6 1996/06/27 06:42:06 downsj Exp $ */ 2 /* $NetBSD: ffs_vfsops.c,v 1.19 1996/02/09 22:22:26 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1989, 1991, 1993, 1994 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. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)ffs_vfsops.c 8.14 (Berkeley) 11/28/94 37 */ 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/namei.h> 42 #include <sys/proc.h> 43 #include <sys/kernel.h> 44 #include <sys/vnode.h> 45 #include <sys/socket.h> 46 #include <sys/mount.h> 47 #include <sys/buf.h> 48 #include <sys/mbuf.h> 49 #include <sys/file.h> 50 #include <sys/disklabel.h> 51 #include <sys/ioctl.h> 52 #include <sys/errno.h> 53 #include <sys/malloc.h> 54 55 #include <miscfs/specfs/specdev.h> 56 57 #include <ufs/ufs/quota.h> 58 #include <ufs/ufs/ufsmount.h> 59 #include <ufs/ufs/inode.h> 60 #include <ufs/ufs/dir.h> 61 #include <ufs/ufs/ufs_extern.h> 62 63 #include <ufs/ffs/fs.h> 64 #include <ufs/ffs/ffs_extern.h> 65 66 int ffs_sbupdate __P((struct ufsmount *, int)); 67 68 struct vfsops ffs_vfsops = { 69 MOUNT_FFS, 70 ffs_mount, 71 ufs_start, 72 ffs_unmount, 73 ufs_root, 74 ufs_quotactl, 75 ffs_statfs, 76 ffs_sync, 77 ffs_vget, 78 ffs_fhtovp, 79 ffs_vptofh, 80 ffs_init, 81 }; 82 83 static struct ufs_dirops ffs_dirops = { 84 ufs_dirremove, 85 ufs_direnter, 86 ufs_dirempty, 87 ufs_dirrewrite, 88 ufs_checkpath, 89 }; 90 91 extern u_long nextgennumber; 92 93 /* 94 * Called by main() when ufs is going to be mounted as root. 95 * 96 * Name is updated by mount(8) after booting. 97 */ 98 #define ROOTNAME "root_device" 99 100 int 101 ffs_mountroot() 102 { 103 extern struct vnode *rootvp; 104 register struct fs *fs; 105 register struct mount *mp; 106 struct proc *p = curproc; /* XXX */ 107 struct ufsmount *ump; 108 size_t size; 109 int error; 110 111 /* 112 * Get vnodes for swapdev and rootdev. 113 */ 114 if (bdevvp(swapdev, &swapdev_vp) || bdevvp(rootdev, &rootvp)) 115 panic("ffs_mountroot: can't setup bdevvp's"); 116 117 mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK); 118 bzero((char *)mp, (u_long)sizeof(struct mount)); 119 mp->mnt_op = &ffs_vfsops; 120 mp->mnt_flag = MNT_RDONLY; 121 if ((error = ffs_mountfs(rootvp, mp, p)) != 0) { 122 free(mp, M_MOUNT); 123 return (error); 124 } 125 if ((error = vfs_lock(mp)) != 0) { 126 (void)ffs_unmount(mp, 0, p); 127 free(mp, M_MOUNT); 128 return (error); 129 } 130 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); 131 mp->mnt_vnodecovered = NULLVP; 132 ump = VFSTOUFS(mp); 133 fs = ump->um_fs; 134 bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt)); 135 fs->fs_fsmnt[0] = '/'; 136 bcopy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname, MNAMELEN); 137 (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 138 &size); 139 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 140 (void)ffs_statfs(mp, &mp->mnt_stat, p); 141 vfs_unlock(mp); 142 inittodr(fs->fs_time); 143 return (0); 144 } 145 146 /* 147 * VFS Operations. 148 * 149 * mount system call 150 */ 151 int 152 ffs_mount(mp, path, data, ndp, p) 153 register struct mount *mp; 154 char *path; 155 caddr_t data; 156 struct nameidata *ndp; 157 struct proc *p; 158 { 159 struct vnode *devvp; 160 struct ufs_args args; 161 struct ufsmount *ump = NULL; 162 register struct fs *fs; 163 size_t size; 164 int error, flags; 165 mode_t accessmode; 166 167 error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)); 168 if (error) 169 return (error); 170 /* 171 * If updating, check whether changing from read-only to 172 * read/write; if there is no device name, that's all we do. 173 */ 174 if (mp->mnt_flag & MNT_UPDATE) { 175 ump = VFSTOUFS(mp); 176 fs = ump->um_fs; 177 if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { 178 flags = WRITECLOSE; 179 if (mp->mnt_flag & MNT_FORCE) 180 flags |= FORCECLOSE; 181 if (vfs_busy(mp)) 182 return (EBUSY); 183 error = ffs_flushfiles(mp, flags, p); 184 if (error == 0 && 185 ffs_cgupdate(ump, MNT_WAIT) == 0 && 186 fs->fs_clean & FS_WASCLEAN) { 187 fs->fs_clean = FS_ISCLEAN; 188 (void) ffs_sbupdate(ump, MNT_WAIT); 189 } 190 vfs_unbusy(mp); 191 if (error) 192 return (error); 193 fs->fs_ronly = 1; 194 } 195 if (mp->mnt_flag & MNT_RELOAD) { 196 error = ffs_reload(mp, ndp->ni_cnd.cn_cred, p); 197 if (error) 198 return (error); 199 } 200 if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) { 201 /* 202 * If upgrade to read-write by non-root, then verify 203 * that user has necessary permissions on the device. 204 */ 205 if (p->p_ucred->cr_uid != 0) { 206 devvp = ump->um_devvp; 207 VOP_LOCK(devvp); 208 error = VOP_ACCESS(devvp, VREAD | VWRITE, 209 p->p_ucred, p); 210 if (error) { 211 VOP_UNLOCK(devvp); 212 return (error); 213 } 214 VOP_UNLOCK(devvp); 215 } 216 fs->fs_ronly = 0; 217 fs->fs_clean <<= 1; 218 fs->fs_fmod = 1; 219 } 220 if (args.fspec == 0) { 221 /* 222 * Process export requests. 223 */ 224 return (vfs_export(mp, &ump->um_export, &args.export)); 225 } 226 } 227 /* 228 * Not an update, or updating the name: look up the name 229 * and verify that it refers to a sensible block device. 230 */ 231 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); 232 if ((error = namei(ndp)) != 0) 233 return (error); 234 devvp = ndp->ni_vp; 235 236 if (devvp->v_type != VBLK) { 237 vrele(devvp); 238 return (ENOTBLK); 239 } 240 if (major(devvp->v_rdev) >= nblkdev) { 241 vrele(devvp); 242 return (ENXIO); 243 } 244 /* 245 * If mount by non-root, then verify that user has necessary 246 * permissions on the device. 247 */ 248 if (p->p_ucred->cr_uid != 0) { 249 accessmode = VREAD; 250 if ((mp->mnt_flag & MNT_RDONLY) == 0) 251 accessmode |= VWRITE; 252 VOP_LOCK(devvp); 253 error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p); 254 if (error) { 255 vput(devvp); 256 return (error); 257 } 258 VOP_UNLOCK(devvp); 259 } 260 if ((mp->mnt_flag & MNT_UPDATE) == 0) 261 error = ffs_mountfs(devvp, mp, p); 262 else { 263 if (devvp != ump->um_devvp) 264 error = EINVAL; /* needs translation */ 265 else 266 vrele(devvp); 267 } 268 if (error) { 269 vrele(devvp); 270 return (error); 271 } 272 ump = VFSTOUFS(mp); 273 fs = ump->um_fs; 274 (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 275 bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 276 bcopy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname, MNAMELEN); 277 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 278 &size); 279 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 280 if (fs->fs_fmod != 0) { /* XXX */ 281 fs->fs_fmod = 0; 282 if (fs->fs_clean & FS_WASCLEAN) 283 fs->fs_time = time.tv_sec; 284 else 285 printf("%s: file system not clean; please fsck(8)\n", 286 mp->mnt_stat.f_mntfromname); 287 (void) ffs_cgupdate(ump, MNT_WAIT); 288 } 289 return (0); 290 } 291 292 /* 293 * Reload all incore data for a filesystem (used after running fsck on 294 * the root filesystem and finding things to fix). The filesystem must 295 * be mounted read-only. 296 * 297 * Things to do to update the mount: 298 * 1) invalidate all cached meta-data. 299 * 2) re-read superblock from disk. 300 * 3) re-read summary information from disk. 301 * 4) invalidate all inactive vnodes. 302 * 5) invalidate all cached file data. 303 * 6) re-read inode data for all active vnodes. 304 */ 305 int 306 ffs_reload(mountp, cred, p) 307 register struct mount *mountp; 308 struct ucred *cred; 309 struct proc *p; 310 { 311 register struct vnode *vp, *nvp, *devvp; 312 struct inode *ip; 313 struct csum *space; 314 struct buf *bp; 315 struct fs *fs, *newfs; 316 struct partinfo dpart; 317 int i, blks, size, error; 318 int32_t *lp; 319 320 if ((mountp->mnt_flag & MNT_RDONLY) == 0) 321 return (EINVAL); 322 /* 323 * Step 1: invalidate all cached meta-data. 324 */ 325 devvp = VFSTOUFS(mountp)->um_devvp; 326 if (vinvalbuf(devvp, 0, cred, p, 0, 0)) 327 panic("ffs_reload: dirty1"); 328 /* 329 * Step 2: re-read superblock from disk. 330 */ 331 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0) 332 size = DEV_BSIZE; 333 else 334 size = dpart.disklab->d_secsize; 335 error = bread(devvp, (daddr_t)(SBOFF / size), SBSIZE, NOCRED, &bp); 336 if (error) 337 return (error); 338 newfs = (struct fs *)bp->b_data; 339 if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE || 340 newfs->fs_bsize < sizeof(struct fs)) { 341 brelse(bp); 342 return (EIO); /* XXX needs translation */ 343 } 344 fs = VFSTOUFS(mountp)->um_fs; 345 /* 346 * Copy pointer fields back into superblock before copying in XXX 347 * new superblock. These should really be in the ufsmount. XXX 348 * Note that important parameters (eg fs_ncg) are unchanged. 349 */ 350 bcopy(&fs->fs_csp[0], &newfs->fs_csp[0], sizeof(fs->fs_csp)); 351 newfs->fs_maxcluster = fs->fs_maxcluster; 352 bcopy(newfs, fs, (u_int)fs->fs_sbsize); 353 if (fs->fs_sbsize < SBSIZE) 354 bp->b_flags |= B_INVAL; 355 brelse(bp); 356 mountp->mnt_maxsymlinklen = fs->fs_maxsymlinklen; 357 ffs_oldfscompat(fs); 358 /* 359 * Step 3: re-read summary information from disk. 360 */ 361 blks = howmany(fs->fs_cssize, fs->fs_fsize); 362 space = fs->fs_csp[0]; 363 for (i = 0; i < blks; i += fs->fs_frag) { 364 size = fs->fs_bsize; 365 if (i + fs->fs_frag > blks) 366 size = (blks - i) * fs->fs_fsize; 367 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, 368 NOCRED, &bp); 369 if (error) 370 return (error); 371 bcopy(bp->b_data, fs->fs_csp[fragstoblks(fs, i)], (u_int)size); 372 brelse(bp); 373 } 374 /* 375 * We no longer know anything about clusters per cylinder group. 376 */ 377 if (fs->fs_contigsumsize > 0) { 378 lp = fs->fs_maxcluster; 379 for (i = 0; i < fs->fs_ncg; i++) 380 *lp++ = fs->fs_contigsumsize; 381 } 382 383 loop: 384 for (vp = mountp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) { 385 nvp = vp->v_mntvnodes.le_next; 386 /* 387 * Step 4: invalidate all inactive vnodes. 388 */ 389 if (vp->v_usecount == 0) { 390 vgone(vp); 391 continue; 392 } 393 /* 394 * Step 5: invalidate all cached file data. 395 */ 396 if (vget(vp, 1)) 397 goto loop; 398 if (vinvalbuf(vp, 0, cred, p, 0, 0)) 399 panic("ffs_reload: dirty2"); 400 /* 401 * Step 6: re-read inode data for all active vnodes. 402 */ 403 ip = VTOI(vp); 404 error = bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)), 405 (int)fs->fs_bsize, NOCRED, &bp); 406 if (error) { 407 vput(vp); 408 return (error); 409 } 410 ip->i_din = *((struct dinode *)bp->b_data + 411 ino_to_fsbo(fs, ip->i_number)); 412 brelse(bp); 413 vput(vp); 414 if (vp->v_mount != mountp) 415 goto loop; 416 } 417 return (0); 418 } 419 420 /* 421 * Common code for mount and mountroot 422 */ 423 int 424 ffs_mountfs(devvp, mp, p) 425 register struct vnode *devvp; 426 struct mount *mp; 427 struct proc *p; 428 { 429 register struct ufsmount *ump; 430 struct buf *bp; 431 register struct fs *fs; 432 dev_t dev; 433 struct partinfo dpart; 434 caddr_t base, space; 435 int blks; 436 int error, i, size, ronly; 437 int32_t *lp; 438 struct ucred *cred; 439 extern struct vnode *rootvp; 440 u_int64_t maxfilesize; /* XXX */ 441 442 dev = devvp->v_rdev; 443 cred = p ? p->p_ucred : NOCRED; 444 /* 445 * Disallow multiple mounts of the same device. 446 * Disallow mounting of a device that is currently in use 447 * (except for root, which might share swap device for miniroot). 448 * Flush out any old buffers remaining from a previous use. 449 */ 450 if ((error = vfs_mountedon(devvp)) != 0) 451 return (error); 452 if (vcount(devvp) > 1 && devvp != rootvp) 453 return (EBUSY); 454 if ((error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0)) != 0) 455 return (error); 456 457 ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 458 error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p); 459 if (error) 460 return (error); 461 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0) 462 size = DEV_BSIZE; 463 else 464 size = dpart.disklab->d_secsize; 465 466 bp = NULL; 467 ump = NULL; 468 error = bread(devvp, (daddr_t)(SBOFF / size), SBSIZE, cred, &bp); 469 if (error) 470 goto out; 471 fs = (struct fs *)bp->b_data; 472 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 473 fs->fs_bsize < sizeof(struct fs)) { 474 error = EINVAL; /* XXX needs translation */ 475 goto out; 476 } 477 /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */ 478 if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) { 479 error = EROFS; /* XXX what should be returned? */ 480 goto out; 481 } 482 ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK); 483 bzero((caddr_t)ump, sizeof *ump); 484 ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT, 485 M_WAITOK); 486 bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize); 487 if (fs->fs_sbsize < SBSIZE) 488 bp->b_flags |= B_INVAL; 489 brelse(bp); 490 bp = NULL; 491 fs = ump->um_fs; 492 fs->fs_ronly = ronly; 493 if (ronly == 0) { 494 fs->fs_clean <<= 1; 495 fs->fs_fmod = 1; 496 } 497 size = fs->fs_cssize; 498 blks = howmany(size, fs->fs_fsize); 499 if (fs->fs_contigsumsize > 0) 500 size += fs->fs_ncg * sizeof(int32_t); 501 base = space = malloc((u_long)size, M_UFSMNT, M_WAITOK); 502 for (i = 0; i < blks; i += fs->fs_frag) { 503 size = fs->fs_bsize; 504 if (i + fs->fs_frag > blks) 505 size = (blks - i) * fs->fs_fsize; 506 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, 507 cred, &bp); 508 if (error) { 509 free(base, M_UFSMNT); 510 goto out; 511 } 512 bcopy(bp->b_data, space, (u_int)size); 513 fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space; 514 space += size; 515 brelse(bp); 516 bp = NULL; 517 } 518 if (fs->fs_contigsumsize > 0) { 519 fs->fs_maxcluster = lp = (int32_t *)space; 520 for (i = 0; i < fs->fs_ncg; i++) 521 *lp++ = fs->fs_contigsumsize; 522 } 523 mp->mnt_data = (qaddr_t)ump; 524 mp->mnt_stat.f_fsid.val[0] = (long)dev; 525 mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_FFS); 526 mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen; 527 mp->mnt_flag |= MNT_LOCAL; 528 ump->um_mountp = mp; 529 ump->um_dev = dev; 530 ump->um_devvp = devvp; 531 ump->um_nindir = fs->fs_nindir; 532 ump->um_bptrtodb = fs->fs_fsbtodb; 533 ump->um_seqinc = fs->fs_frag; 534 ump->um_dirops = &ffs_dirops; 535 for (i = 0; i < MAXQUOTAS; i++) 536 ump->um_quotas[i] = NULLVP; 537 devvp->v_specflags |= SI_MOUNTEDON; 538 ffs_oldfscompat(fs); 539 ump->um_savedmaxfilesize = fs->fs_maxfilesize; /* XXX */ 540 maxfilesize = (u_int64_t)0x80000000 * fs->fs_bsize - 1; /* XXX */ 541 if (fs->fs_maxfilesize > maxfilesize) /* XXX */ 542 fs->fs_maxfilesize = maxfilesize; /* XXX */ 543 return (0); 544 out: 545 if (bp) 546 brelse(bp); 547 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p); 548 if (ump) { 549 free(ump->um_fs, M_UFSMNT); 550 free(ump, M_UFSMNT); 551 mp->mnt_data = (qaddr_t)0; 552 } 553 return (error); 554 } 555 556 /* 557 * Sanity checks for old file systems. 558 * 559 * XXX - goes away some day. 560 */ 561 int 562 ffs_oldfscompat(fs) 563 struct fs *fs; 564 { 565 int i; 566 567 fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */ 568 fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */ 569 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 570 fs->fs_nrpos = 8; /* XXX */ 571 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ 572 u_int64_t sizepb = fs->fs_bsize; /* XXX */ 573 /* XXX */ 574 fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */ 575 for (i = 0; i < NIADDR; i++) { /* XXX */ 576 sizepb *= NINDIR(fs); /* XXX */ 577 fs->fs_maxfilesize += sizepb; /* XXX */ 578 } /* XXX */ 579 fs->fs_qbmask = ~fs->fs_bmask; /* XXX */ 580 fs->fs_qfmask = ~fs->fs_fmask; /* XXX */ 581 } /* XXX */ 582 return (0); 583 } 584 585 /* 586 * unmount system call 587 */ 588 int 589 ffs_unmount(mp, mntflags, p) 590 struct mount *mp; 591 int mntflags; 592 struct proc *p; 593 { 594 register struct ufsmount *ump; 595 register struct fs *fs; 596 int error, flags; 597 598 flags = 0; 599 if (mntflags & MNT_FORCE) 600 flags |= FORCECLOSE; 601 if ((error = ffs_flushfiles(mp, flags, p)) != 0) 602 return (error); 603 ump = VFSTOUFS(mp); 604 fs = ump->um_fs; 605 if (fs->fs_ronly == 0 && 606 ffs_cgupdate(ump, MNT_WAIT) == 0 && 607 fs->fs_clean & FS_WASCLEAN) { 608 fs->fs_clean = FS_ISCLEAN; 609 (void) ffs_sbupdate(ump, MNT_WAIT); 610 } 611 ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; 612 error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE, 613 NOCRED, p); 614 vrele(ump->um_devvp); 615 free(fs->fs_csp[0], M_UFSMNT); 616 free(fs, M_UFSMNT); 617 free(ump, M_UFSMNT); 618 mp->mnt_data = (qaddr_t)0; 619 mp->mnt_flag &= ~MNT_LOCAL; 620 return (error); 621 } 622 623 /* 624 * Flush out all the files in a filesystem. 625 */ 626 int 627 ffs_flushfiles(mp, flags, p) 628 register struct mount *mp; 629 int flags; 630 struct proc *p; 631 { 632 extern int doforce; 633 register struct ufsmount *ump; 634 int error; 635 636 if (!doforce) 637 flags &= ~FORCECLOSE; 638 ump = VFSTOUFS(mp); 639 #ifdef QUOTA 640 if (mp->mnt_flag & MNT_QUOTA) { 641 int i; 642 if ((error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) != 0) 643 return (error); 644 for (i = 0; i < MAXQUOTAS; i++) { 645 if (ump->um_quotas[i] == NULLVP) 646 continue; 647 quotaoff(p, mp, i); 648 } 649 /* 650 * Here we fall through to vflush again to ensure 651 * that we have gotten rid of all the system vnodes. 652 */ 653 } 654 #endif 655 error = vflush(mp, NULLVP, flags); 656 return (error); 657 } 658 659 /* 660 * Get file system statistics. 661 */ 662 int 663 ffs_statfs(mp, sbp, p) 664 struct mount *mp; 665 register struct statfs *sbp; 666 struct proc *p; 667 { 668 register struct ufsmount *ump; 669 register struct fs *fs; 670 671 ump = VFSTOUFS(mp); 672 fs = ump->um_fs; 673 if (fs->fs_magic != FS_MAGIC) 674 panic("ffs_statfs"); 675 #ifdef COMPAT_09 676 sbp->f_type = 1; 677 #else 678 sbp->f_type = 0; 679 #endif 680 sbp->f_bsize = fs->fs_fsize; 681 sbp->f_iosize = fs->fs_bsize; 682 sbp->f_blocks = fs->fs_dsize; 683 sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + 684 fs->fs_cstotal.cs_nffree; 685 sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) - 686 (fs->fs_dsize - sbp->f_bfree); 687 sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO; 688 sbp->f_ffree = fs->fs_cstotal.cs_nifree; 689 if (sbp != &mp->mnt_stat) { 690 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 691 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 692 } 693 strncpy(sbp->f_fstypename, mp->mnt_op->vfs_name, MFSNAMELEN); 694 return (0); 695 } 696 697 /* 698 * Go through the disk queues to initiate sandbagged IO; 699 * go through the inodes to write those that have been modified; 700 * initiate the writing of the super block if it has been modified. 701 * 702 * Note: we are always called with the filesystem marked `MPBUSY'. 703 */ 704 int 705 ffs_sync(mp, waitfor, cred, p) 706 struct mount *mp; 707 int waitfor; 708 struct ucred *cred; 709 struct proc *p; 710 { 711 register struct vnode *vp; 712 register struct inode *ip; 713 register struct ufsmount *ump = VFSTOUFS(mp); 714 register struct fs *fs; 715 int error, allerror = 0; 716 717 fs = ump->um_fs; 718 /* 719 * Write back modified superblock. 720 * Consistency check that the superblock 721 * is still in the buffer cache. 722 */ 723 if (fs->fs_fmod != 0) { 724 if (fs->fs_ronly != 0) { /* XXX */ 725 printf("fs = %s\n", fs->fs_fsmnt); 726 panic("update: rofs mod"); 727 } 728 fs->fs_fmod = 0; 729 fs->fs_time = time.tv_sec; 730 allerror = ffs_cgupdate(ump, waitfor); 731 } 732 /* 733 * Write back each (modified) inode. 734 */ 735 loop: 736 for (vp = mp->mnt_vnodelist.lh_first; 737 vp != NULL; 738 vp = vp->v_mntvnodes.le_next) { 739 /* 740 * If the vnode that we are about to sync is no longer 741 * associated with this mount point, start over. 742 */ 743 if (vp->v_mount != mp) 744 goto loop; 745 if (VOP_ISLOCKED(vp)) 746 continue; 747 ip = VTOI(vp); 748 if ((ip->i_flag & 749 (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 && 750 vp->v_dirtyblkhd.lh_first == NULL) 751 continue; 752 if (vget(vp, 1)) 753 goto loop; 754 if ((error = VOP_FSYNC(vp, cred, waitfor, p)) != 0) 755 allerror = error; 756 vput(vp); 757 } 758 /* 759 * Force stale file system control information to be flushed. 760 */ 761 if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0) 762 allerror = error; 763 #ifdef QUOTA 764 qsync(mp); 765 #endif 766 return (allerror); 767 } 768 769 /* 770 * Look up a FFS dinode number to find its incore vnode, otherwise read it 771 * in from disk. If it is in core, wait for the lock bit to clear, then 772 * return the inode locked. Detection and handling of mount points must be 773 * done by the calling routine. 774 */ 775 int 776 ffs_vget(mp, ino, vpp) 777 struct mount *mp; 778 ino_t ino; 779 struct vnode **vpp; 780 { 781 register struct fs *fs; 782 register struct inode *ip; 783 struct ufsmount *ump; 784 struct buf *bp; 785 struct vnode *vp; 786 dev_t dev; 787 int type, error; 788 789 ump = VFSTOUFS(mp); 790 dev = ump->um_dev; 791 if ((*vpp = ufs_ihashget(dev, ino)) != NULL) 792 return (0); 793 794 /* Allocate a new vnode/inode. */ 795 if ((error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp)) != 0) { 796 *vpp = NULL; 797 return (error); 798 } 799 type = ump->um_devvp->v_tag == VT_MFS ? M_MFSNODE : M_FFSNODE; /* XXX */ 800 MALLOC(ip, struct inode *, sizeof(struct inode), type, M_WAITOK); 801 bzero((caddr_t)ip, sizeof(struct inode)); 802 vp->v_data = ip; 803 ip->i_vnode = vp; 804 ip->i_fs = fs = ump->um_fs; 805 ip->i_dev = dev; 806 ip->i_number = ino; 807 #ifdef QUOTA 808 { 809 int i; 810 811 for (i = 0; i < MAXQUOTAS; i++) 812 ip->i_dquot[i] = NODQUOT; 813 } 814 #endif 815 /* 816 * Put it onto its hash chain and lock it so that other requests for 817 * this inode will block if they arrive while we are sleeping waiting 818 * for old data structures to be purged or for the contents of the 819 * disk portion of this inode to be read. 820 */ 821 ufs_ihashins(ip); 822 823 /* Read in the disk contents for the inode, copy into the inode. */ 824 error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)), 825 (int)fs->fs_bsize, NOCRED, &bp); 826 if (error) { 827 /* 828 * The inode does not contain anything useful, so it would 829 * be misleading to leave it on its hash chain. With mode 830 * still zero, it will be unlinked and returned to the free 831 * list by vput(). 832 */ 833 vput(vp); 834 brelse(bp); 835 *vpp = NULL; 836 return (error); 837 } 838 ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino)); 839 brelse(bp); 840 841 /* 842 * Initialize the vnode from the inode, check for aliases. 843 * Note that the underlying vnode may have changed. 844 */ 845 error = ufs_vinit(mp, ffs_specop_p, FFS_FIFOOPS, &vp); 846 if (error) { 847 vput(vp); 848 *vpp = NULL; 849 return (error); 850 } 851 /* 852 * Finish inode initialization now that aliasing has been resolved. 853 */ 854 ip->i_devvp = ump->um_devvp; 855 VREF(ip->i_devvp); 856 /* 857 * Set up a generation number for this inode if it does not 858 * already have one. This should only happen on old filesystems. 859 */ 860 if (ip->i_gen == 0) { 861 if (++nextgennumber < (u_long)time.tv_sec) 862 nextgennumber = time.tv_sec; 863 ip->i_gen = nextgennumber; 864 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) 865 ip->i_flag |= IN_MODIFIED; 866 } 867 /* 868 * Ensure that uid and gid are correct. This is a temporary 869 * fix until fsck has been changed to do the update. 870 */ 871 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ 872 ip->i_uid = ip->i_din.di_ouid; /* XXX */ 873 ip->i_gid = ip->i_din.di_ogid; /* XXX */ 874 } /* XXX */ 875 876 *vpp = vp; 877 return (0); 878 } 879 880 /* 881 * File handle to vnode 882 * 883 * Have to be really careful about stale file handles: 884 * - check that the inode number is valid 885 * - call ffs_vget() to get the locked inode 886 * - check for an unallocated inode (i_mode == 0) 887 * - check that the given client host has export rights and return 888 * those rights via. exflagsp and credanonp 889 */ 890 int 891 ffs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) 892 register struct mount *mp; 893 struct fid *fhp; 894 struct mbuf *nam; 895 struct vnode **vpp; 896 int *exflagsp; 897 struct ucred **credanonp; 898 { 899 register struct ufid *ufhp; 900 struct fs *fs; 901 902 ufhp = (struct ufid *)fhp; 903 fs = VFSTOUFS(mp)->um_fs; 904 if (ufhp->ufid_ino < ROOTINO || 905 ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) 906 return (ESTALE); 907 return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp)); 908 } 909 910 /* 911 * Vnode pointer to File handle 912 */ 913 /* ARGSUSED */ 914 int 915 ffs_vptofh(vp, fhp) 916 struct vnode *vp; 917 struct fid *fhp; 918 { 919 register struct inode *ip; 920 register struct ufid *ufhp; 921 922 ip = VTOI(vp); 923 ufhp = (struct ufid *)fhp; 924 ufhp->ufid_len = sizeof(struct ufid); 925 ufhp->ufid_ino = ip->i_number; 926 ufhp->ufid_gen = ip->i_gen; 927 return (0); 928 } 929 930 /* 931 * Write a superblock and associated information back to disk. 932 */ 933 int 934 ffs_sbupdate(mp, waitfor) 935 struct ufsmount *mp; 936 int waitfor; 937 { 938 register struct fs *dfs, *fs = mp->um_fs; 939 register struct buf *bp; 940 int i, error = 0; 941 942 bp = getblk(mp->um_devvp, SBOFF >> (fs->fs_fshift - fs->fs_fsbtodb), 943 (int)fs->fs_sbsize, 0, 0); 944 bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize); 945 /* Restore compatibility to old file systems. XXX */ 946 dfs = (struct fs *)bp->b_data; /* XXX */ 947 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 948 dfs->fs_nrpos = -1; /* XXX */ 949 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ 950 int32_t *lp, tmp; /* XXX */ 951 /* XXX */ 952 lp = (int32_t *)&dfs->fs_qbmask; /* XXX */ 953 tmp = lp[4]; /* XXX */ 954 for (i = 4; i > 0; i--) /* XXX */ 955 lp[i] = lp[i-1]; /* XXX */ 956 lp[0] = tmp; /* XXX */ 957 } /* XXX */ 958 dfs->fs_maxfilesize = mp->um_savedmaxfilesize; /* XXX */ 959 if (waitfor == MNT_WAIT) 960 error = bwrite(bp); 961 else 962 bawrite(bp); 963 return (error); 964 } 965 966 int 967 ffs_cgupdate(mp, waitfor) 968 struct ufsmount *mp; 969 int waitfor; 970 { 971 register struct fs *fs = mp->um_fs; 972 register struct buf *bp; 973 int blks; 974 caddr_t space; 975 int i, size, error = 0, allerror = 0; 976 977 allerror = ffs_sbupdate(mp, waitfor); 978 blks = howmany(fs->fs_cssize, fs->fs_fsize); 979 space = (caddr_t)fs->fs_csp[0]; 980 for (i = 0; i < blks; i += fs->fs_frag) { 981 size = fs->fs_bsize; 982 if (i + fs->fs_frag > blks) 983 size = (blks - i) * fs->fs_fsize; 984 bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), 985 size, 0, 0); 986 bcopy(space, bp->b_data, (u_int)size); 987 space += size; 988 if (waitfor == MNT_WAIT) 989 error = bwrite(bp); 990 else 991 bawrite(bp); 992 } 993 if (!allerror && error) 994 allerror = error; 995 return (allerror); 996 } 997