1 /* 2 * Copyright (c) 1989, 1991, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)lfs_vfsops.c 8.17 (Berkeley) 05/10/95 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/mount.h> 17 #include <sys/buf.h> 18 #include <sys/mbuf.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 #include <sys/socket.h> 25 26 #include <miscfs/specfs/specdev.h> 27 28 #include <ufs/ufs/quota.h> 29 #include <ufs/ufs/inode.h> 30 #include <ufs/ufs/ufsmount.h> 31 #include <ufs/ufs/ufs_extern.h> 32 33 #include <ufs/lfs/lfs.h> 34 #include <ufs/lfs/lfs_extern.h> 35 36 int lfs_mountfs __P((struct vnode *, struct mount *, struct proc *)); 37 38 struct vfsops lfs_vfsops = { 39 lfs_mount, 40 ufs_start, 41 lfs_unmount, 42 ufs_root, 43 ufs_quotactl, 44 lfs_statfs, 45 lfs_sync, 46 lfs_vget, 47 lfs_fhtovp, 48 lfs_vptofh, 49 lfs_init, 50 lfs_sysctl, 51 }; 52 53 /* 54 * Called by main() when ufs is going to be mounted as root. 55 */ 56 lfs_mountroot() 57 { 58 extern struct vnode *rootvp; 59 struct fs *fs; 60 struct mount *mp; 61 struct proc *p = curproc; /* XXX */ 62 int error; 63 64 /* 65 * Get vnodes for swapdev and rootdev. 66 */ 67 if ((error = bdevvp(swapdev, &swapdev_vp)) || 68 (error = bdevvp(rootdev, &rootvp))) { 69 printf("lfs_mountroot: can't setup bdevvp's"); 70 return (error); 71 } 72 if (error = vfs_rootmountalloc("lfs", "root_device", &mp)) 73 return (error); 74 if (error = lfs_mountfs(rootvp, mp, p)) { 75 mp->mnt_vfc->vfc_refcount--; 76 free(mp, M_MOUNT); 77 return (error); 78 } 79 if (error = vfs_lock(mp)) { 80 (void)lfs_unmount(mp, 0, p); 81 mp->mnt_vfc->vfc_refcount--; 82 free(mp, M_MOUNT); 83 return (error); 84 } 85 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); 86 (void)lfs_statfs(mp, &mp->mnt_stat, p); 87 vfs_unlock(mp); 88 return (0); 89 } 90 91 /* 92 * VFS Operations. 93 * 94 * mount system call 95 */ 96 lfs_mount(mp, path, data, ndp, p) 97 register struct mount *mp; 98 char *path; 99 caddr_t data; 100 struct nameidata *ndp; 101 struct proc *p; 102 { 103 struct vnode *devvp; 104 struct ufs_args args; 105 struct ufsmount *ump; 106 register struct lfs *fs; /* LFS */ 107 u_int size; 108 int error; 109 mode_t accessmode; 110 111 if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) 112 return (error); 113 114 /* Until LFS can do NFS right. XXX */ 115 if (args.export.ex_flags & MNT_EXPORTED) 116 return (EINVAL); 117 118 /* 119 * If updating, check whether changing from read-only to 120 * read/write; if there is no device name, that's all we do. 121 */ 122 if (mp->mnt_flag & MNT_UPDATE) { 123 ump = VFSTOUFS(mp); 124 if (fs->lfs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) { 125 /* 126 * If upgrade to read-write by non-root, then verify 127 * that user has necessary permissions on the device. 128 */ 129 if (p->p_ucred->cr_uid != 0) { 130 VOP_LOCK(ump->um_devvp); 131 if (error = VOP_ACCESS(ump->um_devvp, 132 VREAD | VWRITE, p->p_ucred, p)) { 133 VOP_UNLOCK(ump->um_devvp); 134 return (error); 135 } 136 VOP_UNLOCK(ump->um_devvp); 137 } 138 fs->lfs_ronly = 0; 139 } 140 if (args.fspec == 0) { 141 /* 142 * Process export requests. 143 */ 144 return (vfs_export(mp, &ump->um_export, &args.export)); 145 } 146 } 147 /* 148 * Not an update, or updating the name: look up the name 149 * and verify that it refers to a sensible block device. 150 */ 151 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); 152 if (error = namei(ndp)) 153 return (error); 154 devvp = ndp->ni_vp; 155 if (devvp->v_type != VBLK) { 156 vrele(devvp); 157 return (ENOTBLK); 158 } 159 if (major(devvp->v_rdev) >= nblkdev) { 160 vrele(devvp); 161 return (ENXIO); 162 } 163 /* 164 * If mount by non-root, then verify that user has necessary 165 * permissions on the device. 166 */ 167 if (p->p_ucred->cr_uid != 0) { 168 accessmode = VREAD; 169 if ((mp->mnt_flag & MNT_RDONLY) == 0) 170 accessmode |= VWRITE; 171 VOP_LOCK(devvp); 172 if (error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) { 173 vput(devvp); 174 return (error); 175 } 176 VOP_UNLOCK(devvp); 177 } 178 if ((mp->mnt_flag & MNT_UPDATE) == 0) 179 error = lfs_mountfs(devvp, mp, p); /* LFS */ 180 else { 181 if (devvp != ump->um_devvp) 182 error = EINVAL; /* needs translation */ 183 else 184 vrele(devvp); 185 } 186 if (error) { 187 vrele(devvp); 188 return (error); 189 } 190 ump = VFSTOUFS(mp); 191 fs = ump->um_lfs; /* LFS */ 192 #ifdef NOTLFS /* LFS */ 193 (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 194 bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 195 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 196 MNAMELEN); 197 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 198 &size); 199 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 200 (void) ufs_statfs(mp, &mp->mnt_stat, p); 201 #else 202 (void)copyinstr(path, fs->lfs_fsmnt, sizeof(fs->lfs_fsmnt) - 1, &size); 203 bzero(fs->lfs_fsmnt + size, sizeof(fs->lfs_fsmnt) - size); 204 bcopy((caddr_t)fs->lfs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 205 MNAMELEN); 206 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 207 &size); 208 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 209 (void) lfs_statfs(mp, &mp->mnt_stat, p); 210 #endif 211 return (0); 212 } 213 214 /* 215 * Common code for mount and mountroot 216 * LFS specific 217 */ 218 int 219 lfs_mountfs(devvp, mp, p) 220 register struct vnode *devvp; 221 struct mount *mp; 222 struct proc *p; 223 { 224 extern struct vnode *rootvp; 225 register struct lfs *fs; 226 register struct ufsmount *ump; 227 struct vnode *vp; 228 struct buf *bp; 229 struct partinfo dpart; 230 dev_t dev; 231 int error, i, ronly, size; 232 struct ucred *cred; 233 234 cred = p ? p->p_ucred : NOCRED; 235 /* 236 * Disallow multiple mounts of the same device. 237 * Disallow mounting of a device that is currently in use 238 * (except for root, which might share swap device for miniroot). 239 * Flush out any old buffers remaining from a previous use. 240 */ 241 if (error = vfs_mountedon(devvp)) 242 return (error); 243 if (vcount(devvp) > 1 && devvp != rootvp) 244 return (EBUSY); 245 if (error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0)) 246 return (error); 247 248 ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 249 if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p)) 250 return (error); 251 252 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0) 253 size = DEV_BSIZE; 254 else { 255 size = dpart.disklab->d_secsize; 256 #ifdef NEVER_USED 257 dpart.part->p_fstype = FS_LFS; 258 dpart.part->p_fsize = fs->lfs_fsize; /* frag size */ 259 dpart.part->p_frag = fs->lfs_frag; /* frags per block */ 260 dpart.part->p_cpg = fs->lfs_segshift; /* segment shift */ 261 #endif 262 } 263 264 /* Don't free random space on error. */ 265 bp = NULL; 266 ump = NULL; 267 268 /* Read in the superblock. */ 269 if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, cred, &bp)) 270 goto out; 271 fs = (struct lfs *)bp->b_data; 272 273 /* Check the basics. */ 274 if (fs->lfs_magic != LFS_MAGIC || fs->lfs_bsize > MAXBSIZE || 275 fs->lfs_bsize < sizeof(struct lfs)) { 276 error = EINVAL; /* XXX needs translation */ 277 goto out; 278 } 279 280 /* Allocate the mount structure, copy the superblock into it. */ 281 ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK); 282 fs = ump->um_lfs = malloc(sizeof(struct lfs), M_UFSMNT, M_WAITOK); 283 bcopy(bp->b_data, fs, sizeof(struct lfs)); 284 if (sizeof(struct lfs) < LFS_SBPAD) /* XXX why? */ 285 bp->b_flags |= B_INVAL; 286 brelse(bp); 287 bp = NULL; 288 289 /* Set up the I/O information */ 290 fs->lfs_iocount = 0; 291 292 /* Set up the ifile and lock aflags */ 293 fs->lfs_doifile = 0; 294 fs->lfs_writer = 0; 295 fs->lfs_dirops = 0; 296 fs->lfs_seglock = 0; 297 298 /* Set the file system readonly/modify bits. */ 299 fs->lfs_ronly = ronly; 300 if (ronly == 0) 301 fs->lfs_fmod = 1; 302 303 /* Initialize the mount structure. */ 304 dev = devvp->v_rdev; 305 mp->mnt_data = (qaddr_t)ump; 306 mp->mnt_stat.f_fsid.val[0] = (long)dev; 307 mp->mnt_stat.f_fsid.val[1] = lfs_mount_type; 308 mp->mnt_maxsymlinklen = fs->lfs_maxsymlinklen; 309 mp->mnt_flag |= MNT_LOCAL; 310 ump->um_mountp = mp; 311 ump->um_dev = dev; 312 ump->um_devvp = devvp; 313 ump->um_bptrtodb = 0; 314 ump->um_seqinc = 1 << fs->lfs_fsbtodb; 315 ump->um_nindir = fs->lfs_nindir; 316 for (i = 0; i < MAXQUOTAS; i++) 317 ump->um_quotas[i] = NULLVP; 318 devvp->v_specflags |= SI_MOUNTEDON; 319 320 /* 321 * We use the ifile vnode for almost every operation. Instead of 322 * retrieving it from the hash table each time we retrieve it here, 323 * artificially increment the reference count and keep a pointer 324 * to it in the incore copy of the superblock. 325 */ 326 if (error = VFS_VGET(mp, LFS_IFILE_INUM, &vp)) 327 goto out; 328 fs->lfs_ivnode = vp; 329 VREF(vp); 330 vput(vp); 331 332 return (0); 333 out: 334 if (bp) 335 brelse(bp); 336 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p); 337 if (ump) { 338 free(ump->um_lfs, M_UFSMNT); 339 free(ump, M_UFSMNT); 340 mp->mnt_data = (qaddr_t)0; 341 } 342 return (error); 343 } 344 345 /* 346 * unmount system call 347 */ 348 lfs_unmount(mp, mntflags, p) 349 struct mount *mp; 350 int mntflags; 351 struct proc *p; 352 { 353 extern int doforce; 354 register struct ufsmount *ump; 355 register struct lfs *fs; 356 int i, error, flags, ronly; 357 358 flags = 0; 359 if (mntflags & MNT_FORCE) 360 flags |= FORCECLOSE; 361 362 ump = VFSTOUFS(mp); 363 fs = ump->um_lfs; 364 #ifdef QUOTA 365 if (mp->mnt_flag & MNT_QUOTA) { 366 if (error = vflush(mp, fs->lfs_ivnode, SKIPSYSTEM|flags)) 367 return (error); 368 for (i = 0; i < MAXQUOTAS; i++) { 369 if (ump->um_quotas[i] == NULLVP) 370 continue; 371 quotaoff(p, mp, i); 372 } 373 /* 374 * Here we fall through to vflush again to ensure 375 * that we have gotten rid of all the system vnodes. 376 */ 377 } 378 #endif 379 if (error = vflush(mp, fs->lfs_ivnode, flags)) 380 return (error); 381 fs->lfs_clean = 1; 382 if (error = VFS_SYNC(mp, 1, p->p_ucred, p)) 383 return (error); 384 if (fs->lfs_ivnode->v_dirtyblkhd.lh_first) 385 panic("lfs_unmount: still dirty blocks on ifile vnode\n"); 386 vrele(fs->lfs_ivnode); 387 vgone(fs->lfs_ivnode); 388 389 ronly = !fs->lfs_ronly; 390 ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; 391 error = VOP_CLOSE(ump->um_devvp, 392 ronly ? FREAD : FREAD|FWRITE, NOCRED, p); 393 vrele(ump->um_devvp); 394 free(fs, M_UFSMNT); 395 free(ump, M_UFSMNT); 396 mp->mnt_data = (qaddr_t)0; 397 mp->mnt_flag &= ~MNT_LOCAL; 398 return (error); 399 } 400 401 /* 402 * Get file system statistics. 403 */ 404 lfs_statfs(mp, sbp, p) 405 struct mount *mp; 406 register struct statfs *sbp; 407 struct proc *p; 408 { 409 register struct lfs *fs; 410 register struct ufsmount *ump; 411 412 ump = VFSTOUFS(mp); 413 fs = ump->um_lfs; 414 if (fs->lfs_magic != LFS_MAGIC) 415 panic("lfs_statfs: magic"); 416 sbp->f_bsize = fs->lfs_bsize; 417 sbp->f_iosize = fs->lfs_bsize; 418 sbp->f_blocks = dbtofsb(fs,fs->lfs_dsize); 419 sbp->f_bfree = dbtofsb(fs, fs->lfs_bfree); 420 /* 421 * To compute the available space. Subtract the minimum free 422 * from the total number of blocks in the file system. Set avail 423 * to the smaller of this number and fs->lfs_bfree. 424 */ 425 sbp->f_bavail = fs->lfs_dsize * (100 - fs->lfs_minfree) / 100; 426 sbp->f_bavail = 427 sbp->f_bavail > fs->lfs_bfree ? fs->lfs_bfree : sbp->f_bavail; 428 sbp->f_bavail = dbtofsb(fs, sbp->f_bavail); 429 sbp->f_files = fs->lfs_nfiles; 430 sbp->f_ffree = sbp->f_bfree * INOPB(fs); 431 if (sbp != &mp->mnt_stat) { 432 sbp->f_type = mp->mnt_vfc->vfc_typenum; 433 bcopy((caddr_t)mp->mnt_stat.f_mntonname, 434 (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 435 bcopy((caddr_t)mp->mnt_stat.f_mntfromname, 436 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 437 } 438 return (0); 439 } 440 441 /* 442 * Go through the disk queues to initiate sandbagged IO; 443 * go through the inodes to write those that have been modified; 444 * initiate the writing of the super block if it has been modified. 445 * 446 * Note: we are always called with the filesystem marked `MPBUSY'. 447 */ 448 lfs_sync(mp, waitfor, cred, p) 449 struct mount *mp; 450 int waitfor; 451 struct ucred *cred; 452 struct proc *p; 453 { 454 int error; 455 456 /* All syncs must be checkpoints until roll-forward is implemented. */ 457 error = lfs_segwrite(mp, SEGM_CKP | (waitfor ? SEGM_SYNC : 0)); 458 #ifdef QUOTA 459 qsync(mp); 460 #endif 461 return (error); 462 } 463 464 /* 465 * Look up an LFS dinode number to find its incore vnode. If not already 466 * in core, read it in from the specified device. Return the inode locked. 467 * Detection and handling of mount points must be done by the calling routine. 468 */ 469 int 470 lfs_vget(mp, ino, vpp) 471 struct mount *mp; 472 ino_t ino; 473 struct vnode **vpp; 474 { 475 register struct lfs *fs; 476 register struct inode *ip; 477 struct buf *bp; 478 struct ifile *ifp; 479 struct vnode *vp; 480 struct ufsmount *ump; 481 ufs_daddr_t daddr; 482 dev_t dev; 483 int error; 484 485 ump = VFSTOUFS(mp); 486 dev = ump->um_dev; 487 if ((*vpp = ufs_ihashget(dev, ino)) != NULL) 488 return (0); 489 490 /* Translate the inode number to a disk address. */ 491 fs = ump->um_lfs; 492 if (ino == LFS_IFILE_INUM) 493 daddr = fs->lfs_idaddr; 494 else { 495 LFS_IENTRY(ifp, fs, ino, bp); 496 daddr = ifp->if_daddr; 497 brelse(bp); 498 if (daddr == LFS_UNUSED_DADDR) 499 return (ENOENT); 500 } 501 502 /* Allocate new vnode/inode. */ 503 if (error = lfs_vcreate(mp, ino, &vp)) { 504 *vpp = NULL; 505 return (error); 506 } 507 508 /* 509 * Put it onto its hash chain and lock it so that other requests for 510 * this inode will block if they arrive while we are sleeping waiting 511 * for old data structures to be purged or for the contents of the 512 * disk portion of this inode to be read. 513 */ 514 ip = VTOI(vp); 515 ufs_ihashins(ip); 516 517 /* 518 * XXX 519 * This may not need to be here, logically it should go down with 520 * the i_devvp initialization. 521 * Ask Kirk. 522 */ 523 ip->i_lfs = ump->um_lfs; 524 525 /* Read in the disk contents for the inode, copy into the inode. */ 526 if (error = 527 bread(ump->um_devvp, daddr, (int)fs->lfs_bsize, NOCRED, &bp)) { 528 /* 529 * The inode does not contain anything useful, so it would 530 * be misleading to leave it on its hash chain. With mode 531 * still zero, it will be unlinked and returned to the free 532 * list by vput(). 533 */ 534 vput(vp); 535 brelse(bp); 536 *vpp = NULL; 537 return (error); 538 } 539 ip->i_din = *lfs_ifind(fs, ino, (struct dinode *)bp->b_data); 540 brelse(bp); 541 542 /* 543 * Initialize the vnode from the inode, check for aliases. In all 544 * cases re-init ip, the underlying vnode/inode may have changed. 545 */ 546 if (error = ufs_vinit(mp, lfs_specop_p, LFS_FIFOOPS, &vp)) { 547 vput(vp); 548 *vpp = NULL; 549 return (error); 550 } 551 /* 552 * Finish inode initialization now that aliasing has been resolved. 553 */ 554 ip->i_devvp = ump->um_devvp; 555 VREF(ip->i_devvp); 556 *vpp = vp; 557 return (0); 558 } 559 560 /* 561 * File handle to vnode 562 * 563 * Have to be really careful about stale file handles: 564 * - check that the inode number is valid 565 * - call lfs_vget() to get the locked inode 566 * - check for an unallocated inode (i_mode == 0) 567 * - check that the given client host has export rights and return 568 * those rights via. exflagsp and credanonp 569 * 570 * XXX 571 * use ifile to see if inode is allocated instead of reading off disk 572 * what is the relationship between my generational number and the NFS 573 * generational number. 574 */ 575 int 576 lfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) 577 register struct mount *mp; 578 struct fid *fhp; 579 struct mbuf *nam; 580 struct vnode **vpp; 581 int *exflagsp; 582 struct ucred **credanonp; 583 { 584 register struct ufid *ufhp; 585 586 ufhp = (struct ufid *)fhp; 587 if (ufhp->ufid_ino < ROOTINO) 588 return (ESTALE); 589 return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp)); 590 } 591 592 /* 593 * Vnode pointer to File handle 594 */ 595 /* ARGSUSED */ 596 lfs_vptofh(vp, fhp) 597 struct vnode *vp; 598 struct fid *fhp; 599 { 600 register struct inode *ip; 601 register struct ufid *ufhp; 602 603 ip = VTOI(vp); 604 ufhp = (struct ufid *)fhp; 605 ufhp->ufid_len = sizeof(struct ufid); 606 ufhp->ufid_ino = ip->i_number; 607 ufhp->ufid_gen = ip->i_gen; 608 return (0); 609 } 610 611 /* 612 * Initialize the filesystem, most work done by ufs_init. 613 */ 614 int lfs_mount_type; 615 616 int 617 lfs_init(vfsp) 618 struct vfsconf *vfsp; 619 { 620 621 lfs_mount_type = vfsp->vfc_typenum; 622 return (ufs_init(vfsp)); 623 } 624