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