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