expand parameters to functions; READDIR drops eofflag;
[unix-history] / usr / src / sys / ufs / ffs / ffs_vfsops.c
CommitLineData
da7c5cc6 1/*
190244fb 2 * Copyright (c) 1989, 1991 The Regents of the University of California.
7188ac27 3 * All rights reserved.
da7c5cc6 4 *
b702c21d 5 * %sccs.include.redist.c%
7188ac27 6 *
ea301039 7 * @(#)ffs_vfsops.c 7.67 (Berkeley) %G%
da7c5cc6 8 */
71e4e98b 9
ab9f4fb0
KB
10#include <sys/param.h>
11#include <sys/systm.h>
12#include <sys/namei.h>
13#include <sys/proc.h>
14#include <sys/kernel.h>
15#include <sys/vnode.h>
16#include <sys/specdev.h>
17#include <sys/mount.h>
18#include <sys/buf.h>
19#include <sys/file.h>
20#include <sys/disklabel.h>
21#include <sys/ioctl.h>
22#include <sys/errno.h>
23#include <sys/malloc.h>
609e7cfa
MK
24#include "ioctl.h"
25#include "disklabel.h"
26#include "stat.h"
71e4e98b 27
ab9f4fb0
KB
28#include <ufs/ufs/quota.h>
29#include <ufs/ufs/ufsmount.h>
30#include <ufs/ufs/inode.h>
31#include <ufs/ufs/ufs_extern.h>
32
33#include <ufs/ffs/fs.h>
34#include <ufs/ffs/ffs_extern.h>
35
06445aba 36int ffs_sbupdate __P((struct ufsmount *, int));
c6f5111d 37
7188ac27 38struct vfsops ufs_vfsops = {
ab9f4fb0 39 ffs_mount,
5bf9d21f 40 ufs_start,
ab9f4fb0 41 ffs_unmount,
a9013e03 42 ffs_root,
8dc876c1 43 ufs_quotactl,
ab9f4fb0
KB
44 ffs_statfs,
45 ffs_sync,
a9013e03
KM
46 ffs_fhtovp,
47 ffs_vptofh,
ab9f4fb0 48 ffs_init,
7188ac27
KM
49};
50
7188ac27 51/*
4ac55ebc 52 * Called by main() when ufs is going to be mounted as root.
7188ac27 53 *
d48157d5 54 * Name is updated by mount(8) after booting.
7188ac27 55 */
8a4911ca 56#define ROOTNAME "root_device"
7188ac27 57
ab9f4fb0 58ffs_mountroot()
71e4e98b 59{
7188ac27 60 extern struct vnode *rootvp;
ab9f4fb0
KB
61 register struct fs *fs;
62 register struct mount *mp;
0eb6f54a 63 struct proc *p = curproc; /* XXX */
7188ac27 64 struct ufsmount *ump;
7188ac27
KM
65 u_int size;
66 int error;
71e4e98b 67
4ac55ebc 68 mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK);
ea301039 69 bzero((char *)mp, (u_long)sizeof(struct mount));
82161bc8
KM
70 mp->mnt_op = &ufs_vfsops;
71 mp->mnt_flag = MNT_RDONLY;
ab9f4fb0
KB
72 if (error = ffs_mountfs(rootvp, mp, p)) {
73 free(mp, M_MOUNT);
7188ac27 74 return (error);
71e4e98b 75 }
d48157d5 76 if (error = vfs_lock(mp)) {
ab9f4fb0
KB
77 (void)ffs_unmount(mp, 0, p);
78 free(mp, M_MOUNT);
7188ac27 79 return (error);
6d07f4cd 80 }
d48157d5 81 rootfs = mp;
82161bc8
KM
82 mp->mnt_next = mp;
83 mp->mnt_prev = mp;
84 mp->mnt_vnodecovered = NULLVP;
7188ac27
KM
85 ump = VFSTOUFS(mp);
86 fs = ump->um_fs;
d45de50d 87 bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt));
7188ac27 88 fs->fs_fsmnt[0] = '/';
82161bc8
KM
89 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
90 MNAMELEN);
91 (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
92 &size);
93 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
ab9f4fb0 94 (void)ffs_statfs(mp, &mp->mnt_stat, p);
7188ac27
KM
95 vfs_unlock(mp);
96 inittodr(fs->fs_time);
97 return (0);
98}
99
100/*
101 * VFS Operations.
102 *
103 * mount system call
104 */
06445aba 105int
ab9f4fb0 106ffs_mount(mp, path, data, ndp, p)
d45de50d 107 register struct mount *mp;
7188ac27
KM
108 char *path;
109 caddr_t data;
110 struct nameidata *ndp;
0eb6f54a 111 struct proc *p;
7188ac27
KM
112{
113 struct vnode *devvp;
114 struct ufs_args args;
115 struct ufsmount *ump;
116 register struct fs *fs;
117 u_int size;
118 int error;
119
120 if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
121 return (error);
190244fb
MK
122 /*
123 * If updating, check whether changing from read-only to
124 * read/write; if there is no device name, that's all we do.
125 */
126 if (mp->mnt_flag & MNT_UPDATE) {
d48157d5
KM
127 ump = VFSTOUFS(mp);
128 fs = ump->um_fs;
82161bc8 129 if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0)
d48157d5 130 fs->fs_ronly = 0;
c906fba1
KM
131 if (args.fspec == 0) {
132 /*
133 * Process export requests.
134 */
135 if (args.exflags & MNT_EXPORTED) {
136 if (error = hang_addrlist(mp, &args))
137 return (error);
138 mp->mnt_flag |= MNT_EXPORTED;
139 }
140 if (args.exflags & MNT_DELEXPORT) {
141 free_addrlist(ump);
142 mp->mnt_flag &=
143 ~(MNT_EXPORTED | MNT_DEFEXPORTED);
144 }
3b931949 145 return (0);
c906fba1 146 }
190244fb
MK
147 }
148 /*
149 * Not an update, or updating the name: look up the name
150 * and verify that it refers to a sensible block device.
151 */
995e59df
KM
152 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
153 if (error = namei(ndp))
190244fb
MK
154 return (error);
155 devvp = ndp->ni_vp;
ab9f4fb0 156
190244fb
MK
157 if (devvp->v_type != VBLK) {
158 vrele(devvp);
159 return (ENOTBLK);
160 }
161 if (major(devvp->v_rdev) >= nblkdev) {
162 vrele(devvp);
163 return (ENXIO);
164 }
165 if ((mp->mnt_flag & MNT_UPDATE) == 0)
ab9f4fb0 166 error = ffs_mountfs(devvp, mp, p);
190244fb 167 else {
d48157d5
KM
168 if (devvp != ump->um_devvp)
169 error = EINVAL; /* needs translation */
2a7dbb09
KM
170 else
171 vrele(devvp);
d48157d5 172 }
7188ac27
KM
173 if (error) {
174 vrele(devvp);
175 return (error);
27d00e76 176 }
7188ac27
KM
177 ump = VFSTOUFS(mp);
178 fs = ump->um_fs;
179 (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
180 bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
82161bc8
KM
181 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
182 MNAMELEN);
183 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
184 &size);
185 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
ab9f4fb0 186 (void)ffs_statfs(mp, &mp->mnt_stat, p);
7188ac27 187 return (0);
71e4e98b
SL
188}
189
7188ac27
KM
190/*
191 * Common code for mount and mountroot
192 */
ab9f4fb0
KB
193int
194ffs_mountfs(devvp, mp, p)
1182ae61 195 register struct vnode *devvp;
7188ac27 196 struct mount *mp;
0eb6f54a 197 struct proc *p;
71e4e98b 198{
9342689a
JH
199 USES_VOP_CLOSE;
200 USES_VOP_IOCTL;
201 USES_VOP_OPEN;
8dc876c1 202 register struct ufsmount *ump = (struct ufsmount *)0;
7188ac27 203 struct buf *bp = NULL;
71e4e98b 204 register struct fs *fs;
7188ac27 205 dev_t dev = devvp->v_rdev;
ec67a3ce
MK
206 struct partinfo dpart;
207 int havepart = 0, blks;
27d00e76 208 caddr_t base, space;
7188ac27
KM
209 int havepart = 0, blks;
210 int error, i, size;
6d07f4cd 211 int needclose = 0;
82161bc8 212 int ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
1c26e003 213 extern struct vnode *rootvp;
71e4e98b 214
0eb6f54a 215 if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p))
7188ac27 216 return (error);
6d07f4cd 217 needclose = 1;
0eb6f54a 218 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
609e7cfa 219 size = DEV_BSIZE;
0eb6f54a 220 else {
ec67a3ce
MK
221 havepart = 1;
222 size = dpart.disklab->d_secsize;
7188ac27 223 }
8dc876c1 224 if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp))
71e4e98b 225 goto out;
e018935f 226 fs = bp->b_un.b_fs;
8dc876c1 227 error = EINVAL; /* XXX needs translation */
1c281610
MK
228 goto out;
229 }
ab9f4fb0 230 ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
7bff53ea 231 bzero((caddr_t)ump, sizeof *ump);
b1ca3fbf 232 ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT,
5adcb337 233 M_WAITOK);
7188ac27 234 bcopy((caddr_t)bp->b_un.b_addr, (caddr_t)ump->um_fs,
71e4e98b 235 (u_int)fs->fs_sbsize);
5d96a9ad
KM
236 if (fs->fs_sbsize < SBSIZE)
237 bp->b_flags |= B_INVAL;
e018935f
MK
238 brelse(bp);
239 bp = NULL;
7188ac27
KM
240 fs = ump->um_fs;
241 fs->fs_ronly = ronly;
71e4e98b
SL
242 if (ronly == 0)
243 fs->fs_fmod = 1;
609e7cfa
MK
244 if (havepart) {
245 dpart.part->p_fstype = FS_BSDFFS;
246 dpart.part->p_fsize = fs->fs_fsize;
247 dpart.part->p_frag = fs->fs_frag;
42ff4c2e 248 dpart.part->p_cpg = fs->fs_cpg;
609e7cfa 249 }
ec67a3ce
MK
250#ifdef SECSIZE
251 /*
252 * If we have a disk label, force per-partition
253 * filesystem information to be correct
254 * and set correct current fsbtodb shift.
255 */
256#endif SECSIZE
257 if (havepart) {
258 dpart.part->p_fstype = FS_BSDFFS;
259 dpart.part->p_fsize = fs->fs_fsize;
260 dpart.part->p_frag = fs->fs_frag;
261#ifdef SECSIZE
262#ifdef tahoe
263 /*
264 * Save the original fsbtodb shift to restore on updates.
265 * (Console doesn't understand fsbtodb changes.)
266 */
267 fs->fs_sparecon[0] = fs->fs_fsbtodb;
268#endif
269 i = fs->fs_fsize / size;
270 for (fs->fs_fsbtodb = 0; i > 1; i >>= 1)
271 fs->fs_fsbtodb++;
272#endif SECSIZE
273 fs->fs_dbsize = size;
274 }
71e4e98b 275 blks = howmany(fs->fs_cssize, fs->fs_fsize);
b1ca3fbf 276 base = space = malloc((u_long)fs->fs_cssize, M_UFSMNT,
5adcb337 277 M_WAITOK);
71e4e98b
SL
278 for (i = 0; i < blks; i += fs->fs_frag) {
279 size = fs->fs_bsize;
280 if (i + fs->fs_frag > blks)
281 size = (blks - i) * fs->fs_fsize;
ec67a3ce
MK
282#ifdef SECSIZE
283 tp = bread(dev, fsbtodb(fs, fs->fs_csaddr + i), size,
284 fs->fs_dbsize);
285#else SECSIZE
a937f856
KM
286 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
287 NOCRED, &bp);
7188ac27 288 if (error) {
b1ca3fbf 289 free(base, M_UFSMNT);
71e4e98b
SL
290 goto out;
291 }
e018935f 292 bcopy((caddr_t)bp->b_un.b_addr, space, (u_int)size);
60f9c9e3 293 fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space;
71e4e98b 294 space += size;
e018935f
MK
295 brelse(bp);
296 bp = NULL;
71e4e98b 297 }
82161bc8
KM
298 mp->mnt_data = (qaddr_t)ump;
299 mp->mnt_stat.f_fsid.val[0] = (long)dev;
300 mp->mnt_stat.f_fsid.val[1] = MOUNT_UFS;
ea301039 301 mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
82161bc8 302 mp->mnt_flag |= MNT_LOCAL;
7188ac27
KM
303 ump->um_mountp = mp;
304 ump->um_dev = dev;
305 ump->um_devvp = devvp;
8dc876c1
KM
306 for (i = 0; i < MAXQUOTAS; i++)
307 ump->um_quotas[i] = NULLVP;
0f93ba7b 308 devvp->v_specflags |= SI_MOUNTEDON;
7188ac27 309
94354803
KM
310 /* Sanity checks for old file systems. XXX */
311 fs->fs_npsect = MAX(fs->fs_npsect, fs->fs_nsect); /* XXX */
312 fs->fs_interleave = MAX(fs->fs_interleave, 1); /* XXX */
2af59000
KM
313 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
314 fs->fs_nrpos = 8; /* XXX */
4605fb61
KM
315 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
316 quad_t sizepb = fs->fs_bsize; /* XXX */
317 /* XXX */
318 fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
319 for (i = 0; i < NIADDR; i++) { /* XXX */
320 sizepb *= NINDIR(fs); /* XXX */
321 fs->fs_maxfilesize += sizepb; /* XXX */
322 } /* XXX */
323 fs->fs_qbmask = ~fs->fs_bmask; /* XXX */
324 fs->fs_qfmask = ~fs->fs_fmask; /* XXX */
325 } /* XXX */
609e7cfa 326
7188ac27 327 return (0);
71e4e98b 328out:
c86c9b6e
KM
329 if (bp)
330 brelse(bp);
609e7cfa 331 if (needclose)
0eb6f54a 332 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
8dc876c1 333 if (ump) {
b1ca3fbf 334 free(ump->um_fs, M_UFSMNT);
ab9f4fb0 335 free(ump, M_UFSMNT);
82161bc8 336 mp->mnt_data = (qaddr_t)0;
27d00e76 337 }
7188ac27 338 return (error);
71e4e98b
SL
339}
340
7188ac27
KM
341/*
342 * unmount system call
343 */
ab9f4fb0
KB
344int
345ffs_unmount(mp, mntflags, p)
7188ac27 346 struct mount *mp;
8dc876c1 347 int mntflags;
0eb6f54a 348 struct proc *p;
71e4e98b 349{
9342689a 350 USES_VOP_CLOSE;
ab9f4fb0 351 extern int doforce;
7188ac27 352 register struct ufsmount *ump;
71e4e98b 353 register struct fs *fs;
8dc876c1 354 int i, error, ronly, flags = 0;
71e4e98b 355
87be6db2 356 if (mntflags & MNT_FORCE) {
d85a9d1b 357 if (!doforce || mp == rootfs)
87be6db2 358 return (EINVAL);
8dc876c1 359 flags |= FORCECLOSE;
87be6db2 360 }
5d96a9ad
KM
361 mntflushbuf(mp, 0);
362 if (mntinvalbuf(mp))
363 return (EBUSY);
7188ac27 364 ump = VFSTOUFS(mp);
ec67a3ce 365 return (error);
71e4e98b 366#ifdef QUOTA
82161bc8 367 if (mp->mnt_flag & MNT_QUOTA) {
8dc876c1 368 if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags))
6d943995 369 return (error);
8dc876c1
KM
370 for (i = 0; i < MAXQUOTAS; i++) {
371 if (ump->um_quotas[i] == NULLVP)
372 continue;
70a360ba 373 quotaoff(p, mp, i);
8dc876c1 374 }
6d943995 375 /*
8dc876c1
KM
376 * Here we fall through to vflush again to ensure
377 * that we have gotten rid of all the system vnodes.
6d943995 378 */
8dc876c1 379 }
71e4e98b 380#endif
8dc876c1 381 if (error = vflush(mp, NULLVP, flags))
6d943995 382 return (error);
7188ac27
KM
383 fs = ump->um_fs;
384 ronly = !fs->fs_ronly;
7188ac27
KM
385 * Get file system statistics.
386 */
ab9f4fb0
KB
387int
388ffs_statfs(mp, sbp, p)
7188ac27
KM
389 struct mount *mp;
390 register struct statfs *sbp;
0eb6f54a 391 struct proc *p;
7188ac27
KM
392{
393 register struct ufsmount *ump;
394 register struct fs *fs;
395
396 ump = VFSTOUFS(mp);
397 fs = ump->um_fs;
398 if (fs->fs_magic != FS_MAGIC)
ab9f4fb0 399 panic("ffs_statfs");
7188ac27 400 sbp->f_type = MOUNT_UFS;
06445aba
KM
401 sbp->f_bsize = fs->fs_fsize;
402 sbp->f_iosize = fs->fs_bsize;
7188ac27
KM
403 sbp->f_blocks = fs->fs_dsize;
404 sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
405 fs->fs_cstotal.cs_nffree;
406 sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) -
407 (fs->fs_dsize - sbp->f_bfree);
5c41c19e 408 sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
7188ac27 409 sbp->f_ffree = fs->fs_cstotal.cs_nifree;
82161bc8
KM
410 if (sbp != &mp->mnt_stat) {
411 bcopy((caddr_t)mp->mnt_stat.f_mntonname,
d45de50d 412 (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
82161bc8 413 bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
d45de50d
KM
414 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
415 }
7188ac27
KM
416 return (0);
417}
418
7188ac27
KM
419/*
420 * Go through the disk queues to initiate sandbagged IO;
421 * go through the inodes to write those that have been modified;
422 * initiate the writing of the super block if it has been modified.
8dc876c1
KM
423 *
424 * Note: we are always called with the filesystem marked `MPBUSY'.
7188ac27 425 */
ab9f4fb0
KB
426int
427ffs_sync(mp, waitfor)
71e4e98b 428 struct mount *mp;
7188ac27 429 int waitfor;
71e4e98b 430{
9342689a
JH
431 USES_VOP_ISLOCKED;
432 USES_VOP_UPDATE;
ab9f4fb0 433 extern int syncprt;
31593ba7 434 register struct vnode *vp;
7188ac27
KM
435 register struct inode *ip;
436 register struct ufsmount *ump = VFSTOUFS(mp);
437 register struct fs *fs;
812b91f3 438 int error, allerror = 0;
7188ac27
KM
439
440 if (syncprt)
ab9f4fb0 441 ufs_bufstats();
7188ac27 442 fs = ump->um_fs;
7188ac27
KM
443 /*
444 * Write back modified superblock.
445 * Consistency check that the superblock
446 * is still in the buffer cache.
447 */
448 if (fs->fs_fmod != 0) {
449 if (fs->fs_ronly != 0) { /* XXX */
450 printf("fs = %s\n", fs->fs_fsmnt);
451 panic("update: rofs mod");
452 }
453 fs->fs_fmod = 0;
454 fs->fs_time = time.tv_sec;
ab9f4fb0 455 allerror = ffs_sbupdate(ump, waitfor);
7188ac27
KM
456 }
457 /*
458 * Write back each (modified) inode.
459 */
25b5cf58 460loop:
a242f429
KM
461 for (vp = mp->mnt_mounth; vp; vp = vp->v_mountf) {
462 /*
463 * If the vnode that we are about to sync is no longer
464 * associated with this mount point, start over.
465 */
466 if (vp->v_mount != mp)
467 goto loop;
d85a9d1b
KM
468 if (VOP_ISLOCKED(vp))
469 continue;
31593ba7 470 ip = VTOI(vp);
25b5cf58
KM
471 if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0 &&
472 vp->v_dirtyblkhd == NULL)
7188ac27 473 continue;
25b5cf58
KM
474 if (vget(vp))
475 goto loop;
476 if (vp->v_dirtyblkhd)
477 vflushbuf(vp, 0);
478 if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) &&
9342689a 479 (error = VOP_UPDATE(vp, &time, &time, 0)))
812b91f3
KM
480 allerror = error;
481 vput(vp);
7188ac27 482 }
7188ac27 483 /*
5d96a9ad 484 * Force stale file system control information to be flushed.
7188ac27 485 */
5d96a9ad 486 vflushbuf(ump->um_devvp, waitfor == MNT_WAIT ? B_SYNC : 0);
8dc876c1
KM
487#ifdef QUOTA
488 qsync(mp);
489#endif
812b91f3 490 return (allerror);
7188ac27
KM
491}
492
a9013e03
KM
493/*
494 * File handle to vnode
495 *
496 * Have to be really careful about stale file handles:
497 * - check that the inode number is valid
498 * - call ffs_vget() to get the locked inode
499 * - check for an unallocated inode (i_mode == 0)
c906fba1 500 * - check that the generation number matches unless setgen true
a9013e03
KM
501 */
502int
c906fba1 503ffs_fhtovp(mp, fhp, setgen, vpp)
a9013e03
KM
504 register struct mount *mp;
505 struct fid *fhp;
c906fba1 506 int setgen;
a9013e03
KM
507 struct vnode **vpp;
508{
9342689a 509 USES_VOP_VGET;
a9013e03
KM
510 register struct inode *ip;
511 register struct ufid *ufhp;
512 struct fs *fs;
513 struct vnode *nvp;
514 int error;
515
516 ufhp = (struct ufid *)fhp;
517 fs = VFSTOUFS(mp)->um_fs;
518 if (ufhp->ufid_ino < ROOTINO ||
519 ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg)
520 return (EINVAL);
9342689a 521 if (error = FFS_VGET(mp, ufhp->ufid_ino, &nvp)) {
a9013e03
KM
522 *vpp = NULLVP;
523 return (error);
524 }
525 ip = VTOI(nvp);
526 if (ip->i_mode == 0) {
527 ufs_iput(ip);
528 *vpp = NULLVP;
529 return (EINVAL);
530 }
531 if (ip->i_gen != ufhp->ufid_gen) {
c906fba1
KM
532 if (setgen)
533 ufhp->ufid_gen = ip->i_gen;
534 else {
535 ufs_iput(ip);
536 *vpp = NULLVP;
537 return (EINVAL);
538 }
a9013e03
KM
539 }
540 *vpp = nvp;
541 return (0);
542}
543
544/*
545 * Vnode pointer to File handle
546 */
547/* ARGSUSED */
548ffs_vptofh(vp, fhp)
549 struct vnode *vp;
550 struct fid *fhp;
551{
552 register struct inode *ip;
553 register struct ufid *ufhp;
554
555 ip = VTOI(vp);
556 ufhp = (struct ufid *)fhp;
557 ufhp->ufid_len = sizeof(struct ufid);
558 ufhp->ufid_ino = ip->i_number;
559 ufhp->ufid_gen = ip->i_gen;
560 return (0);
561}
562
7188ac27
KM
563/*
564 * Write a superblock and associated information back to disk.
565 */
06445aba 566int
ab9f4fb0 567ffs_sbupdate(mp, waitfor)
7188ac27
KM
568 struct ufsmount *mp;
569 int waitfor;
570{
571 register struct fs *fs = mp->um_fs;
71e4e98b
SL
572 register struct buf *bp;
573 int blks;
574 caddr_t space;
7188ac27 575 int i, size, error = 0;
71e4e98b 576
ec67a3ce
MK
577#ifdef SECSIZE
578 bp = getblk(mp->m_dev, (daddr_t)fsbtodb(fs, SBOFF / fs->fs_fsize),
579 (int)fs->fs_sbsize, fs->fs_dbsize);
580#else SECSIZE
7188ac27 581 bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize);
ec67a3ce 582#endif SECSIZE
71e4e98b 583 bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize);
2af59000
KM
584 /* Restore compatibility to old file systems. XXX */
585 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
586 bp->b_un.b_fs->fs_nrpos = -1; /* XXX */
ec67a3ce
MK
587#ifdef SECSIZE
588#ifdef tahoe
589 /* restore standard fsbtodb shift */
590 bp->b_un.b_fs->fs_fsbtodb = fs->fs_sparecon[0];
591 bp->b_un.b_fs->fs_sparecon[0] = 0;
592#endif
593#endif SECSIZE
7188ac27
KM
594 if (waitfor == MNT_WAIT)
595 error = bwrite(bp);
596 else
597 bawrite(bp);
71e4e98b
SL
598 blks = howmany(fs->fs_cssize, fs->fs_fsize);
599 space = (caddr_t)fs->fs_csp[0];
600 for (i = 0; i < blks; i += fs->fs_frag) {
601 size = fs->fs_bsize;
602 if (i + fs->fs_frag > blks)
603 size = (blks - i) * fs->fs_fsize;
ec67a3ce
MK
604#ifdef SECSIZE
605 bp = getblk(mp->m_dev, fsbtodb(fs, fs->fs_csaddr + i), size,
606 fs->fs_dbsize);
607#else SECSIZE
7188ac27 608 bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), size);
ec67a3ce 609#endif SECSIZE
71e4e98b
SL
610 bcopy(space, bp->b_un.b_addr, (u_int)size);
611 space += size;
7188ac27
KM
612 if (waitfor == MNT_WAIT)
613 error = bwrite(bp);
614 else
615 bawrite(bp);
71e4e98b 616 }
7188ac27 617 return (error);
71e4e98b 618}