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