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