use dirbad rather than printf
[unix-history] / usr / src / sys / ufs / lfs / lfs_vfsops.c
CommitLineData
da7c5cc6 1/*
7188ac27
KM
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
da7c5cc6 4 *
7188ac27
KM
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 *
812b91f3 17 * @(#)lfs_vfsops.c 7.29 (Berkeley) %G%
da7c5cc6 18 */
71e4e98b 19
94368568
JB
20#include "param.h"
21#include "systm.h"
7188ac27
KM
22#include "time.h"
23#include "kernel.h"
24#include "namei.h"
25#include "vnode.h"
94368568 26#include "mount.h"
7188ac27 27#include "buf.h"
a937f856 28#include "ucred.h"
94368568 29#include "file.h"
ec67a3ce 30#include "disklabel.h"
7188ac27
KM
31#include "ioctl.h"
32#include "errno.h"
4def0c5e 33#include "malloc.h"
7188ac27
KM
34#include "../ufs/fs.h"
35#include "../ufs/ufsmount.h"
36#include "../ufs/inode.h"
609e7cfa
MK
37#include "ioctl.h"
38#include "disklabel.h"
39#include "stat.h"
71e4e98b 40
7188ac27
KM
41/*
42 * ufs vfs operations.
43 */
44int ufs_mount();
5bf9d21f 45int ufs_start();
7188ac27
KM
46int ufs_unmount();
47int ufs_root();
48int ufs_statfs();
49int ufs_sync();
50int ufs_fhtovp();
51int ufs_vptofh();
de0d8667 52int ufs_init();
7188ac27
KM
53
54struct vfsops ufs_vfsops = {
55 ufs_mount,
5bf9d21f 56 ufs_start,
7188ac27
KM
57 ufs_unmount,
58 ufs_root,
59 ufs_statfs,
60 ufs_sync,
61 ufs_fhtovp,
de0d8667
KM
62 ufs_vptofh,
63 ufs_init
7188ac27
KM
64};
65
66/*
67 * ufs mount table.
68 */
69struct ufsmount mounttab[NMOUNT];
70
71/*
d48157d5 72 * Called by vfs_mountroot when ufs is going to be mounted as root.
7188ac27 73 *
d48157d5 74 * Name is updated by mount(8) after booting.
7188ac27 75 */
8a4911ca 76#define ROOTNAME "root_device"
7188ac27
KM
77
78ufs_mountroot()
71e4e98b 79{
7188ac27
KM
80 register struct mount *mp;
81 extern struct vnode *rootvp;
82 struct ufsmount *ump;
71e4e98b 83 register struct fs *fs;
7188ac27
KM
84 u_int size;
85 int error;
71e4e98b 86
7188ac27
KM
87 mp = (struct mount *)malloc((u_long)sizeof(struct mount),
88 M_MOUNT, M_WAITOK);
89 mp->m_op = &ufs_vfsops;
90 mp->m_flag = 0;
91 mp->m_exroot = 0;
31593ba7 92 mp->m_mounth = (struct vnode *)0;
7188ac27
KM
93 error = mountfs(rootvp, mp);
94 if (error) {
95 free((caddr_t)mp, M_MOUNT);
96 return (error);
71e4e98b 97 }
d48157d5 98 if (error = vfs_lock(mp)) {
7188ac27
KM
99 (void)ufs_unmount(mp, 0);
100 free((caddr_t)mp, M_MOUNT);
101 return (error);
6d07f4cd 102 }
d48157d5
KM
103 rootfs = mp;
104 mp->m_next = mp;
105 mp->m_prev = mp;
106 mp->m_vnodecovered = (struct vnode *)0;
7188ac27
KM
107 ump = VFSTOUFS(mp);
108 fs = ump->um_fs;
109 fs->fs_fsmnt[0] = '/';
110 bzero(fs->fs_fsmnt + 1, sizeof(fs->fs_fsmnt) - 1);
111 (void) copystr(ROOTNAME, ump->um_mntname, MNAMELEN - 1, &size);
112 bzero(ump->um_mntname + size, MNAMELEN - size);
113 vfs_unlock(mp);
114 inittodr(fs->fs_time);
115 return (0);
116}
117
118/*
119 * VFS Operations.
120 *
121 * mount system call
122 */
123ufs_mount(mp, path, data, ndp)
124 struct mount *mp;
125 char *path;
126 caddr_t data;
127 struct nameidata *ndp;
128{
129 struct vnode *devvp;
130 struct ufs_args args;
131 struct ufsmount *ump;
132 register struct fs *fs;
133 u_int size;
134 int error;
135
136 if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
137 return (error);
138 if ((error = getmdev(&devvp, args.fspec, ndp)) != 0)
139 return (error);
d48157d5
KM
140 if ((mp->m_flag & M_UPDATE) == 0) {
141 error = mountfs(devvp, mp);
142 } else {
143 ump = VFSTOUFS(mp);
144 fs = ump->um_fs;
145 if (fs->fs_ronly && (mp->m_flag & M_RDONLY) == 0)
146 fs->fs_ronly = 0;
147 /*
148 * Verify that the specified device is the one that
149 * is really being used for the root file system.
150 */
151 if (devvp != ump->um_devvp)
152 error = EINVAL; /* needs translation */
153 }
7188ac27
KM
154 if (error) {
155 vrele(devvp);
156 return (error);
27d00e76 157 }
7188ac27
KM
158 ump = VFSTOUFS(mp);
159 fs = ump->um_fs;
160 (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
161 bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
162 (void) copyinstr(args.fspec, ump->um_mntname, MNAMELEN - 1, &size);
163 bzero(ump->um_mntname + size, MNAMELEN - size);
164 return (0);
71e4e98b
SL
165}
166
7188ac27
KM
167/*
168 * Common code for mount and mountroot
169 */
170mountfs(devvp, mp)
171 struct vnode *devvp;
172 struct mount *mp;
71e4e98b 173{
7188ac27
KM
174 register struct ufsmount *ump;
175 struct ufsmount *fmp = NULL;
176 struct buf *bp = NULL;
71e4e98b 177 register struct fs *fs;
7188ac27 178 dev_t dev = devvp->v_rdev;
ec67a3ce
MK
179 struct partinfo dpart;
180 int havepart = 0, blks;
27d00e76 181 caddr_t base, space;
7188ac27
KM
182 int havepart = 0, blks;
183 int error, i, size;
6d07f4cd 184 int needclose = 0;
7188ac27 185 int ronly = (mp->m_flag & M_RDONLY) != 0;
71e4e98b 186
7188ac27
KM
187 for (ump = &mounttab[0]; ump < &mounttab[NMOUNT]; ump++) {
188 if (ump->um_fs == NULL) {
27d00e76 189 if (fmp == NULL)
7188ac27
KM
190 fmp = ump;
191 } else if (dev == ump->um_dev) {
192 return (EBUSY); /* needs translation */
27d00e76
KM
193 }
194 }
ec67a3ce
MK
195 (*bdevsw[major(dev)].d_open)(dev, ronly ? FREAD : FREAD|FWRITE,
196 S_IFBLK);
27d00e76 197 if (error) {
7188ac27
KM
198 ump->um_fs = NULL;
199 return (error);
27d00e76 200 }
6d07f4cd 201 needclose = 1;
a937f856 202 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED) != 0)
609e7cfa 203 size = DEV_BSIZE;
7188ac27 204 else {
ec67a3ce
MK
205 havepart = 1;
206 size = dpart.disklab->d_secsize;
7188ac27 207 }
a937f856 208 if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) {
7188ac27 209 ump->um_fs = NULL;
71e4e98b 210 goto out;
27d00e76 211 }
e018935f 212 fs = bp->b_un.b_fs;
7188ac27
KM
213 ump->um_fs = NULL;
214 error = EINVAL; /* XXX also needs translation */
1c281610
MK
215 goto out;
216 }
7188ac27 217 ump->um_fs = (struct fs *)malloc((u_long)fs->fs_sbsize, M_SUPERBLK,
5adcb337 218 M_WAITOK);
7188ac27 219 bcopy((caddr_t)bp->b_un.b_addr, (caddr_t)ump->um_fs,
71e4e98b 220 (u_int)fs->fs_sbsize);
e018935f
MK
221 brelse(bp);
222 bp = NULL;
7188ac27
KM
223 fs = ump->um_fs;
224 fs->fs_ronly = ronly;
71e4e98b
SL
225 if (ronly == 0)
226 fs->fs_fmod = 1;
609e7cfa
MK
227 if (havepart) {
228 dpart.part->p_fstype = FS_BSDFFS;
229 dpart.part->p_fsize = fs->fs_fsize;
230 dpart.part->p_frag = fs->fs_frag;
42ff4c2e 231 dpart.part->p_cpg = fs->fs_cpg;
609e7cfa 232 }
ec67a3ce
MK
233#ifdef SECSIZE
234 /*
235 * If we have a disk label, force per-partition
236 * filesystem information to be correct
237 * and set correct current fsbtodb shift.
238 */
239#endif SECSIZE
240 if (havepart) {
241 dpart.part->p_fstype = FS_BSDFFS;
242 dpart.part->p_fsize = fs->fs_fsize;
243 dpart.part->p_frag = fs->fs_frag;
244#ifdef SECSIZE
245#ifdef tahoe
246 /*
247 * Save the original fsbtodb shift to restore on updates.
248 * (Console doesn't understand fsbtodb changes.)
249 */
250 fs->fs_sparecon[0] = fs->fs_fsbtodb;
251#endif
252 i = fs->fs_fsize / size;
253 for (fs->fs_fsbtodb = 0; i > 1; i >>= 1)
254 fs->fs_fsbtodb++;
255#endif SECSIZE
256 fs->fs_dbsize = size;
257 }
71e4e98b 258 blks = howmany(fs->fs_cssize, fs->fs_fsize);
5adcb337
KM
259 base = space = (caddr_t)malloc((u_long)fs->fs_cssize, M_SUPERBLK,
260 M_WAITOK);
71e4e98b
SL
261 for (i = 0; i < blks; i += fs->fs_frag) {
262 size = fs->fs_bsize;
263 if (i + fs->fs_frag > blks)
264 size = (blks - i) * fs->fs_fsize;
ec67a3ce
MK
265#ifdef SECSIZE
266 tp = bread(dev, fsbtodb(fs, fs->fs_csaddr + i), size,
267 fs->fs_dbsize);
268#else SECSIZE
a937f856
KM
269 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
270 NOCRED, &bp);
7188ac27 271 if (error) {
5adcb337 272 free((caddr_t)base, M_SUPERBLK);
71e4e98b
SL
273 goto out;
274 }
e018935f 275 bcopy((caddr_t)bp->b_un.b_addr, space, (u_int)size);
60f9c9e3 276 fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space;
71e4e98b 277 space += size;
e018935f
MK
278 brelse(bp);
279 bp = NULL;
71e4e98b 280 }
7188ac27
KM
281 mp->m_data = (qaddr_t)ump;
282 mp->m_bsize = fs->fs_bsize;
283 mp->m_fsize = fs->fs_fsize;
284 mp->m_fsid.val[0] = (long)dev;
285 mp->m_fsid.val[1] = MOUNT_UFS;
286 ump->um_mountp = mp;
287 ump->um_dev = dev;
288 ump->um_devvp = devvp;
289 ump->um_qinod = NULL;
a937f856 290 devvp->v_mount = mp;
7188ac27 291
94354803
KM
292 /* Sanity checks for old file systems. XXX */
293 fs->fs_npsect = MAX(fs->fs_npsect, fs->fs_nsect); /* XXX */
294 fs->fs_interleave = MAX(fs->fs_interleave, 1); /* XXX */
2af59000
KM
295 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
296 fs->fs_nrpos = 8; /* XXX */
609e7cfa 297
7188ac27 298 return (0);
71e4e98b 299out:
609e7cfa 300 if (needclose)
a937f856 301 (void) VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED);
7188ac27
KM
302 if (ump->um_fs) {
303 free((caddr_t)ump->um_fs, M_SUPERBLK);
304 ump->um_fs = NULL;
27d00e76 305 }
e018935f
MK
306 if (bp)
307 brelse(bp);
7188ac27 308 return (error);
71e4e98b
SL
309}
310
5bf9d21f
KM
311/*
312 * Make a filesystem operational.
313 * Nothing to do at the moment.
314 */
31593ba7 315/* ARGSUSED */
5bf9d21f
KM
316ufs_start(mp, flags)
317 struct mount *mp;
318 int flags;
319{
320
321 return (0);
322}
71e4e98b 323
7188ac27
KM
324/*
325 * unmount system call
326 */
327ufs_unmount(mp, flags)
328 struct mount *mp;
329 int flags;
71e4e98b 330{
7188ac27 331 register struct ufsmount *ump;
71e4e98b 332 register struct fs *fs;
7188ac27 333 int error, ronly;
71e4e98b 334
7188ac27
KM
335 if (flags & MNT_FORCE)
336 return (EINVAL);
337 ump = VFSTOUFS(mp);
2309ea70 338 if (error = vflush(mp, ITOV(ump->um_qinod), flags))
ec67a3ce 339 return (error);
71e4e98b 340#ifdef QUOTA
31593ba7 341 (void) closedq(ump);
71e4e98b 342 /*
ec67a3ce 343 * A drag, but it would be ugly to cheat, & this doesn't happen often.
71e4e98b 344 */
2309ea70
KM
345 if (vflush(mp, (struct vnode *)NULL, MNT_NOFORCE))
346 panic("ufs_unmount: quota");
71e4e98b 347#endif
7188ac27
KM
348 fs = ump->um_fs;
349 ronly = !fs->fs_ronly;
4def0c5e 350 free((caddr_t)fs->fs_csp[0], M_SUPERBLK);
ec67a3ce
MK
351 error = closei(dev, IFBLK, fs->fs_ronly? FREAD : FREAD|FWRITE);
352 irele(ip);
353 return (error);
71e4e98b
SL
354}
355
7188ac27
KM
356/*
357 * Return root of a filesystem
358 */
359ufs_root(mp, vpp)
360 struct mount *mp;
361 struct vnode **vpp;
362{
31593ba7
KM
363 register struct inode *ip;
364 struct inode *nip;
365 struct vnode tvp;
7188ac27
KM
366 int error;
367
31593ba7
KM
368 tvp.v_mount = mp;
369 ip = VTOI(&tvp);
370 ip->i_vnode = &tvp;
371 ip->i_dev = VFSTOUFS(mp)->um_dev;
372 error = iget(ip, (ino_t)ROOTINO, &nip);
7188ac27
KM
373 if (error)
374 return (error);
31593ba7 375 *vpp = ITOV(nip);
7188ac27
KM
376 return (0);
377}
378
379/*
380 * Get file system statistics.
381 */
382ufs_statfs(mp, sbp)
383 struct mount *mp;
384 register struct statfs *sbp;
385{
386 register struct ufsmount *ump;
387 register struct fs *fs;
388
389 ump = VFSTOUFS(mp);
390 fs = ump->um_fs;
391 if (fs->fs_magic != FS_MAGIC)
392 panic("ufs_statfs");
393 sbp->f_type = MOUNT_UFS;
7188ac27
KM
394 sbp->f_fsize = fs->fs_fsize;
395 sbp->f_bsize = fs->fs_bsize;
396 sbp->f_blocks = fs->fs_dsize;
397 sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
398 fs->fs_cstotal.cs_nffree;
399 sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) -
400 (fs->fs_dsize - sbp->f_bfree);
5c41c19e 401 sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
7188ac27 402 sbp->f_ffree = fs->fs_cstotal.cs_nifree;
7188ac27
KM
403 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
404 bcopy((caddr_t)ump->um_mntname, (caddr_t)&sbp->f_mntfromname[0],
405 MNAMELEN);
406 return (0);
407}
408
409int syncprt = 0;
410
411/*
412 * Go through the disk queues to initiate sandbagged IO;
413 * go through the inodes to write those that have been modified;
414 * initiate the writing of the super block if it has been modified.
415 */
416ufs_sync(mp, waitfor)
71e4e98b 417 struct mount *mp;
7188ac27 418 int waitfor;
71e4e98b 419{
31593ba7 420 register struct vnode *vp;
7188ac27
KM
421 register struct inode *ip;
422 register struct ufsmount *ump = VFSTOUFS(mp);
423 register struct fs *fs;
812b91f3 424 int error, allerror = 0;
7188ac27
KM
425 static int updlock = 0;
426
427 if (syncprt)
428 bufstats();
429 if (updlock)
430 return (EBUSY);
431 fs = ump->um_fs;
432 if (fs == (struct fs *)1)
433 return (0);
434 updlock++;
435 /*
436 * Write back modified superblock.
437 * Consistency check that the superblock
438 * is still in the buffer cache.
439 */
440 if (fs->fs_fmod != 0) {
441 if (fs->fs_ronly != 0) { /* XXX */
442 printf("fs = %s\n", fs->fs_fsmnt);
443 panic("update: rofs mod");
444 }
445 fs->fs_fmod = 0;
446 fs->fs_time = time.tv_sec;
447 error = sbupdate(ump, waitfor);
448 }
449 /*
450 * Write back each (modified) inode.
451 */
31593ba7
KM
452 for (vp = mp->m_mounth; vp; vp = vp->v_mountf) {
453 ip = VTOI(vp);
812b91f3 454 if ((ip->i_flag & ILOCKED) != 0 || vp->v_count == 0 ||
7188ac27
KM
455 (ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0)
456 continue;
31593ba7 457 VREF(vp);
812b91f3
KM
458 VOP_LOCK(vp);
459 if (error = VOP_FSYNC(vp, 0, NOCRED, waitfor))
460 allerror = error;
461 vput(vp);
7188ac27
KM
462 }
463 updlock = 0;
464 /*
465 * Force stale buffer cache information to be flushed.
466 */
a937f856 467 bflush(ump->um_devvp->v_mount);
812b91f3 468 return (allerror);
7188ac27
KM
469}
470
471/*
472 * Write a superblock and associated information back to disk.
473 */
474sbupdate(mp, waitfor)
475 struct ufsmount *mp;
476 int waitfor;
477{
478 register struct fs *fs = mp->um_fs;
71e4e98b
SL
479 register struct buf *bp;
480 int blks;
481 caddr_t space;
7188ac27 482 int i, size, error = 0;
71e4e98b 483
ec67a3ce
MK
484#ifdef SECSIZE
485 bp = getblk(mp->m_dev, (daddr_t)fsbtodb(fs, SBOFF / fs->fs_fsize),
486 (int)fs->fs_sbsize, fs->fs_dbsize);
487#else SECSIZE
7188ac27 488 bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize);
ec67a3ce 489#endif SECSIZE
71e4e98b 490 bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize);
2af59000
KM
491 /* Restore compatibility to old file systems. XXX */
492 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
493 bp->b_un.b_fs->fs_nrpos = -1; /* XXX */
ec67a3ce
MK
494#ifdef SECSIZE
495#ifdef tahoe
496 /* restore standard fsbtodb shift */
497 bp->b_un.b_fs->fs_fsbtodb = fs->fs_sparecon[0];
498 bp->b_un.b_fs->fs_sparecon[0] = 0;
499#endif
500#endif SECSIZE
7188ac27
KM
501 if (waitfor == MNT_WAIT)
502 error = bwrite(bp);
503 else
504 bawrite(bp);
71e4e98b
SL
505 blks = howmany(fs->fs_cssize, fs->fs_fsize);
506 space = (caddr_t)fs->fs_csp[0];
507 for (i = 0; i < blks; i += fs->fs_frag) {
508 size = fs->fs_bsize;
509 if (i + fs->fs_frag > blks)
510 size = (blks - i) * fs->fs_fsize;
ec67a3ce
MK
511#ifdef SECSIZE
512 bp = getblk(mp->m_dev, fsbtodb(fs, fs->fs_csaddr + i), size,
513 fs->fs_dbsize);
514#else SECSIZE
7188ac27 515 bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), size);
ec67a3ce 516#endif SECSIZE
71e4e98b
SL
517 bcopy(space, bp->b_un.b_addr, (u_int)size);
518 space += size;
7188ac27
KM
519 if (waitfor == MNT_WAIT)
520 error = bwrite(bp);
521 else
522 bawrite(bp);
71e4e98b 523 }
7188ac27 524 return (error);
71e4e98b
SL
525}
526
527/*
7188ac27
KM
528 * Print out statistics on the current allocation of the buffer pool.
529 * Can be enabled to print out on every ``sync'' by setting "syncprt"
530 * above.
531 */
532bufstats()
533{
534 int s, i, j, count;
535 register struct buf *bp, *dp;
536 int counts[MAXBSIZE/CLBYTES+1];
537 static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" };
538
539 for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) {
540 count = 0;
541 for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
542 counts[j] = 0;
543 s = splbio();
544 for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) {
545 counts[dp->b_bufsize/CLBYTES]++;
546 count++;
547 }
548 splx(s);
549 printf("%s: total-%d", bname[i], count);
550 for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
551 if (counts[j] != 0)
552 printf(", %d-%d", j * CLBYTES, counts[j]);
553 printf("\n");
554 }
555}
556
557/*
558 * File handle to vnode
113c35f2
KM
559 *
560 * Have to be really careful about stale file handles:
561 * - check that the inode number is in range
562 * - call iget() to get the locked inode
563 * - check for an unallocated inode (i_mode == 0)
564 * - check that the generation number matches
7188ac27
KM
565 */
566ufs_fhtovp(mp, fhp, vpp)
113c35f2 567 register struct mount *mp;
7188ac27
KM
568 struct fid *fhp;
569 struct vnode **vpp;
570{
571 register struct ufid *ufhp;
113c35f2 572 register struct fs *fs;
31593ba7
KM
573 register struct inode *ip;
574 struct inode *nip;
575 struct vnode tvp;
7188ac27
KM
576 int error;
577
578 ufhp = (struct ufid *)fhp;
113c35f2
KM
579 fs = VFSTOUFS(mp)->um_fs;
580 if (ufhp->ufid_ino < ROOTINO ||
581 ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) {
582 *vpp = (struct vnode *)0;
583 return (EINVAL);
584 }
31593ba7
KM
585 tvp.v_mount = mp;
586 ip = VTOI(&tvp);
587 ip->i_vnode = &tvp;
588 ip->i_dev = VFSTOUFS(mp)->um_dev;
589 if (error = iget(ip, ufhp->ufid_ino, &nip)) {
113c35f2 590 *vpp = (struct vnode *)0;
7188ac27
KM
591 return (error);
592 }
31593ba7 593 ip = nip;
113c35f2
KM
594 if (ip->i_mode == 0) {
595 iput(ip);
596 *vpp = (struct vnode *)0;
597 return (EINVAL);
598 }
7188ac27
KM
599 if (ip->i_gen != ufhp->ufid_gen) {
600 iput(ip);
113c35f2 601 *vpp = (struct vnode *)0;
7188ac27
KM
602 return (EINVAL);
603 }
604 *vpp = ITOV(ip);
605 return (0);
606}
607
608/*
29e77c27 609 * Vnode pointer to File handle
7188ac27
KM
610 */
611/* ARGSUSED */
758e3529
KM
612ufs_vptofh(vp, fhp)
613 struct vnode *vp;
7188ac27 614 struct fid *fhp;
7188ac27 615{
758e3529
KM
616 register struct inode *ip = VTOI(vp);
617 register struct ufid *ufhp;
7188ac27 618
758e3529
KM
619 ufhp = (struct ufid *)fhp;
620 ufhp->ufid_len = sizeof(struct ufid);
621 ufhp->ufid_ino = ip->i_number;
622 ufhp->ufid_gen = ip->i_gen;
623 return (0);
7188ac27
KM
624}
625
626/*
627 * Common code for mount and quota.
71e4e98b
SL
628 * Check that the user's argument is a reasonable
629 * thing on which to mount, and return the device number if so.
630 */
7188ac27
KM
631getmdev(devvpp, fname, ndp)
632 struct vnode **devvpp;
715baff1 633 caddr_t fname;
7188ac27 634 register struct nameidata *ndp;
71e4e98b 635{
7188ac27
KM
636 register struct vnode *vp;
637 int error;
71e4e98b 638
7188ac27 639 ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW;
715baff1
KM
640 ndp->ni_segflg = UIO_USERSPACE;
641 ndp->ni_dirp = fname;
7188ac27
KM
642 if (error = namei(ndp)) {
643 if (error == ENOENT)
644 return (ENODEV); /* needs translation */
645 return (error);
6d07f4cd 646 }
7188ac27
KM
647 vp = ndp->ni_vp;
648 if (vp->v_type != VBLK) {
649 vput(vp);
71e4e98b 650 return (ENOTBLK);
e95cdf5c 651 }
e547d435
KM
652 if (major(vp->v_rdev) >= nblkdev) {
653 vput(vp);
71e4e98b 654 return (ENXIO);
e547d435 655 }
7188ac27
KM
656 iunlock(VTOI(vp));
657 *devvpp = vp;
71e4e98b
SL
658 return (0);
659}