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