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