add proc pointers to appropriate VOP and vnode operations
[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 *
b702c21d 5 * %sccs.include.redist.c%
7188ac27 6 *
c6f5111d 7 * @(#)lfs_vfsops.c 7.51 (Berkeley) %G%
da7c5cc6 8 */
71e4e98b 9
94368568
JB
10#include "param.h"
11#include "systm.h"
c6f5111d 12#include "namei.h"
8dc876c1 13#include "proc.h"
7188ac27 14#include "kernel.h"
7188ac27 15#include "vnode.h"
0f93ba7b 16#include "specdev.h"
94368568 17#include "mount.h"
7188ac27 18#include "buf.h"
94368568 19#include "file.h"
ec67a3ce 20#include "disklabel.h"
7188ac27
KM
21#include "ioctl.h"
22#include "errno.h"
4def0c5e 23#include "malloc.h"
609e7cfa
MK
24#include "ioctl.h"
25#include "disklabel.h"
26#include "stat.h"
71e4e98b 27
c6f5111d
MK
28#include "quota.h"
29#include "fs.h"
30#include "ufsmount.h"
31#include "inode.h"
32
7188ac27
KM
33/*
34 * ufs vfs operations.
35 */
36int ufs_mount();
5bf9d21f 37int ufs_start();
7188ac27
KM
38int ufs_unmount();
39int ufs_root();
8dc876c1 40int ufs_quotactl();
7188ac27
KM
41int ufs_statfs();
42int ufs_sync();
43int ufs_fhtovp();
44int ufs_vptofh();
de0d8667 45int ufs_init();
7188ac27
KM
46
47struct vfsops ufs_vfsops = {
48 ufs_mount,
5bf9d21f 49 ufs_start,
7188ac27
KM
50 ufs_unmount,
51 ufs_root,
8dc876c1 52 ufs_quotactl,
7188ac27
KM
53 ufs_statfs,
54 ufs_sync,
55 ufs_fhtovp,
de0d8667
KM
56 ufs_vptofh,
57 ufs_init
7188ac27
KM
58};
59
7188ac27 60/*
d48157d5 61 * Called by vfs_mountroot when ufs is going to be mounted as root.
7188ac27 62 *
d48157d5 63 * Name is updated by mount(8) after booting.
7188ac27 64 */
8a4911ca 65#define ROOTNAME "root_device"
7188ac27
KM
66
67ufs_mountroot()
71e4e98b 68{
7188ac27
KM
69 register struct mount *mp;
70 extern struct vnode *rootvp;
71 struct ufsmount *ump;
71e4e98b 72 register struct fs *fs;
7188ac27
KM
73 u_int size;
74 int error;
71e4e98b 75
7188ac27
KM
76 mp = (struct mount *)malloc((u_long)sizeof(struct mount),
77 M_MOUNT, M_WAITOK);
82161bc8
KM
78 mp->mnt_op = &ufs_vfsops;
79 mp->mnt_flag = MNT_RDONLY;
80 mp->mnt_exroot = 0;
81 mp->mnt_mounth = NULLVP;
7188ac27
KM
82 error = mountfs(rootvp, mp);
83 if (error) {
84 free((caddr_t)mp, M_MOUNT);
85 return (error);
71e4e98b 86 }
d48157d5 87 if (error = vfs_lock(mp)) {
7188ac27
KM
88 (void)ufs_unmount(mp, 0);
89 free((caddr_t)mp, M_MOUNT);
90 return (error);
6d07f4cd 91 }
d48157d5 92 rootfs = mp;
82161bc8
KM
93 mp->mnt_next = mp;
94 mp->mnt_prev = mp;
95 mp->mnt_vnodecovered = NULLVP;
7188ac27
KM
96 ump = VFSTOUFS(mp);
97 fs = ump->um_fs;
d45de50d 98 bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt));
7188ac27 99 fs->fs_fsmnt[0] = '/';
82161bc8
KM
100 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
101 MNAMELEN);
102 (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
103 &size);
104 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
105 (void) ufs_statfs(mp, &mp->mnt_stat);
7188ac27
KM
106 vfs_unlock(mp);
107 inittodr(fs->fs_time);
108 return (0);
109}
110
111/*
112 * VFS Operations.
113 *
114 * mount system call
115 */
116ufs_mount(mp, path, data, ndp)
d45de50d 117 register struct mount *mp;
7188ac27
KM
118 char *path;
119 caddr_t data;
120 struct nameidata *ndp;
121{
122 struct vnode *devvp;
123 struct ufs_args args;
124 struct ufsmount *ump;
125 register struct fs *fs;
126 u_int size;
127 int error;
128
129 if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
130 return (error);
3b931949
KM
131 /*
132 * Process export requests.
133 */
82161bc8
KM
134 if ((args.exflags & MNT_EXPORTED) || (mp->mnt_flag & MNT_EXPORTED)) {
135 if (args.exflags & MNT_EXPORTED)
136 mp->mnt_flag |= MNT_EXPORTED;
3b931949 137 else
82161bc8
KM
138 mp->mnt_flag &= ~MNT_EXPORTED;
139 if (args.exflags & MNT_EXRDONLY)
140 mp->mnt_flag |= MNT_EXRDONLY;
3b931949 141 else
82161bc8
KM
142 mp->mnt_flag &= ~MNT_EXRDONLY;
143 mp->mnt_exroot = args.exroot;
3b931949 144 }
82161bc8 145 if ((mp->mnt_flag & MNT_UPDATE) == 0) {
3b931949
KM
146 if ((error = getmdev(&devvp, args.fspec, ndp)) != 0)
147 return (error);
d48157d5
KM
148 error = mountfs(devvp, mp);
149 } else {
150 ump = VFSTOUFS(mp);
151 fs = ump->um_fs;
82161bc8 152 if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0)
d48157d5
KM
153 fs->fs_ronly = 0;
154 /*
155 * Verify that the specified device is the one that
156 * is really being used for the root file system.
157 */
3b931949
KM
158 if (args.fspec == 0)
159 return (0);
160 if ((error = getmdev(&devvp, args.fspec, ndp)) != 0)
161 return (error);
d48157d5
KM
162 if (devvp != ump->um_devvp)
163 error = EINVAL; /* needs translation */
2a7dbb09
KM
164 else
165 vrele(devvp);
d48157d5 166 }
7188ac27
KM
167 if (error) {
168 vrele(devvp);
169 return (error);
27d00e76 170 }
7188ac27
KM
171 ump = VFSTOUFS(mp);
172 fs = ump->um_fs;
173 (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
174 bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
82161bc8
KM
175 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
176 MNAMELEN);
177 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
178 &size);
179 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
180 (void) ufs_statfs(mp, &mp->mnt_stat);
7188ac27 181 return (0);
71e4e98b
SL
182}
183
7188ac27
KM
184/*
185 * Common code for mount and mountroot
186 */
187mountfs(devvp, mp)
1182ae61 188 register struct vnode *devvp;
7188ac27 189 struct mount *mp;
71e4e98b 190{
8dc876c1 191 register struct ufsmount *ump = (struct ufsmount *)0;
7188ac27 192 struct buf *bp = NULL;
71e4e98b 193 register struct fs *fs;
7188ac27 194 dev_t dev = devvp->v_rdev;
ec67a3ce
MK
195 struct partinfo dpart;
196 int havepart = 0, blks;
27d00e76 197 caddr_t base, space;
7188ac27
KM
198 int havepart = 0, blks;
199 int error, i, size;
6d07f4cd 200 int needclose = 0;
82161bc8 201 int ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
1c26e003 202 extern struct vnode *rootvp;
71e4e98b 203
8dc876c1 204 if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED))
7188ac27 205 return (error);
6d07f4cd 206 needclose = 1;
8dc876c1 207 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED) != 0) {
609e7cfa 208 size = DEV_BSIZE;
8dc876c1 209 } else {
ec67a3ce
MK
210 havepart = 1;
211 size = dpart.disklab->d_secsize;
7188ac27 212 }
8dc876c1 213 if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp))
71e4e98b 214 goto out;
e018935f 215 fs = bp->b_un.b_fs;
8dc876c1 216 error = EINVAL; /* XXX needs translation */
1c281610
MK
217 goto out;
218 }
8dc876c1 219 ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
7188ac27 220 ump->um_fs = (struct fs *)malloc((u_long)fs->fs_sbsize, M_SUPERBLK,
5adcb337 221 M_WAITOK);
7188ac27 222 bcopy((caddr_t)bp->b_un.b_addr, (caddr_t)ump->um_fs,
71e4e98b 223 (u_int)fs->fs_sbsize);
5d96a9ad
KM
224 if (fs->fs_sbsize < SBSIZE)
225 bp->b_flags |= B_INVAL;
e018935f
MK
226 brelse(bp);
227 bp = NULL;
7188ac27
KM
228 fs = ump->um_fs;
229 fs->fs_ronly = ronly;
71e4e98b
SL
230 if (ronly == 0)
231 fs->fs_fmod = 1;
609e7cfa
MK
232 if (havepart) {
233 dpart.part->p_fstype = FS_BSDFFS;
234 dpart.part->p_fsize = fs->fs_fsize;
235 dpart.part->p_frag = fs->fs_frag;
42ff4c2e 236 dpart.part->p_cpg = fs->fs_cpg;
609e7cfa 237 }
ec67a3ce
MK
238#ifdef SECSIZE
239 /*
240 * If we have a disk label, force per-partition
241 * filesystem information to be correct
242 * and set correct current fsbtodb shift.
243 */
244#endif SECSIZE
245 if (havepart) {
246 dpart.part->p_fstype = FS_BSDFFS;
247 dpart.part->p_fsize = fs->fs_fsize;
248 dpart.part->p_frag = fs->fs_frag;
249#ifdef SECSIZE
250#ifdef tahoe
251 /*
252 * Save the original fsbtodb shift to restore on updates.
253 * (Console doesn't understand fsbtodb changes.)
254 */
255 fs->fs_sparecon[0] = fs->fs_fsbtodb;
256#endif
257 i = fs->fs_fsize / size;
258 for (fs->fs_fsbtodb = 0; i > 1; i >>= 1)
259 fs->fs_fsbtodb++;
260#endif SECSIZE
261 fs->fs_dbsize = size;
262 }
71e4e98b 263 blks = howmany(fs->fs_cssize, fs->fs_fsize);
5adcb337
KM
264 base = space = (caddr_t)malloc((u_long)fs->fs_cssize, M_SUPERBLK,
265 M_WAITOK);
71e4e98b
SL
266 for (i = 0; i < blks; i += fs->fs_frag) {
267 size = fs->fs_bsize;
268 if (i + fs->fs_frag > blks)
269 size = (blks - i) * fs->fs_fsize;
ec67a3ce
MK
270#ifdef SECSIZE
271 tp = bread(dev, fsbtodb(fs, fs->fs_csaddr + i), size,
272 fs->fs_dbsize);
273#else SECSIZE
a937f856
KM
274 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
275 NOCRED, &bp);
7188ac27 276 if (error) {
5adcb337 277 free((caddr_t)base, M_SUPERBLK);
71e4e98b
SL
278 goto out;
279 }
e018935f 280 bcopy((caddr_t)bp->b_un.b_addr, space, (u_int)size);
60f9c9e3 281 fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space;
71e4e98b 282 space += size;
e018935f
MK
283 brelse(bp);
284 bp = NULL;
71e4e98b 285 }
82161bc8
KM
286 mp->mnt_data = (qaddr_t)ump;
287 mp->mnt_stat.f_fsid.val[0] = (long)dev;
288 mp->mnt_stat.f_fsid.val[1] = MOUNT_UFS;
289 mp->mnt_flag |= MNT_LOCAL;
7188ac27
KM
290 ump->um_mountp = mp;
291 ump->um_dev = dev;
292 ump->um_devvp = devvp;
8dc876c1
KM
293 for (i = 0; i < MAXQUOTAS; i++)
294 ump->um_quotas[i] = NULLVP;
0f93ba7b 295 devvp->v_specflags |= SI_MOUNTEDON;
7188ac27 296
94354803
KM
297 /* Sanity checks for old file systems. XXX */
298 fs->fs_npsect = MAX(fs->fs_npsect, fs->fs_nsect); /* XXX */
299 fs->fs_interleave = MAX(fs->fs_interleave, 1); /* XXX */
2af59000
KM
300 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
301 fs->fs_nrpos = 8; /* XXX */
609e7cfa 302
7188ac27 303 return (0);
71e4e98b 304out:
c86c9b6e
KM
305 if (bp)
306 brelse(bp);
609e7cfa 307 if (needclose)
a937f856 308 (void) VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED);
8dc876c1 309 if (ump) {
7188ac27 310 free((caddr_t)ump->um_fs, M_SUPERBLK);
8dc876c1 311 free((caddr_t)ump, M_UFSMNT);
82161bc8 312 mp->mnt_data = (qaddr_t)0;
27d00e76 313 }
7188ac27 314 return (error);
71e4e98b
SL
315}
316
5bf9d21f
KM
317/*
318 * Make a filesystem operational.
319 * Nothing to do at the moment.
320 */
31593ba7 321/* ARGSUSED */
5bf9d21f
KM
322ufs_start(mp, flags)
323 struct mount *mp;
324 int flags;
325{
326
327 return (0);
328}
71e4e98b 329
7188ac27
KM
330/*
331 * unmount system call
332 */
8dc876c1 333ufs_unmount(mp, mntflags)
7188ac27 334 struct mount *mp;
8dc876c1 335 int mntflags;
71e4e98b 336{
7188ac27 337 register struct ufsmount *ump;
71e4e98b 338 register struct fs *fs;
8dc876c1 339 int i, error, ronly, flags = 0;
71e4e98b 340
8dc876c1 341 if (mntflags & MNT_FORCE)
7188ac27 342 return (EINVAL);
8dc876c1
KM
343 if (mntflags & MNT_FORCE)
344 flags |= FORCECLOSE;
5d96a9ad
KM
345 mntflushbuf(mp, 0);
346 if (mntinvalbuf(mp))
347 return (EBUSY);
7188ac27 348 ump = VFSTOUFS(mp);
ec67a3ce 349 return (error);
71e4e98b 350#ifdef QUOTA
82161bc8 351 if (mp->mnt_flag & MNT_QUOTA) {
8dc876c1 352 if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags))
6d943995 353 return (error);
8dc876c1
KM
354 for (i = 0; i < MAXQUOTAS; i++) {
355 if (ump->um_quotas[i] == NULLVP)
356 continue;
357 quotaoff(mp, i);
358 }
6d943995 359 /*
8dc876c1
KM
360 * Here we fall through to vflush again to ensure
361 * that we have gotten rid of all the system vnodes.
6d943995 362 */
8dc876c1 363 }
71e4e98b 364#endif
8dc876c1 365 if (error = vflush(mp, NULLVP, flags))
6d943995 366 return (error);
7188ac27
KM
367 fs = ump->um_fs;
368 ronly = !fs->fs_ronly;
ec67a3ce
MK
369 error = closei(dev, IFBLK, fs->fs_ronly? FREAD : FREAD|FWRITE);
370 irele(ip);
371 return (error);
71e4e98b
SL
372}
373
7188ac27
KM
374/*
375 * Return root of a filesystem
376 */
377ufs_root(mp, vpp)
378 struct mount *mp;
379 struct vnode **vpp;
380{
31593ba7
KM
381 register struct inode *ip;
382 struct inode *nip;
383 struct vnode tvp;
7188ac27
KM
384 int error;
385
31593ba7
KM
386 tvp.v_mount = mp;
387 ip = VTOI(&tvp);
388 ip->i_vnode = &tvp;
389 ip->i_dev = VFSTOUFS(mp)->um_dev;
390 error = iget(ip, (ino_t)ROOTINO, &nip);
7188ac27
KM
391 if (error)
392 return (error);
31593ba7 393 *vpp = ITOV(nip);
7188ac27
KM
394 return (0);
395}
396
8dc876c1
KM
397/*
398 * Do operations associated with quotas
399 */
400ufs_quotactl(mp, cmds, uid, arg)
401 struct mount *mp;
402 int cmds;
403 uid_t uid;
404 caddr_t arg;
405{
8dc876c1 406 struct ufsmount *ump = VFSTOUFS(mp);
c6f5111d 407 struct proc *p = curproc; /* XXX */
8dc876c1
KM
408 int cmd, type, error;
409
410#ifndef QUOTA
411 return (EOPNOTSUPP);
412#else
413 if (uid == -1)
c6f5111d 414 uid = p->p_cred->p_ruid;
8dc876c1
KM
415 cmd = cmds >> SUBCMDSHIFT;
416
417 switch (cmd) {
418 case Q_GETQUOTA:
419 case Q_SYNC:
c6f5111d 420 if (uid == p->p_cred->p_ruid)
8dc876c1
KM
421 break;
422 /* fall through */
423 default:
c6f5111d 424 if (error = suser(p->p_ucred, &p->p_acflag))
8dc876c1
KM
425 return (error);
426 }
427
428 type = cmd & SUBCMDMASK;
429 if ((u_int)type >= MAXQUOTAS)
430 return (EINVAL);
431
432 switch (cmd) {
433
434 case Q_QUOTAON:
c6f5111d 435 return (quotaon(p, mp, type, arg));
8dc876c1
KM
436
437 case Q_QUOTAOFF:
438 if (vfs_busy(mp))
439 return (0);
440 error = quotaoff(mp, type);
441 vfs_unbusy(mp);
442 return (error);
443
444 case Q_SETQUOTA:
445 return (setquota(mp, uid, type, arg));
446
447 case Q_SETUSE:
448 return (setuse(mp, uid, type, arg));
449
450 case Q_GETQUOTA:
451 return (getquota(mp, uid, type, arg));
452
453 case Q_SYNC:
454 if (vfs_busy(mp))
455 return (0);
456 error = qsync(mp);
457 vfs_unbusy(mp);
458 return (error);
459
460 default:
461 return (EINVAL);
462 }
463 /* NOTREACHED */
464#endif
465}
466
7188ac27
KM
467/*
468 * Get file system statistics.
469 */
470ufs_statfs(mp, sbp)
471 struct mount *mp;
472 register struct statfs *sbp;
473{
474 register struct ufsmount *ump;
475 register struct fs *fs;
476
477 ump = VFSTOUFS(mp);
478 fs = ump->um_fs;
479 if (fs->fs_magic != FS_MAGIC)
480 panic("ufs_statfs");
481 sbp->f_type = MOUNT_UFS;
7188ac27
KM
482 sbp->f_fsize = fs->fs_fsize;
483 sbp->f_bsize = fs->fs_bsize;
484 sbp->f_blocks = fs->fs_dsize;
485 sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
486 fs->fs_cstotal.cs_nffree;
487 sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) -
488 (fs->fs_dsize - sbp->f_bfree);
5c41c19e 489 sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
7188ac27 490 sbp->f_ffree = fs->fs_cstotal.cs_nifree;
82161bc8
KM
491 if (sbp != &mp->mnt_stat) {
492 bcopy((caddr_t)mp->mnt_stat.f_mntonname,
d45de50d 493 (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
82161bc8 494 bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
d45de50d
KM
495 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
496 }
7188ac27
KM
497 return (0);
498}
499
500int syncprt = 0;
501
502/*
503 * Go through the disk queues to initiate sandbagged IO;
504 * go through the inodes to write those that have been modified;
505 * initiate the writing of the super block if it has been modified.
8dc876c1
KM
506 *
507 * Note: we are always called with the filesystem marked `MPBUSY'.
7188ac27
KM
508 */
509ufs_sync(mp, waitfor)
71e4e98b 510 struct mount *mp;
7188ac27 511 int waitfor;
71e4e98b 512{
31593ba7 513 register struct vnode *vp;
7188ac27
KM
514 register struct inode *ip;
515 register struct ufsmount *ump = VFSTOUFS(mp);
516 register struct fs *fs;
812b91f3 517 int error, allerror = 0;
7188ac27
KM
518
519 if (syncprt)
520 bufstats();
7188ac27 521 fs = ump->um_fs;
7188ac27
KM
522 /*
523 * Write back modified superblock.
524 * Consistency check that the superblock
525 * is still in the buffer cache.
526 */
527 if (fs->fs_fmod != 0) {
528 if (fs->fs_ronly != 0) { /* XXX */
529 printf("fs = %s\n", fs->fs_fsmnt);
530 panic("update: rofs mod");
531 }
532 fs->fs_fmod = 0;
533 fs->fs_time = time.tv_sec;
881f1b87 534 allerror = sbupdate(ump, waitfor);
7188ac27
KM
535 }
536 /*
537 * Write back each (modified) inode.
538 */
25b5cf58 539loop:
a242f429
KM
540 for (vp = mp->mnt_mounth; vp; vp = vp->v_mountf) {
541 /*
542 * If the vnode that we are about to sync is no longer
543 * associated with this mount point, start over.
544 */
545 if (vp->v_mount != mp)
546 goto loop;
31593ba7 547 ip = VTOI(vp);
25b5cf58
KM
548 if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0 &&
549 vp->v_dirtyblkhd == NULL)
7188ac27 550 continue;
25b5cf58
KM
551 if (vget(vp))
552 goto loop;
553 if (vp->v_dirtyblkhd)
554 vflushbuf(vp, 0);
555 if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) &&
556 (error = iupdat(ip, &time, &time, 0)))
812b91f3
KM
557 allerror = error;
558 vput(vp);
7188ac27 559 }
7188ac27 560 /*
5d96a9ad 561 * Force stale file system control information to be flushed.
7188ac27 562 */
5d96a9ad 563 vflushbuf(ump->um_devvp, waitfor == MNT_WAIT ? B_SYNC : 0);
8dc876c1
KM
564#ifdef QUOTA
565 qsync(mp);
566#endif
812b91f3 567 return (allerror);
7188ac27
KM
568}
569
570/*
571 * Write a superblock and associated information back to disk.
572 */
573sbupdate(mp, waitfor)
574 struct ufsmount *mp;
575 int waitfor;
576{
577 register struct fs *fs = mp->um_fs;
71e4e98b
SL
578 register struct buf *bp;
579 int blks;
580 caddr_t space;
7188ac27 581 int i, size, error = 0;
71e4e98b 582
ec67a3ce
MK
583#ifdef SECSIZE
584 bp = getblk(mp->m_dev, (daddr_t)fsbtodb(fs, SBOFF / fs->fs_fsize),
585 (int)fs->fs_sbsize, fs->fs_dbsize);
586#else SECSIZE
7188ac27 587 bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize);
ec67a3ce 588#endif SECSIZE
71e4e98b 589 bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize);
2af59000
KM
590 /* Restore compatibility to old file systems. XXX */
591 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
592 bp->b_un.b_fs->fs_nrpos = -1; /* XXX */
ec67a3ce
MK
593#ifdef SECSIZE
594#ifdef tahoe
595 /* restore standard fsbtodb shift */
596 bp->b_un.b_fs->fs_fsbtodb = fs->fs_sparecon[0];
597 bp->b_un.b_fs->fs_sparecon[0] = 0;
598#endif
599#endif SECSIZE
7188ac27
KM
600 if (waitfor == MNT_WAIT)
601 error = bwrite(bp);
602 else
603 bawrite(bp);
71e4e98b
SL
604 blks = howmany(fs->fs_cssize, fs->fs_fsize);
605 space = (caddr_t)fs->fs_csp[0];
606 for (i = 0; i < blks; i += fs->fs_frag) {
607 size = fs->fs_bsize;
608 if (i + fs->fs_frag > blks)
609 size = (blks - i) * fs->fs_fsize;
ec67a3ce
MK
610#ifdef SECSIZE
611 bp = getblk(mp->m_dev, fsbtodb(fs, fs->fs_csaddr + i), size,
612 fs->fs_dbsize);
613#else SECSIZE
7188ac27 614 bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), size);
ec67a3ce 615#endif SECSIZE
71e4e98b
SL
616 bcopy(space, bp->b_un.b_addr, (u_int)size);
617 space += size;
7188ac27
KM
618 if (waitfor == MNT_WAIT)
619 error = bwrite(bp);
620 else
621 bawrite(bp);
71e4e98b 622 }
7188ac27 623 return (error);
71e4e98b
SL
624}
625
626/*
7188ac27
KM
627 * Print out statistics on the current allocation of the buffer pool.
628 * Can be enabled to print out on every ``sync'' by setting "syncprt"
629 * above.
630 */
631bufstats()
632{
633 int s, i, j, count;
634 register struct buf *bp, *dp;
635 int counts[MAXBSIZE/CLBYTES+1];
636 static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" };
637
638 for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) {
639 count = 0;
640 for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
641 counts[j] = 0;
642 s = splbio();
643 for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) {
644 counts[dp->b_bufsize/CLBYTES]++;
645 count++;
646 }
647 splx(s);
648 printf("%s: total-%d", bname[i], count);
649 for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
650 if (counts[j] != 0)
651 printf(", %d-%d", j * CLBYTES, counts[j]);
652 printf("\n");
653 }
654}
655
656/*
657 * File handle to vnode
113c35f2
KM
658 *
659 * Have to be really careful about stale file handles:
660 * - check that the inode number is in range
661 * - call iget() to get the locked inode
662 * - check for an unallocated inode (i_mode == 0)
663 * - check that the generation number matches
7188ac27
KM
664 */
665ufs_fhtovp(mp, fhp, vpp)
113c35f2 666 register struct mount *mp;
7188ac27
KM
667 struct fid *fhp;
668 struct vnode **vpp;
669{
670 register struct ufid *ufhp;
113c35f2 671 register struct fs *fs;
31593ba7
KM
672 register struct inode *ip;
673 struct inode *nip;
674 struct vnode tvp;
7188ac27
KM
675 int error;
676
677 ufhp = (struct ufid *)fhp;
113c35f2
KM
678 fs = VFSTOUFS(mp)->um_fs;
679 if (ufhp->ufid_ino < ROOTINO ||
680 ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) {
82161bc8 681 *vpp = NULLVP;
113c35f2
KM
682 return (EINVAL);
683 }
31593ba7
KM
684 tvp.v_mount = mp;
685 ip = VTOI(&tvp);
686 ip->i_vnode = &tvp;
687 ip->i_dev = VFSTOUFS(mp)->um_dev;
688 if (error = iget(ip, ufhp->ufid_ino, &nip)) {
82161bc8 689 *vpp = NULLVP;
7188ac27
KM
690 return (error);
691 }
31593ba7 692 ip = nip;
113c35f2
KM
693 if (ip->i_mode == 0) {
694 iput(ip);
82161bc8 695 *vpp = NULLVP;
113c35f2
KM
696 return (EINVAL);
697 }
7188ac27
KM
698 if (ip->i_gen != ufhp->ufid_gen) {
699 iput(ip);
82161bc8 700 *vpp = NULLVP;
7188ac27
KM
701 return (EINVAL);
702 }
703 *vpp = ITOV(ip);
704 return (0);
705}
706
707/*
29e77c27 708 * Vnode pointer to File handle
7188ac27
KM
709 */
710/* ARGSUSED */
758e3529
KM
711ufs_vptofh(vp, fhp)
712 struct vnode *vp;
7188ac27 713 struct fid *fhp;
7188ac27 714{
758e3529
KM
715 register struct inode *ip = VTOI(vp);
716 register struct ufid *ufhp;
7188ac27 717
758e3529
KM
718 ufhp = (struct ufid *)fhp;
719 ufhp->ufid_len = sizeof(struct ufid);
720 ufhp->ufid_ino = ip->i_number;
721 ufhp->ufid_gen = ip->i_gen;
722 return (0);
7188ac27
KM
723}
724
725/*
71e4e98b
SL
726 * Check that the user's argument is a reasonable
727 * thing on which to mount, and return the device number if so.
728 */
7188ac27
KM
729getmdev(devvpp, fname, ndp)
730 struct vnode **devvpp;
715baff1 731 caddr_t fname;
7188ac27 732 register struct nameidata *ndp;
71e4e98b 733{
7188ac27
KM
734 register struct vnode *vp;
735 int error;
71e4e98b 736
6c845185 737 ndp->ni_nameiop = LOOKUP | FOLLOW;
715baff1
KM
738 ndp->ni_segflg = UIO_USERSPACE;
739 ndp->ni_dirp = fname;
c6f5111d 740 if (error = namei(ndp, curproc)) /* XXX */
7188ac27 741 return (error);
7188ac27
KM
742 vp = ndp->ni_vp;
743 if (vp->v_type != VBLK) {
6c845185 744 vrele(vp);
71e4e98b 745 return (ENOTBLK);
e95cdf5c 746 }
e547d435 747 if (major(vp->v_rdev) >= nblkdev) {
6c845185 748 vrele(vp);
71e4e98b 749 return (ENXIO);
e547d435 750 }
7188ac27 751 *devvpp = vp;
71e4e98b
SL
752 return (0);
753}