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