add Sun compatibility ala assuming NFS when spec contains ':' or '@'
[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 *
8e940f59 17 * @(#)ufs_vfsops.c 7.46 (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);
8e940f59 414 struct proc *p = u.u_procp; /* XXX */
8dc876c1
KM
415 int cmd, type, error;
416
417#ifndef QUOTA
418 return (EOPNOTSUPP);
419#else
420 if (uid == -1)
8e940f59 421 uid = p->p_ruid;
8dc876c1
KM
422 cmd = cmds >> SUBCMDSHIFT;
423
424 switch (cmd) {
425 case Q_GETQUOTA:
426 case Q_SYNC:
8e940f59 427 if (uid == p->p_ruid)
8dc876c1
KM
428 break;
429 /* fall through */
430 default:
431 if (error = suser(ndp->ni_cred, &u.u_acflag))
432 return (error);
433 }
434
435 type = cmd & SUBCMDMASK;
436 if ((u_int)type >= MAXQUOTAS)
437 return (EINVAL);
438
439 switch (cmd) {
440
441 case Q_QUOTAON:
442 return (quotaon(ndp, mp, type, arg));
443
444 case Q_QUOTAOFF:
445 if (vfs_busy(mp))
446 return (0);
447 error = quotaoff(mp, type);
448 vfs_unbusy(mp);
449 return (error);
450
451 case Q_SETQUOTA:
452 return (setquota(mp, uid, type, arg));
453
454 case Q_SETUSE:
455 return (setuse(mp, uid, type, arg));
456
457 case Q_GETQUOTA:
458 return (getquota(mp, uid, type, arg));
459
460 case Q_SYNC:
461 if (vfs_busy(mp))
462 return (0);
463 error = qsync(mp);
464 vfs_unbusy(mp);
465 return (error);
466
467 default:
468 return (EINVAL);
469 }
470 /* NOTREACHED */
471#endif
472}
473
7188ac27
KM
474/*
475 * Get file system statistics.
476 */
477ufs_statfs(mp, sbp)
478 struct mount *mp;
479 register struct statfs *sbp;
480{
481 register struct ufsmount *ump;
482 register struct fs *fs;
483
484 ump = VFSTOUFS(mp);
485 fs = ump->um_fs;
486 if (fs->fs_magic != FS_MAGIC)
487 panic("ufs_statfs");
488 sbp->f_type = MOUNT_UFS;
7188ac27
KM
489 sbp->f_fsize = fs->fs_fsize;
490 sbp->f_bsize = fs->fs_bsize;
491 sbp->f_blocks = fs->fs_dsize;
492 sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
493 fs->fs_cstotal.cs_nffree;
494 sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) -
495 (fs->fs_dsize - sbp->f_bfree);
5c41c19e 496 sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
7188ac27 497 sbp->f_ffree = fs->fs_cstotal.cs_nifree;
82161bc8
KM
498 if (sbp != &mp->mnt_stat) {
499 bcopy((caddr_t)mp->mnt_stat.f_mntonname,
d45de50d 500 (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
82161bc8 501 bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
d45de50d
KM
502 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
503 }
7188ac27
KM
504 return (0);
505}
506
507int syncprt = 0;
508
509/*
510 * Go through the disk queues to initiate sandbagged IO;
511 * go through the inodes to write those that have been modified;
512 * initiate the writing of the super block if it has been modified.
8dc876c1
KM
513 *
514 * Note: we are always called with the filesystem marked `MPBUSY'.
7188ac27
KM
515 */
516ufs_sync(mp, waitfor)
71e4e98b 517 struct mount *mp;
7188ac27 518 int waitfor;
71e4e98b 519{
31593ba7 520 register struct vnode *vp;
7188ac27
KM
521 register struct inode *ip;
522 register struct ufsmount *ump = VFSTOUFS(mp);
523 register struct fs *fs;
812b91f3 524 int error, allerror = 0;
7188ac27
KM
525
526 if (syncprt)
527 bufstats();
7188ac27 528 fs = ump->um_fs;
7188ac27
KM
529 /*
530 * Write back modified superblock.
531 * Consistency check that the superblock
532 * is still in the buffer cache.
533 */
534 if (fs->fs_fmod != 0) {
535 if (fs->fs_ronly != 0) { /* XXX */
536 printf("fs = %s\n", fs->fs_fsmnt);
537 panic("update: rofs mod");
538 }
539 fs->fs_fmod = 0;
540 fs->fs_time = time.tv_sec;
881f1b87 541 allerror = sbupdate(ump, waitfor);
7188ac27
KM
542 }
543 /*
544 * Write back each (modified) inode.
545 */
25b5cf58 546loop:
a242f429
KM
547 for (vp = mp->mnt_mounth; vp; vp = vp->v_mountf) {
548 /*
549 * If the vnode that we are about to sync is no longer
550 * associated with this mount point, start over.
551 */
552 if (vp->v_mount != mp)
553 goto loop;
31593ba7 554 ip = VTOI(vp);
25b5cf58
KM
555 if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0 &&
556 vp->v_dirtyblkhd == NULL)
7188ac27 557 continue;
25b5cf58
KM
558 if (vget(vp))
559 goto loop;
560 if (vp->v_dirtyblkhd)
561 vflushbuf(vp, 0);
562 if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) &&
563 (error = iupdat(ip, &time, &time, 0)))
812b91f3
KM
564 allerror = error;
565 vput(vp);
7188ac27 566 }
7188ac27 567 /*
5d96a9ad 568 * Force stale file system control information to be flushed.
7188ac27 569 */
5d96a9ad 570 vflushbuf(ump->um_devvp, waitfor == MNT_WAIT ? B_SYNC : 0);
8dc876c1
KM
571#ifdef QUOTA
572 qsync(mp);
573#endif
812b91f3 574 return (allerror);
7188ac27
KM
575}
576
577/*
578 * Write a superblock and associated information back to disk.
579 */
580sbupdate(mp, waitfor)
581 struct ufsmount *mp;
582 int waitfor;
583{
584 register struct fs *fs = mp->um_fs;
71e4e98b
SL
585 register struct buf *bp;
586 int blks;
587 caddr_t space;
7188ac27 588 int i, size, error = 0;
71e4e98b 589
ec67a3ce
MK
590#ifdef SECSIZE
591 bp = getblk(mp->m_dev, (daddr_t)fsbtodb(fs, SBOFF / fs->fs_fsize),
592 (int)fs->fs_sbsize, fs->fs_dbsize);
593#else SECSIZE
7188ac27 594 bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize);
ec67a3ce 595#endif SECSIZE
71e4e98b 596 bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize);
2af59000
KM
597 /* Restore compatibility to old file systems. XXX */
598 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
599 bp->b_un.b_fs->fs_nrpos = -1; /* XXX */
ec67a3ce
MK
600#ifdef SECSIZE
601#ifdef tahoe
602 /* restore standard fsbtodb shift */
603 bp->b_un.b_fs->fs_fsbtodb = fs->fs_sparecon[0];
604 bp->b_un.b_fs->fs_sparecon[0] = 0;
605#endif
606#endif SECSIZE
7188ac27
KM
607 if (waitfor == MNT_WAIT)
608 error = bwrite(bp);
609 else
610 bawrite(bp);
71e4e98b
SL
611 blks = howmany(fs->fs_cssize, fs->fs_fsize);
612 space = (caddr_t)fs->fs_csp[0];
613 for (i = 0; i < blks; i += fs->fs_frag) {
614 size = fs->fs_bsize;
615 if (i + fs->fs_frag > blks)
616 size = (blks - i) * fs->fs_fsize;
ec67a3ce
MK
617#ifdef SECSIZE
618 bp = getblk(mp->m_dev, fsbtodb(fs, fs->fs_csaddr + i), size,
619 fs->fs_dbsize);
620#else SECSIZE
7188ac27 621 bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), size);
ec67a3ce 622#endif SECSIZE
71e4e98b
SL
623 bcopy(space, bp->b_un.b_addr, (u_int)size);
624 space += size;
7188ac27
KM
625 if (waitfor == MNT_WAIT)
626 error = bwrite(bp);
627 else
628 bawrite(bp);
71e4e98b 629 }
7188ac27 630 return (error);
71e4e98b
SL
631}
632
633/*
7188ac27
KM
634 * Print out statistics on the current allocation of the buffer pool.
635 * Can be enabled to print out on every ``sync'' by setting "syncprt"
636 * above.
637 */
638bufstats()
639{
640 int s, i, j, count;
641 register struct buf *bp, *dp;
642 int counts[MAXBSIZE/CLBYTES+1];
643 static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" };
644
645 for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) {
646 count = 0;
647 for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
648 counts[j] = 0;
649 s = splbio();
650 for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) {
651 counts[dp->b_bufsize/CLBYTES]++;
652 count++;
653 }
654 splx(s);
655 printf("%s: total-%d", bname[i], count);
656 for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
657 if (counts[j] != 0)
658 printf(", %d-%d", j * CLBYTES, counts[j]);
659 printf("\n");
660 }
661}
662
663/*
664 * File handle to vnode
113c35f2
KM
665 *
666 * Have to be really careful about stale file handles:
667 * - check that the inode number is in range
668 * - call iget() to get the locked inode
669 * - check for an unallocated inode (i_mode == 0)
670 * - check that the generation number matches
7188ac27
KM
671 */
672ufs_fhtovp(mp, fhp, vpp)
113c35f2 673 register struct mount *mp;
7188ac27
KM
674 struct fid *fhp;
675 struct vnode **vpp;
676{
677 register struct ufid *ufhp;
113c35f2 678 register struct fs *fs;
31593ba7
KM
679 register struct inode *ip;
680 struct inode *nip;
681 struct vnode tvp;
7188ac27
KM
682 int error;
683
684 ufhp = (struct ufid *)fhp;
113c35f2
KM
685 fs = VFSTOUFS(mp)->um_fs;
686 if (ufhp->ufid_ino < ROOTINO ||
687 ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) {
82161bc8 688 *vpp = NULLVP;
113c35f2
KM
689 return (EINVAL);
690 }
31593ba7
KM
691 tvp.v_mount = mp;
692 ip = VTOI(&tvp);
693 ip->i_vnode = &tvp;
694 ip->i_dev = VFSTOUFS(mp)->um_dev;
695 if (error = iget(ip, ufhp->ufid_ino, &nip)) {
82161bc8 696 *vpp = NULLVP;
7188ac27
KM
697 return (error);
698 }
31593ba7 699 ip = nip;
113c35f2
KM
700 if (ip->i_mode == 0) {
701 iput(ip);
82161bc8 702 *vpp = NULLVP;
113c35f2
KM
703 return (EINVAL);
704 }
7188ac27
KM
705 if (ip->i_gen != ufhp->ufid_gen) {
706 iput(ip);
82161bc8 707 *vpp = NULLVP;
7188ac27
KM
708 return (EINVAL);
709 }
710 *vpp = ITOV(ip);
711 return (0);
712}
713
714/*
29e77c27 715 * Vnode pointer to File handle
7188ac27
KM
716 */
717/* ARGSUSED */
758e3529
KM
718ufs_vptofh(vp, fhp)
719 struct vnode *vp;
7188ac27 720 struct fid *fhp;
7188ac27 721{
758e3529
KM
722 register struct inode *ip = VTOI(vp);
723 register struct ufid *ufhp;
7188ac27 724
758e3529
KM
725 ufhp = (struct ufid *)fhp;
726 ufhp->ufid_len = sizeof(struct ufid);
727 ufhp->ufid_ino = ip->i_number;
728 ufhp->ufid_gen = ip->i_gen;
729 return (0);
7188ac27
KM
730}
731
732/*
71e4e98b
SL
733 * Check that the user's argument is a reasonable
734 * thing on which to mount, and return the device number if so.
735 */
7188ac27
KM
736getmdev(devvpp, fname, ndp)
737 struct vnode **devvpp;
715baff1 738 caddr_t fname;
7188ac27 739 register struct nameidata *ndp;
71e4e98b 740{
7188ac27
KM
741 register struct vnode *vp;
742 int error;
71e4e98b 743
6c845185 744 ndp->ni_nameiop = LOOKUP | FOLLOW;
715baff1
KM
745 ndp->ni_segflg = UIO_USERSPACE;
746 ndp->ni_dirp = fname;
7188ac27
KM
747 if (error = namei(ndp)) {
748 if (error == ENOENT)
749 return (ENODEV); /* needs translation */
750 return (error);
6d07f4cd 751 }
7188ac27
KM
752 vp = ndp->ni_vp;
753 if (vp->v_type != VBLK) {
6c845185 754 vrele(vp);
71e4e98b 755 return (ENOTBLK);
e95cdf5c 756 }
e547d435 757 if (major(vp->v_rdev) >= nblkdev) {
6c845185 758 vrele(vp);
71e4e98b 759 return (ENXIO);
e547d435 760 }
7188ac27 761 *devvpp = vp;
71e4e98b
SL
762 return (0);
763}