1 /* 2 * Copyright (c) 1989 The 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 * @(#)lfs_vfsops.c 7.41 (Berkeley) 05/04/90 18 */ 19 20 #include "param.h" 21 #include "systm.h" 22 #include "user.h" 23 #include "proc.h" 24 #include "kernel.h" 25 #include "vnode.h" 26 #include "specdev.h" 27 #include "mount.h" 28 #include "buf.h" 29 #include "file.h" 30 #include "disklabel.h" 31 #include "ioctl.h" 32 #include "errno.h" 33 #include "malloc.h" 34 #include "../ufs/quota.h" 35 #include "../ufs/fs.h" 36 #include "../ufs/ufsmount.h" 37 #include "../ufs/inode.h" 38 39 /* 40 * ufs vfs operations. 41 */ 42 int ufs_mount(); 43 int ufs_start(); 44 int ufs_unmount(); 45 int ufs_root(); 46 int ufs_quotactl(); 47 int ufs_statfs(); 48 int ufs_sync(); 49 int ufs_fhtovp(); 50 int ufs_vptofh(); 51 int ufs_init(); 52 53 struct vfsops ufs_vfsops = { 54 ufs_mount, 55 ufs_start, 56 ufs_unmount, 57 ufs_root, 58 ufs_quotactl, 59 ufs_statfs, 60 ufs_sync, 61 ufs_fhtovp, 62 ufs_vptofh, 63 ufs_init 64 }; 65 66 /* 67 * Called by vfs_mountroot when ufs is going to be mounted as root. 68 * 69 * Name is updated by mount(8) after booting. 70 */ 71 #define ROOTNAME "root_device" 72 73 ufs_mountroot() 74 { 75 register struct mount *mp; 76 extern struct vnode *rootvp; 77 struct ufsmount *ump; 78 register struct fs *fs; 79 u_int size; 80 int error; 81 82 mp = (struct mount *)malloc((u_long)sizeof(struct mount), 83 M_MOUNT, M_WAITOK); 84 mp->mnt_op = &ufs_vfsops; 85 mp->mnt_flag = MNT_RDONLY; 86 mp->mnt_exroot = 0; 87 mp->mnt_mounth = NULLVP; 88 error = mountfs(rootvp, mp); 89 if (error) { 90 free((caddr_t)mp, M_MOUNT); 91 return (error); 92 } 93 if (error = vfs_lock(mp)) { 94 (void)ufs_unmount(mp, 0); 95 free((caddr_t)mp, M_MOUNT); 96 return (error); 97 } 98 rootfs = mp; 99 mp->mnt_next = mp; 100 mp->mnt_prev = mp; 101 mp->mnt_vnodecovered = NULLVP; 102 ump = VFSTOUFS(mp); 103 fs = ump->um_fs; 104 bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt)); 105 fs->fs_fsmnt[0] = '/'; 106 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 107 MNAMELEN); 108 (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 109 &size); 110 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 111 (void) ufs_statfs(mp, &mp->mnt_stat); 112 vfs_unlock(mp); 113 inittodr(fs->fs_time); 114 return (0); 115 } 116 117 /* 118 * VFS Operations. 119 * 120 * mount system call 121 */ 122 ufs_mount(mp, path, data, ndp) 123 register struct mount *mp; 124 char *path; 125 caddr_t data; 126 struct nameidata *ndp; 127 { 128 struct vnode *devvp; 129 struct ufs_args args; 130 struct ufsmount *ump; 131 register struct fs *fs; 132 u_int size; 133 int error; 134 135 if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) 136 return (error); 137 /* 138 * Process export requests. 139 */ 140 if ((args.exflags & MNT_EXPORTED) || (mp->mnt_flag & MNT_EXPORTED)) { 141 if (args.exflags & MNT_EXPORTED) 142 mp->mnt_flag |= MNT_EXPORTED; 143 else 144 mp->mnt_flag &= ~MNT_EXPORTED; 145 if (args.exflags & MNT_EXRDONLY) 146 mp->mnt_flag |= MNT_EXRDONLY; 147 else 148 mp->mnt_flag &= ~MNT_EXRDONLY; 149 mp->mnt_exroot = args.exroot; 150 } 151 if ((mp->mnt_flag & MNT_UPDATE) == 0) { 152 if ((error = getmdev(&devvp, args.fspec, ndp)) != 0) 153 return (error); 154 error = mountfs(devvp, mp); 155 } else { 156 ump = VFSTOUFS(mp); 157 fs = ump->um_fs; 158 if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0) 159 fs->fs_ronly = 0; 160 /* 161 * Verify that the specified device is the one that 162 * is really being used for the root file system. 163 */ 164 if (args.fspec == 0) 165 return (0); 166 if ((error = getmdev(&devvp, args.fspec, ndp)) != 0) 167 return (error); 168 if (devvp != ump->um_devvp) 169 error = EINVAL; /* needs translation */ 170 } 171 if (error) { 172 vrele(devvp); 173 return (error); 174 } 175 ump = VFSTOUFS(mp); 176 fs = ump->um_fs; 177 (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 178 bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 179 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 180 MNAMELEN); 181 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 182 &size); 183 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 184 (void) ufs_statfs(mp, &mp->mnt_stat); 185 return (0); 186 } 187 188 /* 189 * Common code for mount and mountroot 190 */ 191 mountfs(devvp, mp) 192 register struct vnode *devvp; 193 struct mount *mp; 194 { 195 register struct ufsmount *ump = (struct ufsmount *)0; 196 struct buf *bp = NULL; 197 register struct fs *fs; 198 dev_t dev = devvp->v_rdev; 199 struct partinfo dpart; 200 caddr_t base, space; 201 int havepart = 0, blks; 202 int error, i, size; 203 int needclose = 0; 204 int ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 205 206 /* 207 * Disallow multiple mounts of the same device. 208 * Disallow mounting of a device that is currently in use. 209 * Flush out any old buffers remaining from a previous use. 210 */ 211 if (error = mountedon(devvp)) 212 return (error); 213 if (vcount(devvp) > 1) 214 return (EBUSY); 215 vinvalbuf(devvp, 1); 216 if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED)) 217 return (error); 218 needclose = 1; 219 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED) != 0) { 220 size = DEV_BSIZE; 221 } else { 222 havepart = 1; 223 size = dpart.disklab->d_secsize; 224 } 225 if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) 226 goto out; 227 fs = bp->b_un.b_fs; 228 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 229 fs->fs_bsize < sizeof(struct fs)) { 230 error = EINVAL; /* XXX needs translation */ 231 goto out; 232 } 233 ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK); 234 ump->um_fs = (struct fs *)malloc((u_long)fs->fs_sbsize, M_SUPERBLK, 235 M_WAITOK); 236 bcopy((caddr_t)bp->b_un.b_addr, (caddr_t)ump->um_fs, 237 (u_int)fs->fs_sbsize); 238 if (fs->fs_sbsize < SBSIZE) 239 bp->b_flags |= B_INVAL; 240 brelse(bp); 241 bp = NULL; 242 fs = ump->um_fs; 243 fs->fs_ronly = ronly; 244 if (ronly == 0) 245 fs->fs_fmod = 1; 246 if (havepart) { 247 dpart.part->p_fstype = FS_BSDFFS; 248 dpart.part->p_fsize = fs->fs_fsize; 249 dpart.part->p_frag = fs->fs_frag; 250 dpart.part->p_cpg = fs->fs_cpg; 251 } 252 blks = howmany(fs->fs_cssize, fs->fs_fsize); 253 base = space = (caddr_t)malloc((u_long)fs->fs_cssize, M_SUPERBLK, 254 M_WAITOK); 255 for (i = 0; i < blks; i += fs->fs_frag) { 256 size = fs->fs_bsize; 257 if (i + fs->fs_frag > blks) 258 size = (blks - i) * fs->fs_fsize; 259 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, 260 NOCRED, &bp); 261 if (error) { 262 free((caddr_t)base, M_SUPERBLK); 263 goto out; 264 } 265 bcopy((caddr_t)bp->b_un.b_addr, space, (u_int)size); 266 fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space; 267 space += size; 268 brelse(bp); 269 bp = NULL; 270 } 271 mp->mnt_data = (qaddr_t)ump; 272 mp->mnt_stat.f_fsid.val[0] = (long)dev; 273 mp->mnt_stat.f_fsid.val[1] = MOUNT_UFS; 274 mp->mnt_flag |= MNT_LOCAL; 275 ump->um_mountp = mp; 276 ump->um_dev = dev; 277 ump->um_devvp = devvp; 278 for (i = 0; i < MAXQUOTAS; i++) 279 ump->um_quotas[i] = NULLVP; 280 devvp->v_specflags |= SI_MOUNTEDON; 281 282 /* Sanity checks for old file systems. XXX */ 283 fs->fs_npsect = MAX(fs->fs_npsect, fs->fs_nsect); /* XXX */ 284 fs->fs_interleave = MAX(fs->fs_interleave, 1); /* XXX */ 285 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 286 fs->fs_nrpos = 8; /* XXX */ 287 return (0); 288 out: 289 if (bp) 290 brelse(bp); 291 if (needclose) 292 (void) VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); 293 if (ump) { 294 free((caddr_t)ump->um_fs, M_SUPERBLK); 295 free((caddr_t)ump, M_UFSMNT); 296 mp->mnt_data = (qaddr_t)0; 297 } 298 return (error); 299 } 300 301 /* 302 * Make a filesystem operational. 303 * Nothing to do at the moment. 304 */ 305 /* ARGSUSED */ 306 ufs_start(mp, flags) 307 struct mount *mp; 308 int flags; 309 { 310 311 return (0); 312 } 313 314 /* 315 * unmount system call 316 */ 317 ufs_unmount(mp, mntflags) 318 struct mount *mp; 319 int mntflags; 320 { 321 register struct ufsmount *ump; 322 register struct fs *fs; 323 int i, error, ronly, flags = 0; 324 325 if (mntflags & MNT_FORCE) 326 return (EINVAL); 327 if (mntflags & MNT_FORCE) 328 flags |= FORCECLOSE; 329 mntflushbuf(mp, 0); 330 if (mntinvalbuf(mp)) 331 return (EBUSY); 332 ump = VFSTOUFS(mp); 333 #ifdef QUOTA 334 if (mp->mnt_flag & MNT_QUOTA) { 335 if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) 336 return (error); 337 for (i = 0; i < MAXQUOTAS; i++) { 338 if (ump->um_quotas[i] == NULLVP) 339 continue; 340 quotaoff(mp, i); 341 } 342 /* 343 * Here we fall through to vflush again to ensure 344 * that we have gotten rid of all the system vnodes. 345 */ 346 } 347 #endif 348 if (error = vflush(mp, NULLVP, flags)) 349 return (error); 350 fs = ump->um_fs; 351 ronly = !fs->fs_ronly; 352 ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; 353 error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); 354 vrele(ump->um_devvp); 355 free((caddr_t)fs->fs_csp[0], M_SUPERBLK); 356 free((caddr_t)fs, M_SUPERBLK); 357 free((caddr_t)ump, M_UFSMNT); 358 mp->mnt_data = (qaddr_t)0; 359 mp->mnt_flag &= ~MNT_LOCAL; 360 return (error); 361 } 362 363 /* 364 * Check to see if a filesystem is mounted on a block device. 365 */ 366 mountedon(vp) 367 register struct vnode *vp; 368 { 369 register struct vnode *vq; 370 371 if (vp->v_specflags & SI_MOUNTEDON) 372 return (EBUSY); 373 if (vp->v_flag & VALIASED) { 374 for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) { 375 if (vq->v_rdev != vp->v_rdev || 376 vq->v_type != vp->v_type) 377 continue; 378 if (vq->v_specflags & SI_MOUNTEDON) 379 return (EBUSY); 380 } 381 } 382 return (0); 383 } 384 385 /* 386 * Return root of a filesystem 387 */ 388 ufs_root(mp, vpp) 389 struct mount *mp; 390 struct vnode **vpp; 391 { 392 register struct inode *ip; 393 struct inode *nip; 394 struct vnode tvp; 395 int error; 396 397 tvp.v_mount = mp; 398 ip = VTOI(&tvp); 399 ip->i_vnode = &tvp; 400 ip->i_dev = VFSTOUFS(mp)->um_dev; 401 error = iget(ip, (ino_t)ROOTINO, &nip); 402 if (error) 403 return (error); 404 *vpp = ITOV(nip); 405 return (0); 406 } 407 408 /* 409 * Do operations associated with quotas 410 */ 411 ufs_quotactl(mp, cmds, uid, arg) 412 struct mount *mp; 413 int cmds; 414 uid_t uid; 415 caddr_t arg; 416 { 417 register struct nameidata *ndp = &u.u_nd; 418 struct ufsmount *ump = VFSTOUFS(mp); 419 int cmd, type, error; 420 421 #ifndef QUOTA 422 return (EOPNOTSUPP); 423 #else 424 if (uid == -1) 425 uid = u.u_ruid; 426 cmd = cmds >> SUBCMDSHIFT; 427 428 switch (cmd) { 429 case Q_GETQUOTA: 430 case Q_SYNC: 431 if (uid == u.u_ruid) 432 break; 433 /* fall through */ 434 default: 435 if (error = suser(ndp->ni_cred, &u.u_acflag)) 436 return (error); 437 } 438 439 type = cmd & SUBCMDMASK; 440 if ((u_int)type >= MAXQUOTAS) 441 return (EINVAL); 442 443 switch (cmd) { 444 445 case Q_QUOTAON: 446 return (quotaon(ndp, mp, type, arg)); 447 448 case Q_QUOTAOFF: 449 if (vfs_busy(mp)) 450 return (0); 451 error = quotaoff(mp, type); 452 vfs_unbusy(mp); 453 return (error); 454 455 case Q_SETQUOTA: 456 return (setquota(mp, uid, type, arg)); 457 458 case Q_SETUSE: 459 return (setuse(mp, uid, type, arg)); 460 461 case Q_GETQUOTA: 462 return (getquota(mp, uid, type, arg)); 463 464 case Q_SYNC: 465 if (vfs_busy(mp)) 466 return (0); 467 error = qsync(mp); 468 vfs_unbusy(mp); 469 return (error); 470 471 default: 472 return (EINVAL); 473 } 474 /* NOTREACHED */ 475 #endif 476 } 477 478 /* 479 * Get file system statistics. 480 */ 481 ufs_statfs(mp, sbp) 482 struct mount *mp; 483 register struct statfs *sbp; 484 { 485 register struct ufsmount *ump; 486 register struct fs *fs; 487 488 ump = VFSTOUFS(mp); 489 fs = ump->um_fs; 490 if (fs->fs_magic != FS_MAGIC) 491 panic("ufs_statfs"); 492 sbp->f_type = MOUNT_UFS; 493 sbp->f_fsize = fs->fs_fsize; 494 sbp->f_bsize = fs->fs_bsize; 495 sbp->f_blocks = fs->fs_dsize; 496 sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + 497 fs->fs_cstotal.cs_nffree; 498 sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) - 499 (fs->fs_dsize - sbp->f_bfree); 500 sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO; 501 sbp->f_ffree = fs->fs_cstotal.cs_nifree; 502 if (sbp != &mp->mnt_stat) { 503 bcopy((caddr_t)mp->mnt_stat.f_mntonname, 504 (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 505 bcopy((caddr_t)mp->mnt_stat.f_mntfromname, 506 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 507 } 508 return (0); 509 } 510 511 int syncprt = 0; 512 513 /* 514 * Go through the disk queues to initiate sandbagged IO; 515 * go through the inodes to write those that have been modified; 516 * initiate the writing of the super block if it has been modified. 517 * 518 * Note: we are always called with the filesystem marked `MPBUSY'. 519 */ 520 ufs_sync(mp, waitfor) 521 struct mount *mp; 522 int waitfor; 523 { 524 register struct vnode *vp; 525 register struct inode *ip; 526 register struct ufsmount *ump = VFSTOUFS(mp); 527 register struct fs *fs; 528 struct vnode *nvp; 529 int error, allerror = 0; 530 static int updlock = 0; 531 532 if (syncprt) 533 bufstats(); 534 if (updlock) 535 return (EBUSY); 536 fs = ump->um_fs; 537 if (fs == (struct fs *)1) 538 return (0); 539 updlock++; 540 /* 541 * Write back modified superblock. 542 * Consistency check that the superblock 543 * is still in the buffer cache. 544 */ 545 if (fs->fs_fmod != 0) { 546 if (fs->fs_ronly != 0) { /* XXX */ 547 printf("fs = %s\n", fs->fs_fsmnt); 548 panic("update: rofs mod"); 549 } 550 fs->fs_fmod = 0; 551 fs->fs_time = time.tv_sec; 552 error = sbupdate(ump, waitfor); 553 } 554 /* 555 * Write back each (modified) inode. 556 */ 557 loop: 558 for (vp = mp->mnt_mounth; vp; vp = nvp) { 559 nvp = vp->v_mountf; 560 ip = VTOI(vp); 561 if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0 && 562 vp->v_dirtyblkhd == NULL) 563 continue; 564 if (vget(vp)) 565 goto loop; 566 if (vp->v_dirtyblkhd) 567 vflushbuf(vp, 0); 568 if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) && 569 (error = iupdat(ip, &time, &time, 0))) 570 allerror = error; 571 vput(vp); 572 } 573 updlock = 0; 574 /* 575 * Force stale file system control information to be flushed. 576 */ 577 vflushbuf(ump->um_devvp, waitfor == MNT_WAIT ? B_SYNC : 0); 578 #ifdef QUOTA 579 qsync(mp); 580 #endif 581 return (allerror); 582 } 583 584 /* 585 * Write a superblock and associated information back to disk. 586 */ 587 sbupdate(mp, waitfor) 588 struct ufsmount *mp; 589 int waitfor; 590 { 591 register struct fs *fs = mp->um_fs; 592 register struct buf *bp; 593 int blks; 594 caddr_t space; 595 int i, size, error = 0; 596 597 bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize); 598 bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize); 599 /* Restore compatibility to old file systems. XXX */ 600 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 601 bp->b_un.b_fs->fs_nrpos = -1; /* XXX */ 602 if (waitfor == MNT_WAIT) 603 error = bwrite(bp); 604 else 605 bawrite(bp); 606 blks = howmany(fs->fs_cssize, fs->fs_fsize); 607 space = (caddr_t)fs->fs_csp[0]; 608 for (i = 0; i < blks; i += fs->fs_frag) { 609 size = fs->fs_bsize; 610 if (i + fs->fs_frag > blks) 611 size = (blks - i) * fs->fs_fsize; 612 bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), size); 613 bcopy(space, bp->b_un.b_addr, (u_int)size); 614 space += size; 615 if (waitfor == MNT_WAIT) 616 error = bwrite(bp); 617 else 618 bawrite(bp); 619 } 620 return (error); 621 } 622 623 /* 624 * Print out statistics on the current allocation of the buffer pool. 625 * Can be enabled to print out on every ``sync'' by setting "syncprt" 626 * above. 627 */ 628 bufstats() 629 { 630 int s, i, j, count; 631 register struct buf *bp, *dp; 632 int counts[MAXBSIZE/CLBYTES+1]; 633 static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" }; 634 635 for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) { 636 count = 0; 637 for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 638 counts[j] = 0; 639 s = splbio(); 640 for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) { 641 counts[dp->b_bufsize/CLBYTES]++; 642 count++; 643 } 644 splx(s); 645 printf("%s: total-%d", bname[i], count); 646 for (j = 0; j <= MAXBSIZE/CLBYTES; j++) 647 if (counts[j] != 0) 648 printf(", %d-%d", j * CLBYTES, counts[j]); 649 printf("\n"); 650 } 651 } 652 653 /* 654 * File handle to vnode 655 * 656 * Have to be really careful about stale file handles: 657 * - check that the inode number is in range 658 * - call iget() to get the locked inode 659 * - check for an unallocated inode (i_mode == 0) 660 * - check that the generation number matches 661 */ 662 ufs_fhtovp(mp, fhp, vpp) 663 register struct mount *mp; 664 struct fid *fhp; 665 struct vnode **vpp; 666 { 667 register struct ufid *ufhp; 668 register struct fs *fs; 669 register struct inode *ip; 670 struct inode *nip; 671 struct vnode tvp; 672 int error; 673 674 ufhp = (struct ufid *)fhp; 675 fs = VFSTOUFS(mp)->um_fs; 676 if (ufhp->ufid_ino < ROOTINO || 677 ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) { 678 *vpp = NULLVP; 679 return (EINVAL); 680 } 681 tvp.v_mount = mp; 682 ip = VTOI(&tvp); 683 ip->i_vnode = &tvp; 684 ip->i_dev = VFSTOUFS(mp)->um_dev; 685 if (error = iget(ip, ufhp->ufid_ino, &nip)) { 686 *vpp = NULLVP; 687 return (error); 688 } 689 ip = nip; 690 if (ip->i_mode == 0) { 691 iput(ip); 692 *vpp = NULLVP; 693 return (EINVAL); 694 } 695 if (ip->i_gen != ufhp->ufid_gen) { 696 iput(ip); 697 *vpp = NULLVP; 698 return (EINVAL); 699 } 700 *vpp = ITOV(ip); 701 return (0); 702 } 703 704 /* 705 * Vnode pointer to File handle 706 */ 707 /* ARGSUSED */ 708 ufs_vptofh(vp, fhp) 709 struct vnode *vp; 710 struct fid *fhp; 711 { 712 register struct inode *ip = VTOI(vp); 713 register struct ufid *ufhp; 714 715 ufhp = (struct ufid *)fhp; 716 ufhp->ufid_len = sizeof(struct ufid); 717 ufhp->ufid_ino = ip->i_number; 718 ufhp->ufid_gen = ip->i_gen; 719 return (0); 720 } 721 722 /* 723 * Common code for mount and quota. 724 * Check that the user's argument is a reasonable 725 * thing on which to mount, and return the device number if so. 726 */ 727 getmdev(devvpp, fname, ndp) 728 struct vnode **devvpp; 729 caddr_t fname; 730 register struct nameidata *ndp; 731 { 732 register struct vnode *vp; 733 int error; 734 735 ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 736 ndp->ni_segflg = UIO_USERSPACE; 737 ndp->ni_dirp = fname; 738 if (error = namei(ndp)) { 739 if (error == ENOENT) 740 return (ENODEV); /* needs translation */ 741 return (error); 742 } 743 vp = ndp->ni_vp; 744 if (vp->v_type != VBLK) { 745 vput(vp); 746 return (ENOTBLK); 747 } 748 if (major(vp->v_rdev) >= nblkdev) { 749 vput(vp); 750 return (ENXIO); 751 } 752 iunlock(VTOI(vp)); 753 *devvpp = vp; 754 return (0); 755 } 756