ISO debugging uses logpri
[unix-history] / usr / src / sys / ufs / lfs / lfs_vfsops.c
CommitLineData
da7c5cc6 1/*
190244fb 2 * Copyright (c) 1989, 1991 The Regents of the University of California.
7188ac27 3 * All rights reserved.
da7c5cc6 4 *
b702c21d 5 * %sccs.include.redist.c%
7188ac27 6 *
0b4d6502 7 * @(#)lfs_vfsops.c 7.57 (Berkeley) %G%
da7c5cc6 8 */
71e4e98b 9
94368568
JB
10#include "param.h"
11#include "systm.h"
c6f5111d 12#include "namei.h"
8dc876c1 13#include "proc.h"
7188ac27 14#include "kernel.h"
7188ac27 15#include "vnode.h"
0f93ba7b 16#include "specdev.h"
94368568 17#include "mount.h"
7188ac27 18#include "buf.h"
94368568 19#include "file.h"
ec67a3ce 20#include "disklabel.h"
7188ac27
KM
21#include "ioctl.h"
22#include "errno.h"
4def0c5e 23#include "malloc.h"
609e7cfa
MK
24#include "ioctl.h"
25#include "disklabel.h"
26#include "stat.h"
71e4e98b 27
0b4d6502
KB
28#include "../ufs/quota.h"
29#include "../ufs/inode.h"
30#include "../ufs/ufsmount.h"
31#include "lfs.h"
32#include "lfs_extern.h"
c6f5111d 33
0b4d6502
KB
34static int lfs_mountfs
35 __P((struct vnode *, struct mount *, struct proc *));
36static int sbupdate __P((struct ufsmount *, int));
37
38struct vfsops lfs_vfsops = {
39 lfs_mount,
5bf9d21f 40 ufs_start,
0b4d6502
KB
41 lfs_unmount,
42 lfs_root,
8dc876c1 43 ufs_quotactl,
0b4d6502
KB
44 lfs_statfs,
45 lfs_sync,
46 lfs_fhtovp,
de0d8667 47 ufs_vptofh,
0b4d6502 48 lfs_init
7188ac27
KM
49};
50
d85a9d1b
KM
51/*
52 * Flag to allow forcible unmounting.
53 */
0b4d6502 54extern int doforce; /* LFS */
7188ac27 55
0b4d6502 56lfs_mountroot()
71e4e98b 57{
0b4d6502
KB
58 /* LFS IMPLEMENT -- lfs_mountroot */
59 panic("lfs_mountroot");
7188ac27
KM
60}
61
62/*
63 * VFS Operations.
64 *
65 * mount system call
66 */
0b4d6502 67lfs_mount(mp, path, data, ndp, p)
d45de50d 68 register struct mount *mp;
7188ac27
KM
69 char *path;
70 caddr_t data;
71 struct nameidata *ndp;
0eb6f54a 72 struct proc *p;
7188ac27
KM
73{
74 struct vnode *devvp;
75 struct ufs_args args;
76 struct ufsmount *ump;
0b4d6502 77 register LFS *fs; /* LFS */
7188ac27
KM
78 u_int size;
79 int error;
80
0b4d6502 81printf("lfs_mount\n");
7188ac27
KM
82 if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
83 return (error);
3b931949
KM
84 /*
85 * Process export requests.
86 */
82161bc8
KM
87 if ((args.exflags & MNT_EXPORTED) || (mp->mnt_flag & MNT_EXPORTED)) {
88 if (args.exflags & MNT_EXPORTED)
89 mp->mnt_flag |= MNT_EXPORTED;
3b931949 90 else
82161bc8
KM
91 mp->mnt_flag &= ~MNT_EXPORTED;
92 if (args.exflags & MNT_EXRDONLY)
93 mp->mnt_flag |= MNT_EXRDONLY;
3b931949 94 else
82161bc8
KM
95 mp->mnt_flag &= ~MNT_EXRDONLY;
96 mp->mnt_exroot = args.exroot;
3b931949 97 }
190244fb
MK
98 /*
99 * If updating, check whether changing from read-only to
100 * read/write; if there is no device name, that's all we do.
101 */
102 if (mp->mnt_flag & MNT_UPDATE) {
d48157d5 103 ump = VFSTOUFS(mp);
0b4d6502 104#ifdef NOTLFS /* LFS */
d48157d5 105 fs = ump->um_fs;
82161bc8 106 if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0)
d48157d5 107 fs->fs_ronly = 0;
0b4d6502
KB
108#else
109 fs = ump->um_lfs;
110 if (fs->lfs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0)
111 fs->lfs_ronly = 0;
112#endif
3b931949
KM
113 if (args.fspec == 0)
114 return (0);
190244fb
MK
115 }
116 /*
117 * Not an update, or updating the name: look up the name
118 * and verify that it refers to a sensible block device.
119 */
120 ndp->ni_nameiop = LOOKUP | FOLLOW;
121 ndp->ni_segflg = UIO_USERSPACE;
122 ndp->ni_dirp = args.fspec;
123 if (error = namei(ndp, p))
124 return (error);
125 devvp = ndp->ni_vp;
126 if (devvp->v_type != VBLK) {
127 vrele(devvp);
128 return (ENOTBLK);
129 }
130 if (major(devvp->v_rdev) >= nblkdev) {
131 vrele(devvp);
132 return (ENXIO);
133 }
134 if ((mp->mnt_flag & MNT_UPDATE) == 0)
0b4d6502 135 error = lfs_mountfs(devvp, mp, p); /* LFS */
190244fb 136 else {
d48157d5
KM
137 if (devvp != ump->um_devvp)
138 error = EINVAL; /* needs translation */
2a7dbb09
KM
139 else
140 vrele(devvp);
d48157d5 141 }
7188ac27
KM
142 if (error) {
143 vrele(devvp);
144 return (error);
27d00e76 145 }
7188ac27 146 ump = VFSTOUFS(mp);
0b4d6502
KB
147 fs = ump->um_lfs; /* LFS */
148#ifdef NOTLFS /* LFS */
7188ac27
KM
149 (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
150 bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
82161bc8
KM
151 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
152 MNAMELEN);
153 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
154 &size);
155 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
0eb6f54a 156 (void) ufs_statfs(mp, &mp->mnt_stat, p);
0b4d6502
KB
157#else
158 (void)copyinstr(path, fs->lfs_fsmnt, sizeof(fs->lfs_fsmnt) - 1, &size);
159 bzero(fs->lfs_fsmnt + size, sizeof(fs->lfs_fsmnt) - size);
160 bcopy((caddr_t)fs->lfs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
161 MNAMELEN);
162 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
163 &size);
164 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
165 (void) lfs_statfs(mp, &mp->mnt_stat, p);
166#endif
7188ac27 167 return (0);
71e4e98b
SL
168}
169
7188ac27
KM
170/*
171 * Common code for mount and mountroot
0b4d6502 172 * LFS specific
7188ac27 173 */
0b4d6502
KB
174static int
175lfs_mountfs(devvp, mp, p)
1182ae61 176 register struct vnode *devvp;
7188ac27 177 struct mount *mp;
0eb6f54a 178 struct proc *p;
71e4e98b 179{
1c26e003 180 extern struct vnode *rootvp;
0b4d6502
KB
181 register LFS *fs;
182 register struct ufsmount *ump;
183 struct inode *ip;
184 struct vnode *vp;
185 struct buf *bp;
186 struct partinfo dpart;
187 daddr_t seg_addr;
188 dev_t dev;
189 int error, i, ronly, size;
71e4e98b 190
0eb6f54a 191 if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p))
7188ac27 192 return (error);
0b4d6502 193
0eb6f54a 194 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
609e7cfa 195 size = DEV_BSIZE;
0eb6f54a 196 else {
ec67a3ce 197 size = dpart.disklab->d_secsize;
0b4d6502
KB
198#ifdef NEVER_USED
199 dpart.part->p_fstype = FS_LFS;
200 dpart.part->p_fsize = fs->lfs_fsize; /* frag size */
201 dpart.part->p_frag = fs->lfs_frag; /* frags per block */
202 dpart.part->p_cpg = fs->lfs_segshift; /* segment shift */
203#endif
7188ac27 204 }
0b4d6502
KB
205
206 /* Don't free random space on error. */
207 bp = NULL;
208 ump = NULL;
209
210 /* Read in the superblock. */
211 if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, NOCRED, &bp))
71e4e98b 212 goto out;
8dc876c1 213 error = EINVAL; /* XXX needs translation */
1c281610
MK
214 goto out;
215 }
0b4d6502
KB
216#ifdef DEBUG
217 dump_super(fs);
218#endif
219
220 /* Allocate the mount structure, copy the superblock into it. */
8dc876c1 221 ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
0b4d6502
KB
222 ump->um_lfs = malloc(sizeof(LFS), M_SUPERBLK, M_WAITOK);
223 bcopy(bp->b_un.b_addr, ump->um_lfs, sizeof(LFS));
224 if (sizeof(LFS) < LFS_SBPAD) /* XXX why? */
5d96a9ad 225 bp->b_flags |= B_INVAL;
e018935f
MK
226 brelse(bp);
227 bp = NULL;
0b4d6502
KB
228
229 /* Set the file system readonly/modify bits. */
230 fs = ump->um_lfs;
231 fs->lfs_ronly = ronly;
71e4e98b 232 if (ronly == 0)
0b4d6502
KB
233 fs->lfs_fmod = 1;
234
235 /* Initialize the mount structure. */
236 dev = devvp->v_rdev;
82161bc8
KM
237 mp->mnt_data = (qaddr_t)ump;
238 mp->mnt_stat.f_fsid.val[0] = (long)dev;
0b4d6502 239 mp->mnt_stat.f_fsid.val[1] = MOUNT_LFS;
82161bc8 240 mp->mnt_flag |= MNT_LOCAL;
7188ac27
KM
241 ump->um_mountp = mp;
242 ump->um_dev = dev;
243 ump->um_devvp = devvp;
8dc876c1
KM
244 for (i = 0; i < MAXQUOTAS; i++)
245 ump->um_quotas[i] = NULLVP;
7188ac27 246
0b4d6502
KB
247 /* Read the ifile disk inode and store it in a vnode. */
248 error = bread(devvp, fs->lfs_idaddr, fs->lfs_bsize, NOCRED, &bp);
249 if (error)
250 goto out;
251 error = lfs_vcreate(mp, LFS_IFILE_INUM, &vp);
252 if (error)
253 goto out;
254 ip = VTOI(vp);
255
256 /* The ifile inode is stored in the superblock. */
257 fs->lfs_ivnode = vp;
258
259 /* Copy the on-disk inode into place. */
260 ip->i_din = *lfs_ifind(fs, LFS_IFILE_INUM, bp->b_un.b_dino);
261 brelse(bp);
262
263 /* Initialize the associated vnode */
264 vp->v_type = IFTOVT(ip->i_mode);
265
266 /*
267 * Read in the segusage table.
268 *
269 * Since we always explicitly write the segusage table at a checkpoint,
270 * we're assuming that it is continguous on disk.
271 */
272 seg_addr = ip->i_din.di_db[0];
273 size = fs->lfs_segtabsz << fs->lfs_bshift;
274 fs->lfs_segtab = malloc(size, M_SUPERBLK, M_WAITOK);
275 error = bread(devvp, seg_addr, size, NOCRED, &bp);
276 if (error) {
277 free(fs->lfs_segtab, M_SUPERBLK);
278 goto out;
279 }
280 bcopy((caddr_t)bp->b_un.b_addr, fs->lfs_segtab, size);
281 brelse(bp);
282 devvp->v_specflags |= SI_MOUNTEDON;
283 VREF(ip->i_devvp);
609e7cfa 284
7188ac27 285 return (0);
71e4e98b 286out:
c86c9b6e
KM
287 if (bp)
288 brelse(bp);
0b4d6502 289 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
8dc876c1 290 if (ump) {
0b4d6502 291 free((caddr_t)ump->um_lfs, M_SUPERBLK);
8dc876c1 292 free((caddr_t)ump, M_UFSMNT);
82161bc8 293 mp->mnt_data = (qaddr_t)0;
27d00e76 294 }
7188ac27 295 return (error);
71e4e98b
SL
296}
297
7188ac27
KM
298/*
299 * unmount system call
300 */
0b4d6502 301lfs_unmount(mp, mntflags, p)
7188ac27 302 struct mount *mp;
8dc876c1 303 int mntflags;
0eb6f54a 304 struct proc *p;
71e4e98b 305{
7188ac27 306 register struct ufsmount *ump;
0b4d6502 307 register struct lfs *fs; /* LFS */
8dc876c1 308 int i, error, ronly, flags = 0;
71e4e98b 309
0b4d6502 310printf("lfs_unmount\n");
87be6db2 311 if (mntflags & MNT_FORCE) {
d85a9d1b 312 if (!doforce || mp == rootfs)
87be6db2 313 return (EINVAL);
8dc876c1 314 flags |= FORCECLOSE;
87be6db2 315 }
5d96a9ad
KM
316 mntflushbuf(mp, 0);
317 if (mntinvalbuf(mp))
318 return (EBUSY);
7188ac27 319 ump = VFSTOUFS(mp);
ec67a3ce 320 return (error);
71e4e98b 321#ifdef QUOTA
82161bc8 322 if (mp->mnt_flag & MNT_QUOTA) {
8dc876c1 323 if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags))
6d943995 324 return (error);
8dc876c1
KM
325 for (i = 0; i < MAXQUOTAS; i++) {
326 if (ump->um_quotas[i] == NULLVP)
327 continue;
70a360ba 328 quotaoff(p, mp, i);
8dc876c1 329 }
6d943995 330 /*
8dc876c1
KM
331 * Here we fall through to vflush again to ensure
332 * that we have gotten rid of all the system vnodes.
6d943995 333 */
8dc876c1 334 }
71e4e98b 335#endif
8dc876c1 336 if (error = vflush(mp, NULLVP, flags))
6d943995 337 return (error);
0b4d6502 338#ifdef NOTLFS /* LFS */
7188ac27
KM
339 fs = ump->um_fs;
340 ronly = !fs->fs_ronly;
0b4d6502
KB
341#else
342 fs = ump->um_lfs;
343 ronly = !fs->lfs_ronly;
344#endif
7188ac27
KM
345 * Return root of a filesystem
346 */
0b4d6502 347lfs_root(mp, vpp)
7188ac27
KM
348 struct mount *mp;
349 struct vnode **vpp;
350{
31593ba7
KM
351 register struct inode *ip;
352 struct inode *nip;
353 struct vnode tvp;
7188ac27
KM
354 int error;
355
0b4d6502 356printf("lfs_root\n");
31593ba7
KM
357 tvp.v_mount = mp;
358 ip = VTOI(&tvp);
359 ip->i_vnode = &tvp;
360 ip->i_dev = VFSTOUFS(mp)->um_dev;
0b4d6502 361 error = lfs_iget(ip, (ino_t)ROOTINO, &nip); /* LFS */
7188ac27
KM
362 if (error)
363 return (error);
31593ba7 364 *vpp = ITOV(nip);
7188ac27
KM
365 return (0);
366}
367
368/*
369 * Get file system statistics.
370 */
0b4d6502 371lfs_statfs(mp, sbp, p)
7188ac27
KM
372 struct mount *mp;
373 register struct statfs *sbp;
0eb6f54a 374 struct proc *p;
7188ac27 375{
0b4d6502 376 register LFS *fs;
7188ac27 377 register struct ufsmount *ump;
7188ac27 378
0b4d6502 379printf("lfs_statfs\n");
7188ac27 380 ump = VFSTOUFS(mp);
0b4d6502 381#ifdef NOTLFS /* LFS */
7188ac27
KM
382 fs = ump->um_fs;
383 if (fs->fs_magic != FS_MAGIC)
384 panic("ufs_statfs");
385 sbp->f_type = MOUNT_UFS;
7188ac27
KM
386 sbp->f_fsize = fs->fs_fsize;
387 sbp->f_bsize = fs->fs_bsize;
388 sbp->f_blocks = fs->fs_dsize;
389 sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
390 fs->fs_cstotal.cs_nffree;
391 sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) -
392 (fs->fs_dsize - sbp->f_bfree);
5c41c19e 393 sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
7188ac27 394 sbp->f_ffree = fs->fs_cstotal.cs_nifree;
0b4d6502
KB
395#else
396 fs = ump->um_lfs;
397 if (fs->lfs_magic != LFS_MAGIC)
398 panic("lfs_statfs: magic");
399 sbp->f_type = MOUNT_LFS;
400 sbp->f_fsize = fs->lfs_bsize;
401 sbp->f_bsize = fs->lfs_bsize;
402 sbp->f_blocks = fs->lfs_dsize;
403 sbp->f_bfree = fs->lfs_bfree;
404 sbp->f_bavail = (fs->lfs_dsize * (100 - fs->lfs_minfree) / 100) -
405 (fs->lfs_dsize - sbp->f_bfree);
406 sbp->f_files = fs->lfs_nfiles;
407 sbp->f_ffree = fs->lfs_bfree * INOPB(fs);
408#endif
82161bc8
KM
409 if (sbp != &mp->mnt_stat) {
410 bcopy((caddr_t)mp->mnt_stat.f_mntonname,
d45de50d 411 (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
82161bc8 412 bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
d45de50d
KM
413 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
414 }
7188ac27
KM
415 return (0);
416}
417
0b4d6502 418extern int syncprt; /* LFS */
7188ac27
KM
419
420/*
421 * Go through the disk queues to initiate sandbagged IO;
422 * go through the inodes to write those that have been modified;
423 * initiate the writing of the super block if it has been modified.
8dc876c1
KM
424 *
425 * Note: we are always called with the filesystem marked `MPBUSY'.
7188ac27 426 */
0b4d6502 427lfs_sync(mp, waitfor)
71e4e98b 428 struct mount *mp;
7188ac27 429 int waitfor;
71e4e98b 430{
31593ba7 431 register struct vnode *vp;
7188ac27
KM
432 register struct inode *ip;
433 register struct ufsmount *ump = VFSTOUFS(mp);
434 register struct fs *fs;
812b91f3 435 int error, allerror = 0;
7188ac27 436
0b4d6502 437printf("lfs_sync\n");
7188ac27
KM
438 if (syncprt)
439 bufstats();
0b4d6502 440#ifdef NOTLFS /* LFS */
7188ac27 441 fs = ump->um_fs;
7188ac27
KM
442 /*
443 * Write back modified superblock.
444 * Consistency check that the superblock
445 * is still in the buffer cache.
446 */
447 if (fs->fs_fmod != 0) {
448 if (fs->fs_ronly != 0) { /* XXX */
449 printf("fs = %s\n", fs->fs_fsmnt);
450 panic("update: rofs mod");
451 }
452 fs->fs_fmod = 0;
453 fs->fs_time = time.tv_sec;
881f1b87 454 allerror = sbupdate(ump, waitfor);
7188ac27 455 }
0b4d6502
KB
456#else
457#ifdef DEBUG
458 return (0);
459#else
460 /* LFS IMPLEMENT -- read only access, super-block update */
461 panic("lfs_sync not implemented"); */
462#endif
463#endif
7188ac27
KM
464 /*
465 * Write back each (modified) inode.
466 */
25b5cf58 467loop:
a242f429
KM
468 for (vp = mp->mnt_mounth; vp; vp = vp->v_mountf) {
469 /*
470 * If the vnode that we are about to sync is no longer
471 * associated with this mount point, start over.
472 */
473 if (vp->v_mount != mp)
474 goto loop;
d85a9d1b
KM
475 if (VOP_ISLOCKED(vp))
476 continue;
31593ba7 477 ip = VTOI(vp);
25b5cf58
KM
478 if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0 &&
479 vp->v_dirtyblkhd == NULL)
7188ac27 480 continue;
25b5cf58
KM
481 if (vget(vp))
482 goto loop;
483 if (vp->v_dirtyblkhd)
484 vflushbuf(vp, 0);
485 if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) &&
0b4d6502 486 (error = lfs_iupdat(ip, &time, &time, 0))) /* LFS */
812b91f3
KM
487 allerror = error;
488 vput(vp);
7188ac27 489 }
7188ac27 490 /*
5d96a9ad 491 * Force stale file system control information to be flushed.
7188ac27 492 */
5d96a9ad 493 vflushbuf(ump->um_devvp, waitfor == MNT_WAIT ? B_SYNC : 0);
8dc876c1
KM
494#ifdef QUOTA
495 qsync(mp);
496#endif
812b91f3 497 return (allerror);
7188ac27
KM
498}
499
0b4d6502 500static int
7188ac27
KM
501sbupdate(mp, waitfor)
502 struct ufsmount *mp;
503 int waitfor;
504{
0b4d6502
KB
505 /* LFS IMPLEMENT -- sbupdate */
506 panic("sbupdate not implemented");
7188ac27
KM
507}
508
509/*
510 * File handle to vnode
113c35f2
KM
511 *
512 * Have to be really careful about stale file handles:
513 * - check that the inode number is in range
514 * - call iget() to get the locked inode
515 * - check for an unallocated inode (i_mode == 0)
516 * - check that the generation number matches
7188ac27 517 */
0b4d6502 518lfs_fhtovp(mp, fhp, vpp)
113c35f2 519 register struct mount *mp;
7188ac27
KM
520 struct fid *fhp;
521 struct vnode **vpp;
522{
523 register struct ufid *ufhp;
0b4d6502 524 register struct lfs *fs; /* LFS */
31593ba7 525 register struct inode *ip;
0b4d6502
KB
526 IFILE *ifp;
527 struct buf *bp;
31593ba7
KM
528 struct inode *nip;
529 struct vnode tvp;
7188ac27
KM
530 int error;
531
532 ufhp = (struct ufid *)fhp;
0b4d6502 533#ifdef NOTLFS /* LFS */
113c35f2
KM
534 fs = VFSTOUFS(mp)->um_fs;
535 if (ufhp->ufid_ino < ROOTINO ||
536 ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) {
82161bc8 537 *vpp = NULLVP;
113c35f2
KM
538 return (EINVAL);
539 }
0b4d6502
KB
540#else
541 fs = VFSTOUFS(mp)->um_lfs;
542 if (ufhp->ufid_ino < ROOTINO) {
543 *vpp = NULLVP;
544 return (EINVAL);
545 }
546#endif
31593ba7
KM
547 tvp.v_mount = mp;
548 ip = VTOI(&tvp);
549 ip->i_vnode = &tvp;
550 ip->i_dev = VFSTOUFS(mp)->um_dev;
0b4d6502 551 if (error = lfs_iget(ip, ufhp->ufid_ino, &nip)) { /* LFS */
82161bc8 552 *vpp = NULLVP;
7188ac27
KM
553 return (error);
554 }
31593ba7 555 ip = nip;
113c35f2
KM
556 if (ip->i_mode == 0) {
557 iput(ip);
82161bc8 558 *vpp = NULLVP;
113c35f2
KM
559 return (EINVAL);
560 }
7188ac27
KM
561 if (ip->i_gen != ufhp->ufid_gen) {
562 iput(ip);
82161bc8 563 *vpp = NULLVP;
7188ac27
KM
564 return (EINVAL);
565 }
566 *vpp = ITOV(ip);
567 return (0);
568}