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