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.47 (Berkeley) 06/03/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 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) ufs_statfs(mp, &mp->mnt_stat); 187 return (0); 188 } 189 190 /* 191 * Common code for mount and mountroot 192 */ 193 mountfs(devvp, mp) 194 register struct vnode *devvp; 195 struct mount *mp; 196 { 197 register struct ufsmount *ump = (struct ufsmount *)0; 198 struct buf *bp = NULL; 199 register struct fs *fs; 200 dev_t dev = devvp->v_rdev; 201 struct partinfo dpart; 202 caddr_t base, space; 203 int havepart = 0, blks; 204 int error, i, size; 205 int needclose = 0; 206 int ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 207 208 /* 209 * Disallow multiple mounts of the same device. 210 * Disallow mounting of a device that is currently in use. 211 * Flush out any old buffers remaining from a previous use. 212 */ 213 if (error = mountedon(devvp)) 214 return (error); 215 if (vcount(devvp) > 1) 216 return (EBUSY); 217 vinvalbuf(devvp, 1); 218 if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED)) 219 return (error); 220 needclose = 1; 221 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED) != 0) { 222 size = DEV_BSIZE; 223 } else { 224 havepart = 1; 225 size = dpart.disklab->d_secsize; 226 } 227 if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) 228 goto out; 229 fs = bp->b_un.b_fs; 230 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 231 fs->fs_bsize < sizeof(struct fs)) { 232 error = EINVAL; /* XXX needs translation */ 233 goto out; 234 } 235 ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK); 236 ump->um_fs = (struct fs *)malloc((u_long)fs->fs_sbsize, M_SUPERBLK, 237 M_WAITOK); 238 bcopy((caddr_t)bp->b_un.b_addr, (caddr_t)ump->um_fs, 239 (u_int)fs->fs_sbsize); 240 if (fs->fs_sbsize < SBSIZE) 241 bp->b_flags |= B_INVAL; 242 brelse(bp); 243 bp = NULL; 244 fs = ump->um_fs; 245 fs->fs_ronly = ronly; 246 if (ronly == 0) 247 fs->fs_fmod = 1; 248 if (havepart) { 249 dpart.part->p_fstype = FS_BSDFFS; 250 dpart.part->p_fsize = fs->fs_fsize; 251 dpart.part->p_frag = fs->fs_frag; 252 dpart.part->p_cpg = fs->fs_cpg; 253 } 254 blks = howmany(fs->fs_cssize, fs->fs_fsize); 255 base = space = (caddr_t)malloc((u_long)fs->fs_cssize, M_SUPERBLK, 256 M_WAITOK); 257 for (i = 0; i < blks; i += fs->fs_frag) { 258 size = fs->fs_bsize; 259 if (i + fs->fs_frag > blks) 260 size = (blks - i) * fs->fs_fsize; 261 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, 262 NOCRED, &bp); 263 if (error) { 264 free((caddr_t)base, M_SUPERBLK); 265 goto out; 266 } 267 bcopy((caddr_t)bp->b_un.b_addr, space, (u_int)size); 268 fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space; 269 space += size; 270 brelse(bp); 271 bp = NULL; 272 } 273 mp->mnt_data = (qaddr_t)ump; 274 mp->mnt_stat.f_fsid.val[0] = (long)dev; 275 mp->mnt_stat.f_fsid.val[1] = MOUNT_UFS; 276 mp->mnt_flag |= MNT_LOCAL; 277 ump->um_mountp = mp; 278 ump->um_dev = dev; 279 ump->um_devvp = devvp; 280 for (i = 0; i < MAXQUOTAS; i++) 281 ump->um_quotas[i] = NULLVP; 282 devvp->v_specflags |= SI_MOUNTEDON; 283 284 /* Sanity checks for old file systems. XXX */ 285 fs->fs_npsect = MAX(fs->fs_npsect, fs->fs_nsect); /* XXX */ 286 fs->fs_interleave = MAX(fs->fs_interleave, 1); /* XXX */ 287 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ 288 fs->fs_nrpos = 8; /* XXX */ 289 return (0); 290 out: 291 if (bp) 292 brelse(bp); 293 if (needclose) 294 (void) VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); 295 if (ump) { 296 free((caddr_t)ump->um_fs, M_SUPERBLK); 297 free((caddr_t)ump, M_UFSMNT); 298 mp->mnt_data = (qaddr_t)0; 299 } 300 return (error); 301 } 302 303 /* 304 * Make a filesystem operational. 305 * Nothing to do at the moment. 306 */ 307 /* ARGSUSED */ 308 ufs_start(mp, flags) 309 struct mount *mp; 310 int flags; 311 { 312 313 return (0); 314 } 315 316 /* 317 * unmount system call 318 */ 319 ufs_unmount(mp, mntflags) 320 struct mount *mp; 321 int mntflags; 322 { 323 register struct ufsmount *ump; 324 register struct fs *fs; 325 int i, error, ronly, flags = 0; 326 327 if (mntflags & MNT_FORCE) 328 return (EINVAL); 329 if (mntflags & MNT_FORCE) 330 flags |= FORCECLOSE; 331 mntflushbuf(mp, 0); 332 if (mntinvalbuf(mp)) 333 return (EBUSY); 334 ump = VFSTOUFS(mp); 335 #ifdef QUOTA 336 if (mp->mnt_flag & MNT_QUOTA) { 337 if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) 338 return (error); 339 for (i = 0; i < MAXQUOTAS; i++) { 340 if (ump->um_quotas[i] == NULLVP) 341 continue; 342 quotaoff(mp, i); 343 } 344 /* 345 * Here we fall through to vflush again to ensure 346 * that we have gotten rid of all the system vnodes. 347 */ 348 } 349 #endif 350 if (error = vflush(mp, NULLVP, flags)) 351 return (error); 352 fs = ump->um_fs; 353 ronly = !fs->fs_ronly; 354 ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; 355 error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); 356 vrele(ump->um_devvp); 357 free((caddr_t)fs->fs_csp[0], M_SUPERBLK); 358 free((caddr_t)fs, M_SUPERBLK); 359 free((caddr_t)ump, M_UFSMNT); 360 mp->mnt_data = (qaddr_t)0; 361 mp->mnt_flag &= ~MNT_LOCAL; 362 return (error); 363 } 364 365 /* 366 * Check to see if a filesystem is mounted on a block device. 367 */ 368 mountedon(vp) 369 register struct vnode *vp; 370 { 371 register struct vnode *vq; 372 373 if (vp->v_specflags & SI_MOUNTEDON) 374 return (EBUSY); 375 if (vp->v_flag & VALIASED) { 376 for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) { 377 if (vq->v_rdev != vp->v_rdev || 378 vq->v_type != vp->v_type) 379 continue; 380 if (vq->v_specflags & SI_MOUNTEDON) 381 return (EBUSY); 382 } 383 } 384 return (0); 385 } 386 387 /* 388 * Return root of a filesystem 389 */ 390 ufs_root(mp, vpp) 391 struct mount *mp; 392 struct vnode **vpp; 393 { 394 register struct inode *ip; 395 struct inode *nip; 396 struct vnode tvp; 397 int error; 398 399 tvp.v_mount = mp; 400 ip = VTOI(&tvp); 401 ip->i_vnode = &tvp; 402 ip->i_dev = VFSTOUFS(mp)->um_dev; 403 error = iget(ip, (ino_t)ROOTINO, &nip); 404 if (error) 405 return (error); 406 *vpp = ITOV(nip); 407 return (0); 408 } 409 410 /* 411 * Do operations associated with quotas 412 */ 413 ufs_quotactl(mp, cmds, uid, arg) 414 struct mount *mp; 415 int cmds; 416 uid_t uid; 417 caddr_t arg; 418 { 419 register struct nameidata *ndp = &u.u_nd; 420 struct ufsmount *ump = VFSTOUFS(mp); 421 struct proc *p = u.u_procp; /* XXX */ 422 int cmd, type, error; 423 424 #ifndef QUOTA 425 return (EOPNOTSUPP); 426 #else 427 if (uid == -1) 428 uid = p->p_ruid; 429 cmd = cmds >> SUBCMDSHIFT; 430 431 switch (cmd) { 432 case Q_GETQUOTA: 433 case Q_SYNC: 434 if (uid == p->p_ruid) 435 break; 436 /* fall through */ 437 default: 438 if (error = suser(ndp->ni_cred, &u.u_acflag)) 439 return (error); 440 } 441 442 type = cmd & SUBCMDMASK; 443 if ((u_int)type >= MAXQUOTAS) 444 return (EINVAL); 445 446 switch (cmd) { 447 448 case Q_QUOTAON: 449 return (quotaon(ndp, mp, type, arg)); 450 451 case Q_QUOTAOFF: 452 if (vfs_busy(mp)) 453 return (0); 454 error = quotaoff(mp, type); 455 vfs_unbusy(mp); 456 return (error); 457 458 case Q_SETQUOTA: 459 return (setquota(mp, uid, type, arg)); 460 461 case Q_SETUSE: 462 return (setuse(mp, uid, type, arg)); 463 464 case Q_GETQUOTA: 465 return (getquota(mp, uid, type, arg)); 466 467 case Q_SYNC: 468 if (vfs_busy(mp)) 469 return (0); 470 error = qsync(mp); 471 vfs_unbusy(mp); 472 return (error); 473 474 default: 475 return (EINVAL); 476 } 477 /* NOTREACHED */ 478 #endif 479 } 480 481 /* 482 * Get file system statistics. 483 */ 484 ufs_statfs(mp, sbp) 485 struct mount *mp; 486 register struct statfs *sbp; 487 { 488 register struct ufsmount *ump; 489 register struct fs *fs; 490 491 ump = VFSTOUFS(mp); 492 fs = ump->um_fs; 493 if (fs->fs_magic != FS_MAGIC) 494 panic("ufs_statfs"); 495 sbp->f_type = MOUNT_UFS; 496 sbp->f_fsize = fs->fs_fsize; 497 sbp->f_bsize = fs->fs_bsize; 498 sbp->f_blocks = fs->fs_dsize; 499 sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + 500 fs->fs_cstotal.cs_nffree; 501 sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) - 502 (fs->fs_dsize - sbp->f_bfree); 503 sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO; 504 sbp->f_ffree = fs->fs_cstotal.cs_nifree; 505 if (sbp != &mp->mnt_stat) { 506 bcopy((caddr_t)mp->mnt_stat.f_mntonname, 507 (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 508 bcopy((caddr_t)mp->mnt_stat.f_mntfromname, 509 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 510 } 511 return (0); 512 } 513 514 int syncprt = 0; 515 516 /* 517 * Go through the disk queues to initiate sandbagged IO; 518 * go through the inodes to write those that have been modified; 519 * initiate the writing of the super block if it has been modified. 520 * 521 * Note: we are always called with the filesystem marked `MPBUSY'. 522 */ 523 ufs_sync(mp, waitfor) 524 struct mount *mp; 525 int waitfor; 526 { 527 register struct vnode *vp; 528 register struct inode *ip; 529 register struct ufsmount *ump = VFSTOUFS(mp); 530 register struct fs *fs; 531 int error, allerror = 0; 532 533 if (syncprt) 534 bufstats(); 535 fs = ump->um_fs; 536 /* 537 * Write back modified superblock. 538 * Consistency check that the superblock 539 * is still in the buffer cache. 540 */ 541 if (fs->fs_fmod != 0) { 542 if (fs->fs_ronly != 0) { /* XXX */ 543 printf("fs = %s\n", fs->fs_fsmnt); 544 panic("update: rofs mod"); 545 } 546 fs->fs_fmod = 0; 547 fs->fs_time = time.tv_sec; 548 allerror = sbupdate(ump, waitfor); 549 } 550 /* 551 * Write back each (modified) inode. 552 */ 553 loop: 554 for (vp = mp->mnt_mounth; vp; vp = vp->v_mountf) { 555 /* 556 * If the vnode that we are about to sync is no longer 557 * associated with this mount point, start over. 558 */ 559 if (vp->v_mount != mp) 560 goto loop; 561 ip = VTOI(vp); 562 if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0 && 563 vp->v_dirtyblkhd == NULL) 564 continue; 565 if (vget(vp)) 566 goto loop; 567 if (vp->v_dirtyblkhd) 568 vflushbuf(vp, 0); 569 if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) && 570 (error = iupdat(ip, &time, &time, 0))) 571 allerror = error; 572 vput(vp); 573 } 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 * Check that the user's argument is a reasonable 724 * thing on which to mount, and return the device number if so. 725 */ 726 getmdev(devvpp, fname, ndp) 727 struct vnode **devvpp; 728 caddr_t fname; 729 register struct nameidata *ndp; 730 { 731 register struct vnode *vp; 732 int error; 733 734 ndp->ni_nameiop = LOOKUP | FOLLOW; 735 ndp->ni_segflg = UIO_USERSPACE; 736 ndp->ni_dirp = fname; 737 if (error = namei(ndp)) { 738 if (error == ENOENT) 739 return (ENODEV); /* needs translation */ 740 return (error); 741 } 742 vp = ndp->ni_vp; 743 if (vp->v_type != VBLK) { 744 vrele(vp); 745 return (ENOTBLK); 746 } 747 if (major(vp->v_rdev) >= nblkdev) { 748 vrele(vp); 749 return (ENXIO); 750 } 751 *devvpp = vp; 752 return (0); 753 } 754