1 /* 2 * Copyright (c) 1989, 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)ffs_vfsops.c 7.61 (Berkeley) 01/13/92 8 */ 9 10 #include <sys/param.h> 11 #include <sys/systm.h> 12 #include <sys/namei.h> 13 #include <sys/proc.h> 14 #include <sys/kernel.h> 15 #include <sys/vnode.h> 16 #include <sys/specdev.h> 17 #include <sys/mount.h> 18 #include <sys/buf.h> 19 #include <sys/file.h> 20 #include <sys/disklabel.h> 21 #include <sys/ioctl.h> 22 #include <sys/errno.h> 23 #include <sys/malloc.h> 24 25 #include <ufs/ufs/quota.h> 26 #include <ufs/ufs/ufsmount.h> 27 #include <ufs/ufs/inode.h> 28 #include <ufs/ufs/ufs_extern.h> 29 30 #include <ufs/ffs/fs.h> 31 #include <ufs/ffs/ffs_extern.h> 32 33 int ffs_sbupdate __P((struct ufsmount *, int)); 34 35 struct vfsops ufs_vfsops = { 36 ffs_mount, 37 ufs_start, 38 ffs_unmount, 39 ffs_root, 40 ufs_quotactl, 41 ffs_statfs, 42 ffs_sync, 43 ffs_fhtovp, 44 ffs_vptofh, 45 ffs_init, 46 }; 47 48 /* 49 * Called by vfs_mountroot when ufs is going to be mounted as root. 50 * 51 * Name is updated by mount(8) after booting. 52 */ 53 #define ROOTNAME "root_device" 54 55 ffs_mountroot() 56 { 57 extern struct vnode *rootvp; 58 register struct fs *fs; 59 register struct mount *mp; 60 struct proc *p = curproc; /* XXX */ 61 struct ufsmount *ump; 62 u_int size; 63 int error; 64 65 mp = malloc((u_long)sizeof(struct mount), 66 M_MOUNT, M_WAITOK); 67 mp->mnt_op = &ufs_vfsops; 68 mp->mnt_flag = MNT_RDONLY; 69 mp->mnt_mounth = NULLVP; 70 if (error = ffs_mountfs(rootvp, mp, p)) { 71 free(mp, M_MOUNT); 72 return (error); 73 } 74 if (error = vfs_lock(mp)) { 75 (void)ffs_unmount(mp, 0, p); 76 free(mp, M_MOUNT); 77 return (error); 78 } 79 rootfs = mp; 80 mp->mnt_next = mp; 81 mp->mnt_prev = mp; 82 mp->mnt_vnodecovered = NULLVP; 83 ump = VFSTOUFS(mp); 84 fs = ump->um_fs; 85 bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt)); 86 fs->fs_fsmnt[0] = '/'; 87 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 88 MNAMELEN); 89 (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 90 &size); 91 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 92 (void)ffs_statfs(mp, &mp->mnt_stat, p); 93 vfs_unlock(mp); 94 inittodr(fs->fs_time); 95 return (0); 96 } 97 98 /* 99 * VFS Operations. 100 * 101 * mount system call 102 */ 103 int 104 ffs_mount(mp, path, data, ndp, p) 105 register struct mount *mp; 106 char *path; 107 caddr_t data; 108 struct nameidata *ndp; 109 struct proc *p; 110 { 111 struct vnode *devvp; 112 struct ufs_args args; 113 struct ufsmount *ump; 114 register struct fs *fs; 115 u_int size; 116 int error; 117 118 if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) 119 return (error); 120 /* 121 * If updating, check whether changing from read-only to 122 * read/write; if there is no device name, that's all we do. 123 */ 124 if (mp->mnt_flag & MNT_UPDATE) { 125 ump = VFSTOUFS(mp); 126 fs = ump->um_fs; 127 if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0) 128 fs->fs_ronly = 0; 129 if (args.fspec == 0) { 130 /* 131 * Process export requests. 132 */ 133 if (args.exflags & MNT_EXPORTED) { 134 if (error = hang_addrlist(mp, &args)) 135 return (error); 136 mp->mnt_flag |= MNT_EXPORTED; 137 } 138 if (args.exflags & MNT_DELEXPORT) { 139 free_addrlist(ump); 140 mp->mnt_flag &= 141 ~(MNT_EXPORTED | MNT_DEFEXPORTED); 142 } 143 return (0); 144 } 145 } 146 /* 147 * Not an update, or updating the name: look up the name 148 * and verify that it refers to a sensible block device. 149 */ 150 ndp->ni_nameiop = LOOKUP | FOLLOW; 151 ndp->ni_segflg = UIO_USERSPACE; 152 ndp->ni_dirp = args.fspec; 153 if (error = namei(ndp, p)) 154 return (error); 155 devvp = ndp->ni_vp; 156 157 if (devvp->v_type != VBLK) { 158 vrele(devvp); 159 return (ENOTBLK); 160 } 161 if (major(devvp->v_rdev) >= nblkdev) { 162 vrele(devvp); 163 return (ENXIO); 164 } 165 if ((mp->mnt_flag & MNT_UPDATE) == 0) 166 error = ffs_mountfs(devvp, mp, p); 167 else { 168 if (devvp != ump->um_devvp) 169 error = EINVAL; /* needs translation */ 170 else 171 vrele(devvp); 172 } 173 if (error) { 174 vrele(devvp); 175 return (error); 176 } 177 ump = VFSTOUFS(mp); 178 fs = ump->um_fs; 179 (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 180 bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 181 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 182 MNAMELEN); 183 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 184 &size); 185 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 186 (void)ffs_statfs(mp, &mp->mnt_stat, p); 187 return (0); 188 } 189 190 /* 191 * Common code for mount and mountroot 192 */ 193 int 194 ffs_mountfs(devvp, mp, p) 195 register struct vnode *devvp; 196 struct mount *mp; 197 struct proc *p; 198 { 199 register struct ufsmount *ump = (struct ufsmount *)0; 200 struct buf *bp = NULL; 201 register struct fs *fs; 202 dev_t dev = devvp->v_rdev; 203 struct partinfo dpart; 204 caddr_t base, space; 205 int havepart = 0, blks; 206 int error, i, size; 207 int needclose = 0; 208 int ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 209 extern struct vnode *rootvp; 210 211 /* 212 * Disallow multiple mounts of the same device. 213 * Disallow mounting of a device that is currently in use 214 * (except for root, which might share swap device for miniroot). 215 * Flush out any old buffers remaining from a previous use. 216 */ 217 if (error = ufs_mountedon(devvp)) 218 return (error); 219 if (vcount(devvp) > 1 && devvp != rootvp) 220 return (EBUSY); 221 vinvalbuf(devvp, 1); 222 if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p)) 223 return (error); 224 needclose = 1; 225 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0) 226 size = DEV_BSIZE; 227 else { 228 havepart = 1; 229 size = dpart.disklab->d_secsize; 230 } 231 if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) 232 goto out; 233 fs = bp->b_un.b_fs; 234 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 235 fs->fs_bsize < sizeof(struct fs)) { 236 error = EINVAL; /* XXX needs translation */ 237 goto out; 238 } 239 ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK); 240 ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT, 241 M_WAITOK); 242 bcopy((caddr_t)bp->b_un.b_addr, (caddr_t)ump->um_fs, 243 (u_int)fs->fs_sbsize); 244 if (fs->fs_sbsize < SBSIZE) 245 bp->b_flags |= B_INVAL; 246 brelse(bp); 247 bp = NULL; 248 fs = ump->um_fs; 249 fs->fs_ronly = ronly; 250 if (ronly == 0) 251 fs->fs_fmod = 1; 252 if (havepart) { 253 dpart.part->p_fstype = FS_BSDFFS; 254 dpart.part->p_fsize = fs->fs_fsize; 255 dpart.part->p_frag = fs->fs_frag; 256 dpart.part->p_cpg = fs->fs_cpg; 257 } 258 blks = howmany(fs->fs_cssize, fs->fs_fsize); 259 base = space = malloc((u_long)fs->fs_cssize, M_UFSMNT, 260 M_WAITOK); 261 for (i = 0; i < blks; i += fs->fs_frag) { 262 size = fs->fs_bsize; 263 if (i + fs->fs_frag > blks) 264 size = (blks - i) * fs->fs_fsize; 265 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, 266 NOCRED, &bp); 267 if (error) { 268 free(base, M_UFSMNT); 269 goto out; 270 } 271 bcopy((caddr_t)bp->b_un.b_addr, space, (u_int)size); 272 fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space; 273 space += size; 274 brelse(bp); 275 bp = NULL; 276 } 277 mp->mnt_data = (qaddr_t)ump; 278 mp->mnt_stat.f_fsid.val[0] = (long)dev; 279 mp->mnt_stat.f_fsid.val[1] = MOUNT_UFS; 280 mp->mnt_flag |= MNT_LOCAL; 281 ump->um_mountp = mp; 282 ump->um_dev = dev; 283 ump->um_devvp = devvp; 284 for (i = 0; i < MAXQUOTAS; i++) 285 ump->um_quotas[i] = NULLVP; 286 devvp->v_specflags |= SI_MOUNTEDON; 287 288 /* Sanity checks for old file systems. XXX */ 289 fs->fs_npsect = MAX(fs->fs_npsect, fs->fs_nsect); /* XXX */ 290 fs->fs_interleave = MAX(fs->fs_interleave, 1); /* XXX */ 291 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 292 fs->fs_nrpos = 8; /* XXX */ 293 return (0); 294 out: 295 if (bp) 296 brelse(bp); 297 if (needclose) 298 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); 299 if (ump) { 300 free(ump->um_fs, M_UFSMNT); 301 free(ump, M_UFSMNT); 302 mp->mnt_data = (qaddr_t)0; 303 } 304 return (error); 305 } 306 307 /* 308 * unmount system call 309 */ 310 int 311 ffs_unmount(mp, mntflags, p) 312 struct mount *mp; 313 int mntflags; 314 struct proc *p; 315 { 316 extern int doforce; 317 register struct ufsmount *ump; 318 register struct fs *fs; 319 int i, error, ronly, flags = 0; 320 321 if (mntflags & MNT_FORCE) { 322 if (!doforce || mp == rootfs) 323 return (EINVAL); 324 flags |= FORCECLOSE; 325 } 326 mntflushbuf(mp, 0); 327 if (mntinvalbuf(mp)) 328 return (EBUSY); 329 ump = VFSTOUFS(mp); 330 #ifdef QUOTA 331 if (mp->mnt_flag & MNT_QUOTA) { 332 if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) 333 return (error); 334 for (i = 0; i < MAXQUOTAS; i++) { 335 if (ump->um_quotas[i] == NULLVP) 336 continue; 337 quotaoff(p, mp, i); 338 } 339 /* 340 * Here we fall through to vflush again to ensure 341 * that we have gotten rid of all the system vnodes. 342 */ 343 } 344 #endif 345 if (error = vflush(mp, NULLVP, flags)) 346 return (error); 347 fs = ump->um_fs; 348 ronly = !fs->fs_ronly; 349 ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; 350 error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE, 351 NOCRED, p); 352 vrele(ump->um_devvp); 353 free(fs->fs_csp[0], M_UFSMNT); 354 free(fs, M_UFSMNT); 355 free(ump, M_UFSMNT); 356 mp->mnt_data = (qaddr_t)0; 357 mp->mnt_flag &= ~MNT_LOCAL; 358 return (error); 359 } 360 361 /* 362 * Return root of a filesystem 363 */ 364 int 365 ffs_root(mp, vpp) 366 struct mount *mp; 367 struct vnode **vpp; 368 { 369 struct vnode *nvp; 370 int error; 371 372 if (error = ffs_vget(mp, (ino_t)ROOTINO, &nvp)) 373 return (error); 374 *vpp = nvp; 375 return (0); 376 } 377 378 /* 379 * Get file system statistics. 380 */ 381 int 382 ffs_statfs(mp, sbp, p) 383 struct mount *mp; 384 register struct statfs *sbp; 385 struct proc *p; 386 { 387 register struct ufsmount *ump; 388 register struct fs *fs; 389 390 ump = VFSTOUFS(mp); 391 fs = ump->um_fs; 392 if (fs->fs_magic != FS_MAGIC) 393 panic("ffs_statfs"); 394 sbp->f_type = MOUNT_UFS; 395 sbp->f_bsize = fs->fs_fsize; 396 sbp->f_iosize = fs->fs_bsize; 397 sbp->f_blocks = fs->fs_dsize; 398 sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + 399 fs->fs_cstotal.cs_nffree; 400 sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) - 401 (fs->fs_dsize - sbp->f_bfree); 402 sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO; 403 sbp->f_ffree = fs->fs_cstotal.cs_nifree; 404 if (sbp != &mp->mnt_stat) { 405 bcopy((caddr_t)mp->mnt_stat.f_mntonname, 406 (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 407 bcopy((caddr_t)mp->mnt_stat.f_mntfromname, 408 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 409 } 410 return (0); 411 } 412 413 /* 414 * Go through the disk queues to initiate sandbagged IO; 415 * go through the inodes to write those that have been modified; 416 * initiate the writing of the super block if it has been modified. 417 * 418 * Note: we are always called with the filesystem marked `MPBUSY'. 419 */ 420 int 421 ffs_sync(mp, waitfor) 422 struct mount *mp; 423 int waitfor; 424 { 425 extern int syncprt; 426 register struct vnode *vp; 427 register struct inode *ip; 428 register struct ufsmount *ump = VFSTOUFS(mp); 429 register struct fs *fs; 430 int error, allerror = 0; 431 432 if (syncprt) 433 ufs_bufstats(); 434 fs = ump->um_fs; 435 /* 436 * Write back modified superblock. 437 * Consistency check that the superblock 438 * is still in the buffer cache. 439 */ 440 if (fs->fs_fmod != 0) { 441 if (fs->fs_ronly != 0) { /* XXX */ 442 printf("fs = %s\n", fs->fs_fsmnt); 443 panic("update: rofs mod"); 444 } 445 fs->fs_fmod = 0; 446 fs->fs_time = time.tv_sec; 447 allerror = ffs_sbupdate(ump, waitfor); 448 } 449 /* 450 * Write back each (modified) inode. 451 */ 452 loop: 453 for (vp = mp->mnt_mounth; vp; vp = vp->v_mountf) { 454 /* 455 * If the vnode that we are about to sync is no longer 456 * associated with this mount point, start over. 457 */ 458 if (vp->v_mount != mp) 459 goto loop; 460 if (VOP_ISLOCKED(vp)) 461 continue; 462 ip = VTOI(vp); 463 if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0 && 464 vp->v_dirtyblkhd == NULL) 465 continue; 466 if (vget(vp)) 467 goto loop; 468 if (vp->v_dirtyblkhd) 469 vflushbuf(vp, 0); 470 if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) && 471 (error = ffs_update(vp, &time, &time, 0))) 472 allerror = error; 473 vput(vp); 474 } 475 /* 476 * Force stale file system control information to be flushed. 477 */ 478 vflushbuf(ump->um_devvp, waitfor == MNT_WAIT ? B_SYNC : 0); 479 #ifdef QUOTA 480 qsync(mp); 481 #endif 482 return (allerror); 483 } 484 485 /* 486 * File handle to vnode 487 * 488 * Have to be really careful about stale file handles: 489 * - check that the inode number is valid 490 * - call ffs_vget() to get the locked inode 491 * - check for an unallocated inode (i_mode == 0) 492 * - check that the generation number matches unless setgen true 493 */ 494 int 495 ffs_fhtovp(mp, fhp, setgen, vpp) 496 register struct mount *mp; 497 struct fid *fhp; 498 int setgen; 499 struct vnode **vpp; 500 { 501 register struct inode *ip; 502 register struct ufid *ufhp; 503 struct fs *fs; 504 struct vnode *nvp; 505 int error; 506 507 ufhp = (struct ufid *)fhp; 508 fs = VFSTOUFS(mp)->um_fs; 509 if (ufhp->ufid_ino < ROOTINO || 510 ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) 511 return (EINVAL); 512 if (error = ffs_vget(mp, ufhp->ufid_ino, &nvp)) { 513 *vpp = NULLVP; 514 return (error); 515 } 516 ip = VTOI(nvp); 517 if (ip->i_mode == 0) { 518 ufs_iput(ip); 519 *vpp = NULLVP; 520 return (EINVAL); 521 } 522 if (ip->i_gen != ufhp->ufid_gen) { 523 if (setgen) 524 ufhp->ufid_gen = ip->i_gen; 525 else { 526 ufs_iput(ip); 527 *vpp = NULLVP; 528 return (EINVAL); 529 } 530 } 531 *vpp = nvp; 532 return (0); 533 } 534 535 /* 536 * Vnode pointer to File handle 537 */ 538 /* ARGSUSED */ 539 ffs_vptofh(vp, fhp) 540 struct vnode *vp; 541 struct fid *fhp; 542 { 543 register struct inode *ip; 544 register struct ufid *ufhp; 545 546 ip = VTOI(vp); 547 ufhp = (struct ufid *)fhp; 548 ufhp->ufid_len = sizeof(struct ufid); 549 ufhp->ufid_ino = ip->i_number; 550 ufhp->ufid_gen = ip->i_gen; 551 return (0); 552 } 553 554 /* 555 * Write a superblock and associated information back to disk. 556 */ 557 int 558 ffs_sbupdate(mp, waitfor) 559 struct ufsmount *mp; 560 int waitfor; 561 { 562 register struct fs *fs = mp->um_fs; 563 register struct buf *bp; 564 int blks; 565 caddr_t space; 566 int i, size, error = 0; 567 568 bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize); 569 bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize); 570 /* Restore compatibility to old file systems. XXX */ 571 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 572 bp->b_un.b_fs->fs_nrpos = -1; /* XXX */ 573 if (waitfor == MNT_WAIT) 574 error = bwrite(bp); 575 else 576 bawrite(bp); 577 blks = howmany(fs->fs_cssize, fs->fs_fsize); 578 space = (caddr_t)fs->fs_csp[0]; 579 for (i = 0; i < blks; i += fs->fs_frag) { 580 size = fs->fs_bsize; 581 if (i + fs->fs_frag > blks) 582 size = (blks - i) * fs->fs_fsize; 583 bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), size); 584 bcopy(space, bp->b_un.b_addr, (u_int)size); 585 space += size; 586 if (waitfor == MNT_WAIT) 587 error = bwrite(bp); 588 else 589 bawrite(bp); 590 } 591 return (error); 592 } 593