1 /** $MirOS: src/sys/ufs/ffs/ffs_vfsops.c,v 1.14 2010/09/21 21:24:30 tg Exp $ */
2 /* $OpenBSD: ffs_vfsops.c,v 1.70 2005/07/03 20:14:02 drahn Exp $ */
3 /* $NetBSD: ffs_vfsops.c,v 1.19 1996/02/09 22:22:26 christos Exp $ */
4
5 /*
6 * Copyright (c) 2004
7 * Thorsten "mirabilos" Glaser <tg@mirbsd.org>
8 * Copyright (c) 1989, 1991, 1993, 1994
9 * The Regents of the University of California. All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)ffs_vfsops.c 8.14 (Berkeley) 11/28/94
36 */
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/namei.h>
41 #include <sys/proc.h>
42 #include <sys/kernel.h>
43 #include <sys/vnode.h>
44 #include <sys/socket.h>
45 #include <sys/mount.h>
46 #include <sys/buf.h>
47 #include <sys/mbuf.h>
48 #include <sys/file.h>
49 #include <sys/disklabel.h>
50 #include <sys/ioctl.h>
51 #include <sys/errno.h>
52 #include <sys/malloc.h>
53 #include <sys/sysctl.h>
54 #include <sys/pool.h>
55
56 #include <dev/rndvar.h>
57
58 #include <miscfs/specfs/specdev.h>
59
60 #include <ufs/ufs/quota.h>
61 #include <ufs/ufs/ufsmount.h>
62 #include <ufs/ufs/inode.h>
63 #include <ufs/ufs/dir.h>
64 #include <ufs/ufs/ufs_extern.h>
65 #include <ufs/ufs/dirhash.h>
66
67 #include <ufs/ffs/fs.h>
68 #include <ufs/ffs/ffs_extern.h>
69
70 int ffs_sbupdate(struct ufsmount *, int);
71 int ffs_reload_vnode(struct vnode *, void *);
72 int ffs_sync_vnode(struct vnode *, void *);
73
74 const struct vfsops ffs_vfsops = {
75 ffs_mount,
76 ufs_start,
77 ffs_unmount,
78 ufs_root,
79 ufs_quotactl,
80 ffs_statfs,
81 ffs_sync,
82 ffs_vget,
83 ffs_fhtovp,
84 ffs_vptofh,
85 ffs_init,
86 ffs_sysctl,
87 ufs_check_export
88 };
89
90 struct inode_vtbl ffs_vtbl = {
91 ffs_truncate,
92 ffs_update,
93 ffs_inode_alloc,
94 ffs_inode_free,
95 ffs_balloc,
96 ffs_bufatoff
97 };
98
99 extern u_long nextgennumber;
100
101 /*
102 * Called by main() when ufs is going to be mounted as root.
103 */
104
105 struct pool ffs_ino_pool;
106
107 int
ffs_mountroot()108 ffs_mountroot()
109 {
110 struct fs *fs;
111 struct mount *mp;
112 struct proc *p = curproc; /* XXX */
113 struct ufsmount *ump;
114 int error;
115
116 /*
117 * Get vnodes for swapdev and rootdev.
118 */
119 swapdev_vp = NULL;
120 if ((error = bdevvp(swapdev, &swapdev_vp)) ||
121 (error = bdevvp(rootdev, &rootvp))) {
122 printf("ffs_mountroot: can't setup bdevvps\n");
123 if (swapdev_vp)
124 vrele(swapdev_vp);
125 return (error);
126 }
127
128 if ((error = vfs_rootmountalloc("ffs", "root_device", &mp)) != 0) {
129 vrele(swapdev_vp);
130 vrele(rootvp);
131 return (error);
132 }
133
134 if ((error = ffs_mountfs(rootvp, mp, p)) != 0) {
135 mp->mnt_vfc->vfc_refcount--;
136 vfs_unbusy(mp, p);
137 free(mp, M_MOUNT);
138 vrele(swapdev_vp);
139 vrele(rootvp);
140 return (error);
141 }
142 simple_lock(&mountlist_slock);
143 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
144 simple_unlock(&mountlist_slock);
145 ump = VFSTOUFS(mp);
146 fs = ump->um_fs;
147 (void) copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0);
148 (void)ffs_statfs(mp, &mp->mnt_stat, p);
149 vfs_unbusy(mp, p);
150 inittodr(fs->fs_time);
151 return (0);
152 }
153
154 /*
155 * VFS Operations.
156 *
157 * mount system call
158 */
159 int
ffs_mount(mp,path,data,ndp,p)160 ffs_mount(mp, path, data, ndp, p)
161 register struct mount *mp;
162 const char *path;
163 void *data;
164 struct nameidata *ndp;
165 struct proc *p;
166 {
167 struct vnode *devvp;
168 struct ufs_args args;
169 struct ufsmount *ump = NULL;
170 register struct fs *fs;
171 int error = 0, flags;
172 int ronly = 0;
173 mode_t accessmode;
174 size_t size;
175
176 error = copyin(data, &args, sizeof (struct ufs_args));
177 if (error)
178 return (error);
179
180 #ifndef FFS_SOFTUPDATES
181 if (mp->mnt_flag & MNT_SOFTDEP) {
182 printf("WARNING: soft updates isn't compiled in\n");
183 mp->mnt_flag &= ~MNT_SOFTDEP;
184 }
185 #endif
186
187 /*
188 * Soft updates is incompatible with "async",
189 * so if we are doing softupdates stop the user
190 * from setting the async flag.
191 */
192 if ((mp->mnt_flag & (MNT_SOFTDEP | MNT_ASYNC)) ==
193 (MNT_SOFTDEP | MNT_ASYNC)) {
194 return (EINVAL);
195 }
196 /*
197 * If updating, check whether changing from read-only to
198 * read/write; if there is no device name, that's all we do.
199 */
200 if (mp->mnt_flag & MNT_UPDATE) {
201 ump = VFSTOUFS(mp);
202 fs = ump->um_fs;
203 devvp = ump->um_devvp;
204 error = 0;
205 ronly = fs->fs_ronly;
206
207 if (ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
208 flags = WRITECLOSE;
209 if (mp->mnt_flag & MNT_FORCE)
210 flags |= FORCECLOSE;
211 if (fs->fs_flags & FS_DOSOFTDEP) {
212 error = softdep_flushfiles(mp, flags, p);
213 mp->mnt_flag &= ~MNT_SOFTDEP;
214 } else
215 error = ffs_flushfiles(mp, flags, p);
216 ronly = 1;
217 }
218
219 /*
220 * Flush soft dependencies if disabling it via an update
221 * mount. This may leave some items to be processed,
222 * so don't do this yet XXX.
223 */
224 if ((fs->fs_flags & FS_DOSOFTDEP) &&
225 !(mp->mnt_flag & MNT_SOFTDEP) &&
226 !(mp->mnt_flag & MNT_RDONLY) && fs->fs_ronly == 0) {
227 #if 0
228 flags = WRITECLOSE;
229 if (mp->mnt_flag & MNT_FORCE)
230 flags |= FORCECLOSE;
231 error = softdep_flushfiles(mp, flags, p);
232 #elif FFS_SOFTUPDATES
233 mp->mnt_flag |= MNT_SOFTDEP;
234 #endif
235 }
236 /*
237 * When upgrading to a softdep mount, we must first flush
238 * all vnodes. (not done yet -- see above)
239 */
240 if (!(fs->fs_flags & FS_DOSOFTDEP) &&
241 (mp->mnt_flag & MNT_SOFTDEP) && fs->fs_ronly == 0) {
242 #if 0
243 flags = WRITECLOSE;
244 if (mp->mnt_flag & MNT_FORCE)
245 flags |= FORCECLOSE;
246 error = ffs_flushfiles(mp, flags, p);
247 #else
248 mp->mnt_flag &= ~MNT_SOFTDEP;
249 #endif
250 }
251
252 if (!error && (mp->mnt_flag & MNT_RELOAD))
253 error = ffs_reload(mp, ndp->ni_cnd.cn_cred, p);
254 if (error)
255 goto error_1;
256
257 if (ronly && (mp->mnt_flag & MNT_WANTRDWR)) {
258 /*
259 * If upgrade to read-write by non-root, then verify
260 * that user has necessary permissions on the device.
261 */
262 if (p->p_ucred->cr_uid != 0) {
263 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
264 error = VOP_ACCESS(devvp, VREAD | VWRITE,
265 p->p_ucred, p);
266 VOP_UNLOCK(devvp, 0, p);
267 if (error)
268 goto error_1;
269 }
270
271 if (fs->fs_clean == 0) {
272 #ifdef DIAGNOSTIC
273 if (mp->mnt_flag & MNT_RELOAD)
274 printf(
275 "WARNING: %s still dirty after reload\n",
276 fs->fs_fsmnt);
277 #endif
278 #if 0
279 /*
280 * It is safe mount unclean file system
281 * if it was previously mounted with softdep
282 * but we may loss space and must
283 * sometimes run fsck manually.
284 */
285 if (fs->fs_flags & FS_DOSOFTDEP)
286 printf(
287 "WARNING: %s was not properly unmounted\n",
288 fs->fs_fsmnt);
289 else
290 #endif
291 if (mp->mnt_flag & MNT_FORCE) {
292 printf(
293 "WARNING: %s was not properly unmounted\n",
294 fs->fs_fsmnt);
295 } else {
296 printf(
297 "WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n",
298 fs->fs_fsmnt);
299 error = EROFS;
300 goto error_1;
301 }
302 }
303
304 if ((fs->fs_flags & FS_DOSOFTDEP)) {
305 error = softdep_mount(devvp, mp, fs,
306 p->p_ucred);
307 if (error)
308 goto error_1;
309 }
310 fs->fs_contigdirs=(u_int8_t*)malloc((u_long)fs->fs_ncg,
311 M_UFSMNT, M_WAITOK);
312 bzero(fs->fs_contigdirs, fs->fs_ncg);
313
314 ronly = 0;
315 }
316 if (args.fspec == 0) {
317 /*
318 * Process export requests.
319 */
320 error = vfs_export(mp, &ump->um_export,
321 &args.export_info);
322 if (error)
323 goto error_1;
324 else
325 goto success;
326 }
327 }
328 /*
329 * Not an update, or updating the name: look up the name
330 * and verify that it refers to a sensible block device.
331 */
332 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
333 if ((error = namei(ndp)) != 0)
334 goto error_1;
335
336 devvp = ndp->ni_vp;
337
338 if (devvp->v_type != VBLK) {
339 error = ENOTBLK;
340 goto error_2;
341 }
342
343 if (major(devvp->v_rdev) >= nblkdev) {
344 error = ENXIO;
345 goto error_2;
346 }
347
348 /*
349 * If mount by non-root, then verify that user has necessary
350 * permissions on the device.
351 */
352 if (p->p_ucred->cr_uid != 0) {
353 accessmode = VREAD;
354 if ((mp->mnt_flag & MNT_RDONLY) == 0)
355 accessmode |= VWRITE;
356 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
357 error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p);
358 VOP_UNLOCK(devvp, 0, p);
359 if (error)
360 goto error_2;
361 }
362
363 if (mp->mnt_flag & MNT_UPDATE) {
364 /*
365 * UPDATE
366 * If it's not the same vnode, or at least the same device
367 * then it's not correct.
368 */
369
370 if (devvp != ump->um_devvp) {
371 if (devvp->v_rdev == ump->um_devvp->v_rdev) {
372 vrele(devvp);
373 } else {
374 error = EINVAL; /* needs translation */
375 }
376 } else
377 vrele(devvp);
378 /*
379 * Update device name only on success
380 */
381 if (!error) {
382 /*
383 * Save "mounted from" info for mount point (NULL pad)
384 */
385 copyinstr(args.fspec,
386 mp->mnt_stat.f_mntfromname,
387 MNAMELEN - 1,
388 &size);
389 bzero(mp->mnt_stat.f_mntfromname + size,
390 MNAMELEN - size);
391 }
392 } else {
393 /*
394 * Since this is a new mount, we want the names for
395 * the device and the mount point copied in. If an
396 * error occurs, the mountpoint is discarded by the
397 * upper level code.
398 */
399 /* Save "last mounted on" info for mount point (NULL pad)*/
400 copyinstr(path, /* mount point*/
401 mp->mnt_stat.f_mntonname, /* save area*/
402 MNAMELEN - 1, /* max size*/
403 &size); /* real size*/
404 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
405
406 /* Save "mounted from" info for mount point (NULL pad)*/
407 copyinstr(args.fspec, /* device name*/
408 mp->mnt_stat.f_mntfromname, /* save area*/
409 MNAMELEN - 1, /* max size*/
410 &size); /* real size*/
411 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
412
413 error = ffs_mountfs(devvp, mp, p);
414 }
415
416 if (error)
417 goto error_2;
418
419 /*
420 * Initialize FS stat information in mount struct; uses both
421 * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname
422 *
423 * This code is common to root and non-root mounts
424 */
425 bcopy(&args, &mp->mnt_stat.mount_info.ufs_args, sizeof(args));
426 (void)VFS_STATFS(mp, &mp->mnt_stat, p);
427
428 success:
429 if (path && (mp->mnt_flag & MNT_UPDATE)) {
430 /* Update clean flag after changing read-onlyness. */
431 fs = ump->um_fs;
432 if (ronly != fs->fs_ronly) {
433 fs->fs_ronly = ronly;
434 fs->fs_clean = ronly &&
435 (fs->fs_flags & FS_UNCLEAN) == 0 ? 1 : 0;
436 if (ronly)
437 free(fs->fs_contigdirs, M_UFSMNT);
438 }
439 if (!ronly) {
440 if (mp->mnt_flag & MNT_SOFTDEP)
441 fs->fs_flags |= FS_DOSOFTDEP;
442 else
443 fs->fs_flags &= ~FS_DOSOFTDEP;
444 }
445 /* add entropy, in case it's remount r/o */
446 arc4random_buf(fs->fs_historic_start,
447 sizeof(fs->fs_historic_start));
448 ffs_sbupdate(ump, MNT_WAIT);
449 }
450 return (0);
451
452 error_2: /* error with devvp held */
453 vrele (devvp);
454 error_1: /* no state to back out */
455 return (error);
456 }
457
458
459 struct ffs_reload_args {
460 struct fs *fs;
461 struct proc *p;
462 struct ucred *cred;
463 struct vnode *devvp;
464 };
465
466 int
ffs_reload_vnode(struct vnode * vp,void * args)467 ffs_reload_vnode(struct vnode *vp, void *args)
468 {
469 struct ffs_reload_args *fra = args;
470 struct inode *ip;
471 struct buf *bp;
472 int error;
473
474 /*
475 * Step 4: invalidate all inactive vnodes.
476 */
477 if (vp->v_usecount == 0) {
478 vgonel(vp, fra->p);
479 return (0);
480 }
481
482 /*
483 * Step 5: invalidate all cached file data.
484 */
485 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, fra->p))
486 return (0);
487
488 if (vinvalbuf(vp, 0, fra->cred, fra->p, 0, 0))
489 panic("ffs_reload: dirty2");
490 /*
491 * Step 6: re-read inode data for all active vnodes.
492 */
493 ip = VTOI(vp);
494 error = bread(fra->devvp,
495 fsbtodb(fra->fs, ino_to_fsba(fra->fs, ip->i_number)),
496 (int)fra->fs->fs_bsize, NOCRED, &bp);
497 if (error) {
498 vput(vp);
499 return (error);
500 }
501 ip->i_din1 = *((struct ufs1_dinode *)bp->b_data +
502 ino_to_fsbo(fra->fs, ip->i_number));
503 ip->i_effnlink = ip->i_ffs_nlink;
504 brelse(bp);
505 vput(vp);
506 return (0);
507 }
508
509 /*
510 * Reload all incore data for a filesystem (used after running fsck on
511 * the root filesystem and finding things to fix). The filesystem must
512 * be mounted read-only.
513 *
514 * Things to do to update the mount:
515 * 1) invalidate all cached meta-data.
516 * 2) re-read superblock from disk.
517 * 3) re-read summary information from disk.
518 * 4) invalidate all inactive vnodes.
519 * 5) invalidate all cached file data.
520 * 6) re-read inode data for all active vnodes.
521 */
522 int
ffs_reload(mountp,cred,p)523 ffs_reload(mountp, cred, p)
524 register struct mount *mountp;
525 struct ucred *cred;
526 struct proc *p;
527 {
528 struct vnode *devvp;
529 caddr_t space;
530 struct fs *fs, *newfs;
531 struct partinfo dpart;
532 int i, blks, size, error;
533 int32_t *lp;
534 struct buf *bp = NULL;
535 struct ffs_reload_args fra;
536
537 if ((mountp->mnt_flag & MNT_RDONLY) == 0)
538 return (EINVAL);
539 /*
540 * Step 1: invalidate all cached meta-data.
541 */
542 devvp = VFSTOUFS(mountp)->um_devvp;
543 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
544 error = vinvalbuf(devvp, 0, cred, p, 0, 0);
545 VOP_UNLOCK(devvp, 0, p);
546 if (error)
547 panic("ffs_reload: dirty1");
548
549 /*
550 * Step 2: re-read superblock from disk.
551 */
552 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
553 size = DEV_BSIZE;
554 else
555 size = dpart.disklab->d_secsize;
556 error = bread(devvp, (daddr_t)(SBOFF / size), SBSIZE, NOCRED, &bp);
557 if (error)
558 return (error);
559 newfs = (struct fs *)bp->b_data;
560 if (newfs->fs_magic != FS_MAGIC || (u_int)newfs->fs_bsize > MAXBSIZE ||
561 newfs->fs_bsize < sizeof(struct fs) ||
562 (u_int)newfs->fs_sbsize > SBSIZE) {
563 brelse(bp);
564 return (EIO); /* XXX needs translation */
565 }
566 fs = VFSTOUFS(mountp)->um_fs;
567 /*
568 * Copy pointer fields back into superblock before copying in XXX
569 * new superblock. These should really be in the ufsmount. XXX
570 * Note that important parameters (eg fs_ncg) are unchanged.
571 */
572 newfs->fs_csp = fs->fs_csp;
573 newfs->fs_maxcluster = fs->fs_maxcluster;
574 newfs->fs_ronly = fs->fs_ronly;
575 bcopy(newfs, fs, (u_int)fs->fs_sbsize);
576 if (fs->fs_sbsize < SBSIZE)
577 bp->b_flags |= B_INVAL;
578 brelse(bp);
579 mountp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
580 ffs_oldfscompat(fs);
581 (void)ffs_statfs(mountp, &mountp->mnt_stat, p);
582 /*
583 * Step 3: re-read summary information from disk.
584 */
585 blks = howmany(fs->fs_cssize, fs->fs_fsize);
586 space = (caddr_t)fs->fs_csp;
587 for (i = 0; i < blks; i += fs->fs_frag) {
588 size = fs->fs_bsize;
589 if (i + fs->fs_frag > blks)
590 size = (blks - i) * fs->fs_fsize;
591 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
592 NOCRED, &bp);
593 if (error)
594 return (error);
595 bcopy(bp->b_data, space, (u_int)size);
596 space += size;
597 brelse(bp);
598 }
599 if ((fs->fs_flags & FS_DOSOFTDEP))
600 (void) softdep_mount(devvp, mountp, fs, cred);
601 /*
602 * We no longer know anything about clusters per cylinder group.
603 */
604 if (fs->fs_contigsumsize > 0) {
605 lp = fs->fs_maxcluster;
606 for (i = 0; i < fs->fs_ncg; i++)
607 *lp++ = fs->fs_contigsumsize;
608 }
609
610 fra.p = p;
611 fra.cred = cred;
612 fra.fs = fs;
613 fra.devvp = devvp;
614
615 error = vfs_mount_foreach_vnode(mountp, ffs_reload_vnode, &fra);
616
617 return (error);
618 }
619
620 /*
621 * Common code for mount and mountroot
622 */
623 int
ffs_mountfs(devvp,mp,p)624 ffs_mountfs(devvp, mp, p)
625 register struct vnode *devvp;
626 struct mount *mp;
627 struct proc *p;
628 {
629 register struct ufsmount *ump;
630 struct buf *bp;
631 register struct fs *fs;
632 dev_t dev;
633 struct partinfo dpart;
634 caddr_t space;
635 int error, i, blks, size, ronly;
636 int32_t *lp;
637 size_t strsize;
638 struct ucred *cred;
639 u_int64_t maxfilesize; /* XXX */
640
641 dev = devvp->v_rdev;
642 cred = p ? p->p_ucred : NOCRED;
643 /*
644 * Disallow multiple mounts of the same device.
645 * Disallow mounting of a device that is currently in use
646 * (except for root, which might share swap device for miniroot).
647 * Flush out any old buffers remaining from a previous use.
648 */
649 if ((error = vfs_mountedon(devvp)) != 0)
650 return (error);
651 if (vcount(devvp) > 1 && devvp != rootvp)
652 return (EBUSY);
653 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
654 error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0);
655 VOP_UNLOCK(devvp, 0, p);
656 if (error)
657 return (error);
658
659 ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
660 error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
661 if (error)
662 return (error);
663 if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0)
664 size = DEV_BSIZE;
665 else
666 size = dpart.disklab->d_secsize;
667
668 bp = NULL;
669 ump = NULL;
670 error = bread(devvp, (daddr_t)(SBOFF / size), SBSIZE, cred, &bp);
671 if (error)
672 goto out;
673 fs = (struct fs *)bp->b_data;
674
675 /*
676 * MirOS ffs specific: add true (first two) and pseudo (last)
677 * randomness from superblock
678 */
679 rnd_lopool_add(fs->fs_historic_start, sizeof(fs->fs_historic_start));
680 rnd_lopool_addh(fs, SBSIZE);
681 arc4random_buf(fs->fs_historic_start, sizeof(fs->fs_historic_start));
682
683 if (fs->fs_magic != FS_UFS1_MAGIC || (u_int)fs->fs_bsize > MAXBSIZE ||
684 fs->fs_bsize < sizeof(struct fs) ||
685 (u_int)fs->fs_sbsize > SBSIZE) {
686 if (fs->fs_magic == FS_UFS2_MAGIC)
687 printf("no UFS2 support\n");
688 error = EFTYPE; /* Inappropriate format */
689 goto out;
690 }
691 fs->fs_fmod = 0;
692 fs->fs_flags &= ~FS_UNCLEAN;
693 if (fs->fs_clean == 0) {
694 fs->fs_flags |= FS_UNCLEAN;
695 #if 0
696 /*
697 * It is safe mount unclean file system
698 * if it was previously mounted with softdep
699 * but we may loss space and must
700 * sometimes run fsck manually.
701 */
702 if (fs->fs_flags & FS_DOSOFTDEP)
703 printf(
704 "WARNING: %s was not properly unmounted\n",
705 fs->fs_fsmnt);
706 else
707 #endif
708 if (ronly || (mp->mnt_flag & MNT_FORCE)) {
709 printf(
710 "WARNING: %s was not properly unmounted\n",
711 fs->fs_fsmnt);
712 } else {
713 printf(
714 "WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n",
715 fs->fs_fsmnt);
716 error = EROFS;
717 goto out;
718 }
719 }
720 /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */
721 if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) {
722 error = EROFS; /* XXX what should be returned? */
723 goto out;
724 }
725 ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
726 bzero(ump, sizeof *ump);
727 ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT,
728 M_WAITOK);
729 if (fs->fs_magic == FS_UFS1_MAGIC) {
730 ump->um_fstype = UM_UFS1;
731 }
732 bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize);
733 if (fs->fs_sbsize < SBSIZE)
734 bp->b_flags |= B_INVAL;
735 brelse(bp);
736 bp = NULL;
737 fs = ump->um_fs;
738 fs->fs_ronly = ronly;
739 size = fs->fs_cssize;
740 blks = howmany(size, fs->fs_fsize);
741 if (fs->fs_contigsumsize > 0)
742 size += fs->fs_ncg * sizeof(int32_t);
743 space = malloc((u_long)size, M_UFSMNT, M_WAITOK);
744 fs->fs_csp = (struct csum *)space;
745 for (i = 0; i < blks; i += fs->fs_frag) {
746 size = fs->fs_bsize;
747 if (i + fs->fs_frag > blks)
748 size = (blks - i) * fs->fs_fsize;
749 error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
750 cred, &bp);
751 if (error) {
752 free(fs->fs_csp, M_UFSMNT);
753 goto out;
754 }
755 bcopy(bp->b_data, space, (u_int)size);
756 space += size;
757 brelse(bp);
758 bp = NULL;
759 }
760 if (fs->fs_contigsumsize > 0) {
761 fs->fs_maxcluster = lp = (int32_t *)space;
762 for (i = 0; i < fs->fs_ncg; i++)
763 *lp++ = fs->fs_contigsumsize;
764 }
765 mp->mnt_data = (qaddr_t)ump;
766 mp->mnt_stat.f_fsid.val[0] = (long)dev;
767 /* Use on-disk fsid if it exists, else fake it */
768 if (fs->fs_id[0] != 0 && fs->fs_id[1] != 0)
769 mp->mnt_stat.f_fsid.val[1] = fs->fs_id[1];
770 else
771 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
772 mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
773 mp->mnt_flag |= MNT_LOCAL;
774 ump->um_mountp = mp;
775 ump->um_dev = dev;
776 ump->um_devvp = devvp;
777 ump->um_nindir = fs->fs_nindir;
778 ump->um_bptrtodb = fs->fs_fsbtodb;
779 ump->um_seqinc = fs->fs_frag;
780 for (i = 0; i < MAXQUOTAS; i++)
781 ump->um_quotas[i] = NULLVP;
782
783 devvp->v_specmountpoint = mp;
784 ffs_oldfscompat(fs);
785
786 if (ronly)
787 fs->fs_contigdirs = NULL;
788 else {
789 fs->fs_contigdirs = (u_int8_t*)malloc((u_long)fs->fs_ncg,
790 M_UFSMNT, M_WAITOK);
791 bzero(fs->fs_contigdirs, fs->fs_ncg);
792 }
793
794 /*
795 * Set FS local "last mounted on" information (NULL pad)
796 */
797 copystr(mp->mnt_stat.f_mntonname, /* mount point*/
798 fs->fs_fsmnt, /* copy area*/
799 sizeof(fs->fs_fsmnt) - 1, /* max size*/
800 &strsize); /* real size*/
801 bzero(fs->fs_fsmnt + strsize, sizeof(fs->fs_fsmnt) - strsize);
802
803 #if 0
804 if( mp->mnt_flag & MNT_ROOTFS) {
805 /*
806 * Root mount; update timestamp in mount structure.
807 * this will be used by the common root mount code
808 * to update the system clock.
809 */
810 mp->mnt_time = fs->fs_time;
811 }
812 #endif
813
814 /*
815 * XXX
816 * Limit max file size. Even though ffs can handle files up to 16TB,
817 * we do limit the max file to 2^31 pages to prevent overflow of
818 * a 32-bit unsigned int. The buffer cache has its own checks but
819 * a little added paranoia never hurts.
820 */
821 ump->um_savedmaxfilesize = fs->fs_maxfilesize; /* XXX */
822 maxfilesize = (u_int64_t)0x80000000 * MIN(PAGE_SIZE, fs->fs_bsize) - 1;
823 if (fs->fs_maxfilesize > maxfilesize) /* XXX */
824 fs->fs_maxfilesize = maxfilesize; /* XXX */
825 if (ronly == 0) {
826 if ((fs->fs_flags & FS_DOSOFTDEP) &&
827 (error = softdep_mount(devvp, mp, fs, cred)) != 0) {
828 free(fs->fs_csp, M_UFSMNT);
829 free(fs->fs_contigdirs, M_UFSMNT);
830 goto out;
831 }
832 fs->fs_fmod = 1;
833 fs->fs_clean = 0;
834 if (mp->mnt_flag & MNT_SOFTDEP)
835 fs->fs_flags |= FS_DOSOFTDEP;
836 else
837 fs->fs_flags &= ~FS_DOSOFTDEP;
838 (void) ffs_sbupdate(ump, MNT_WAIT);
839 }
840 return (0);
841 out:
842 devvp->v_specmountpoint = NULL;
843 if (bp)
844 brelse(bp);
845 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
846 if (ump) {
847 free(ump->um_fs, M_UFSMNT);
848 free(ump, M_UFSMNT);
849 mp->mnt_data = (qaddr_t)0;
850 }
851 return (error);
852 }
853
854 /*
855 * Sanity checks for old file systems.
856 *
857 * XXX - goes away some day.
858 */
859 int
ffs_oldfscompat(fs)860 ffs_oldfscompat(fs)
861 struct fs *fs;
862 {
863 int i;
864
865 fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */
866 fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */
867 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
868 fs->fs_nrpos = 8; /* XXX */
869 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
870 u_int64_t sizepb = fs->fs_bsize; /* XXX */
871 /* XXX */
872 fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
873 for (i = 0; i < NIADDR; i++) { /* XXX */
874 sizepb *= NINDIR(fs); /* XXX */
875 fs->fs_maxfilesize += sizepb; /* XXX */
876 } /* XXX */
877 fs->fs_qbmask = ~fs->fs_bmask; /* XXX */
878 fs->fs_qfmask = ~fs->fs_fmask; /* XXX */
879 } /* XXX */
880 if (fs->fs_avgfilesize <= 0) /* XXX */
881 fs->fs_avgfilesize = AVFILESIZ; /* XXX */
882 if (fs->fs_avgfpdir <= 0) /* XXX */
883 fs->fs_avgfpdir = AFPDIR; /* XXX */
884 return (0);
885 }
886
887 /*
888 * unmount system call
889 */
890 int
ffs_unmount(mp,mntflags,p)891 ffs_unmount(mp, mntflags, p)
892 struct mount *mp;
893 int mntflags;
894 struct proc *p;
895 {
896 register struct ufsmount *ump;
897 register struct fs *fs;
898 int error, flags;
899
900 flags = 0;
901 if (mntflags & MNT_FORCE)
902 flags |= FORCECLOSE;
903
904 ump = VFSTOUFS(mp);
905 fs = ump->um_fs;
906
907 /* MirOS specific: write random data into superblock (entropy seed) */
908 arc4random_buf(fs->fs_historic_start, sizeof(fs->fs_historic_start));
909
910 if (mp->mnt_flag & MNT_SOFTDEP)
911 error = softdep_flushfiles(mp, flags, p);
912 else
913 error = ffs_flushfiles(mp, flags, p);
914 if (error != 0)
915 return (error);
916
917 if (fs->fs_ronly == 0) {
918 fs->fs_clean = (fs->fs_flags & FS_UNCLEAN) ? 0 : 1;
919 error = ffs_sbupdate(ump, MNT_WAIT);
920 if (error) {
921 fs->fs_clean = 0;
922 return (error);
923 }
924 free(fs->fs_contigdirs, M_UFSMNT);
925 }
926 ump->um_devvp->v_specmountpoint = NULL;
927
928 vinvalbuf(ump->um_devvp, V_SAVE, NOCRED, p, 0, 0);
929 error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
930 NOCRED, p);
931 vrele(ump->um_devvp);
932 free(fs->fs_csp, M_UFSMNT);
933 free(fs, M_UFSMNT);
934 free(ump, M_UFSMNT);
935 mp->mnt_data = (qaddr_t)0;
936 mp->mnt_flag &= ~MNT_LOCAL;
937 return (error);
938 }
939
940 /*
941 * Flush out all the files in a filesystem.
942 */
943 int
ffs_flushfiles(mp,flags,p)944 ffs_flushfiles(mp, flags, p)
945 register struct mount *mp;
946 int flags;
947 struct proc *p;
948 {
949 register struct ufsmount *ump;
950 int error;
951
952 ump = VFSTOUFS(mp);
953 if (mp->mnt_flag & MNT_QUOTA) {
954 int i;
955 if ((error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) != 0)
956 return (error);
957 for (i = 0; i < MAXQUOTAS; i++) {
958 if (ump->um_quotas[i] == NULLVP)
959 continue;
960 quotaoff(p, mp, i);
961 }
962 /*
963 * Here we fall through to vflush again to ensure
964 * that we have gotten rid of all the system vnodes.
965 */
966 }
967
968 /*
969 * Flush all the files.
970 */
971 if ((error = vflush(mp, NULL, flags)) != 0)
972 return (error);
973 /*
974 * Flush filesystem metadata.
975 */
976 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
977 error = VOP_FSYNC(ump->um_devvp, p->p_ucred, MNT_WAIT, p);
978 VOP_UNLOCK(ump->um_devvp, 0, p);
979 return (error);
980 }
981
982 /*
983 * Get file system statistics.
984 */
985 int
ffs_statfs(mp,sbp,p)986 ffs_statfs(mp, sbp, p)
987 struct mount *mp;
988 register struct statfs *sbp;
989 struct proc *p;
990 {
991 register struct ufsmount *ump;
992 register struct fs *fs;
993
994 ump = VFSTOUFS(mp);
995 fs = ump->um_fs;
996 if (fs->fs_magic != FS_MAGIC)
997 panic("ffs_statfs");
998 sbp->f_bsize = fs->fs_fsize;
999 sbp->f_iosize = fs->fs_bsize;
1000 sbp->f_blocks = fs->fs_dsize;
1001 sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
1002 fs->fs_cstotal.cs_nffree;
1003 sbp->f_bavail = sbp->f_bfree - ((int64_t)fs->fs_dsize * fs->fs_minfree / 100);
1004 sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
1005 sbp->f_ffree = fs->fs_cstotal.cs_nifree;
1006 if (sbp != &mp->mnt_stat) {
1007 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
1008 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
1009 bcopy(&mp->mnt_stat.mount_info.ufs_args,
1010 &sbp->mount_info.ufs_args, sizeof(struct ufs_args));
1011 }
1012 strncpy(sbp->f_fstypename, mp->mnt_vfc->vfc_name, MFSNAMELEN);
1013 return (0);
1014 }
1015
1016
1017 struct ffs_sync_args {
1018 int allerror;
1019 struct proc *p;
1020 int waitfor;
1021 struct ucred *cred;
1022 };
1023
1024 int
ffs_sync_vnode(struct vnode * vp,void * arg)1025 ffs_sync_vnode(struct vnode *vp, void *arg) {
1026 struct ffs_sync_args *fsa = arg;
1027 struct inode *ip;
1028 int error;
1029
1030 ip = VTOI(vp);
1031 if (fsa->waitfor == MNT_LAZY ||
1032 vp->v_type == VNON ||
1033 ((ip->i_flag &
1034 (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
1035 LIST_EMPTY(&vp->v_dirtyblkhd)) ) {
1036 simple_unlock(&vp->v_interlock);
1037 return (0);
1038 }
1039
1040 if (vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, fsa->p))
1041 return (0);
1042
1043 if ((error = VOP_FSYNC(vp, fsa->cred, fsa->waitfor, fsa->p)))
1044 fsa->allerror = error;
1045 VOP_UNLOCK(vp, 0, fsa->p);
1046 vrele(vp);
1047
1048 return (0);
1049 }
1050
1051 /*
1052 * Go through the disk queues to initiate sandbagged IO;
1053 * go through the inodes to write those that have been modified;
1054 * initiate the writing of the super block if it has been modified.
1055 *
1056 * Note: we are always called with the filesystem marked 'MPBUSY'.
1057 */
1058 int
ffs_sync(mp,waitfor,cred,p)1059 ffs_sync(mp, waitfor, cred, p)
1060 struct mount *mp;
1061 int waitfor;
1062 struct ucred *cred;
1063 struct proc *p;
1064 {
1065 struct ufsmount *ump = VFSTOUFS(mp);
1066 struct fs *fs;
1067 int error, allerror = 0, count;
1068 struct ffs_sync_args fsa;
1069
1070 fs = ump->um_fs;
1071 /*
1072 * Write back modified superblock.
1073 * Consistency check that the superblock
1074 * is still in the buffer cache.
1075 */
1076 if (fs->fs_fmod != 0 && fs->fs_ronly != 0) {
1077 printf("fs = %s\n", fs->fs_fsmnt);
1078 panic("update: rofs mod");
1079 }
1080
1081 loop:
1082 /*
1083 * Write back each (modified) inode.
1084 */
1085 fsa.allerror = 0;
1086 fsa.p = p;
1087 fsa.cred = cred;
1088 fsa.waitfor = waitfor;
1089
1090 vfs_mount_foreach_vnode(mp, ffs_sync_vnode, &fsa);
1091
1092 if (fsa.allerror != 0)
1093 allerror = fsa.allerror;
1094 /*
1095 * Force stale file system control information to be flushed.
1096 */
1097 if ((ump->um_mountp->mnt_flag & MNT_SOFTDEP) && waitfor == MNT_WAIT) {
1098 if ((error = softdep_flushworklist(ump->um_mountp, &count, p)))
1099 allerror = error;
1100 /* Flushed work items may create new vnodes to clean */
1101 if (count)
1102 goto loop;
1103 }
1104 if (waitfor != MNT_LAZY) {
1105 if (ump->um_mountp->mnt_flag & MNT_SOFTDEP)
1106 waitfor = MNT_NOWAIT;
1107 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
1108 if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0)
1109 allerror = error;
1110 VOP_UNLOCK(ump->um_devvp, 0, p);
1111 }
1112 qsync(mp);
1113 /*
1114 * Write back modified superblock.
1115 */
1116
1117 if (fs->fs_fmod != 0 && (error = ffs_sbupdate(ump, waitfor)) != 0)
1118 allerror = error;
1119
1120 return (allerror);
1121 }
1122
1123 /*
1124 * Look up a FFS dinode number to find its incore vnode, otherwise read it
1125 * in from disk. If it is in core, wait for the lock bit to clear, then
1126 * return the inode locked. Detection and handling of mount points must be
1127 * done by the calling routine.
1128 */
1129 int
ffs_vget(mp,ino,vpp)1130 ffs_vget(mp, ino, vpp)
1131 struct mount *mp;
1132 ino_t ino;
1133 struct vnode **vpp;
1134 {
1135 register struct fs *fs;
1136 register struct inode *ip;
1137 struct ufsmount *ump;
1138 struct buf *bp;
1139 struct vnode *vp;
1140 dev_t dev;
1141 int error;
1142
1143 ump = VFSTOUFS(mp);
1144 dev = ump->um_dev;
1145
1146 retry:
1147 if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
1148 return (0);
1149
1150 /* Allocate a new vnode/inode. */
1151 if ((error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp)) != 0) {
1152 *vpp = NULL;
1153 return (error);
1154 }
1155 #ifdef VFSDEBUG
1156 vp->v_flag |= VLOCKSWORK;
1157 #endif
1158 /* XXX - we use the same pool for ffs and mfs */
1159 ip = pool_get(&ffs_ino_pool, PR_WAITOK);
1160 bzero((caddr_t)ip, sizeof(struct inode));
1161 lockinit(&ip->i_lock, PINOD, "inode", 0, 0);
1162 ip->i_ump = ump;
1163 VREF(ip->i_devvp);
1164 vp->v_data = ip;
1165 ip->i_vnode = vp;
1166 ip->i_fs = fs = ump->um_fs;
1167 ip->i_dev = dev;
1168 ip->i_number = ino;
1169 ip->i_vtbl = &ffs_vtbl;
1170
1171 /*
1172 * Put it onto its hash chain and lock it so that other requests for
1173 * this inode will block if they arrive while we are sleeping waiting
1174 * for old data structures to be purged or for the contents of the
1175 * disk portion of this inode to be read.
1176 */
1177 error = ufs_ihashins(ip);
1178
1179 if (error) {
1180 /*
1181 * VOP_INACTIVE will treat this as a stale file
1182 * and recycle it quickly
1183 */
1184 vrele(vp);
1185
1186 if (error == EEXIST)
1187 goto retry;
1188
1189 return (error);
1190 }
1191
1192
1193 /* Read in the disk contents for the inode, copy into the inode. */
1194 error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
1195 (int)fs->fs_bsize, NOCRED, &bp);
1196 if (error) {
1197 /*
1198 * The inode does not contain anything useful, so it would
1199 * be misleading to leave it on its hash chain. With mode
1200 * still zero, it will be unlinked and returned to the free
1201 * list by vput().
1202 */
1203 vput(vp);
1204 brelse(bp);
1205 *vpp = NULL;
1206 return (error);
1207 }
1208 ip->i_din1 = *((struct ufs1_dinode *)bp->b_data + ino_to_fsbo(fs, ino));
1209 if (DOINGSOFTDEP(vp))
1210 softdep_load_inodeblock(ip);
1211 else
1212 ip->i_effnlink = ip->i_ffs_nlink;
1213 brelse(bp);
1214
1215 /*
1216 * Initialize the vnode from the inode, check for aliases.
1217 * Note that the underlying vnode may have changed.
1218 */
1219 error = ufs_vinit(mp, ffs_specop_p, FFS_FIFOOPS, &vp);
1220 if (error) {
1221 vput(vp);
1222 *vpp = NULL;
1223 return (error);
1224 }
1225 /*
1226 * Set up a generation number for this inode if it does not
1227 * already have one. This should only happen on old filesystems.
1228 */
1229 if (ip->i_ffs_gen == 0) {
1230 ip->i_ffs_gen = arc4random() & INT_MAX;
1231 if (ip->i_ffs_gen == 0 || ip->i_ffs_gen == -1)
1232 ip->i_ffs_gen = 1; /* shouldn't happen */
1233 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
1234 ip->i_flag |= IN_MODIFIED;
1235 }
1236 /*
1237 * Ensure that uid and gid are correct. This is a temporary
1238 * fix until fsck has been changed to do the update.
1239 */
1240 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
1241 ip->i_ffs_uid = ip->i_din1.di_ouid; /* XXX */
1242 ip->i_ffs_gid = ip->i_din1.di_ogid; /* XXX */
1243 } /* XXX */
1244
1245 *vpp = vp;
1246 return (0);
1247 }
1248
1249 /*
1250 * File handle to vnode
1251 *
1252 * Have to be really careful about stale file handles:
1253 * - check that the inode number is valid
1254 * - call ffs_vget() to get the locked inode
1255 * - check for an unallocated inode (i_mode == 0)
1256 */
1257 int
ffs_fhtovp(mp,fhp,vpp)1258 ffs_fhtovp(mp, fhp, vpp)
1259 register struct mount *mp;
1260 struct fid *fhp;
1261 struct vnode **vpp;
1262 {
1263 register struct ufid *ufhp;
1264 struct fs *fs;
1265
1266 ufhp = (struct ufid *)fhp;
1267 fs = VFSTOUFS(mp)->um_fs;
1268 if (ufhp->ufid_ino < ROOTINO ||
1269 ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg)
1270 return (ESTALE);
1271 return (ufs_fhtovp(mp, ufhp, vpp));
1272 }
1273
1274 /*
1275 * Vnode pointer to File handle
1276 */
1277 /* ARGSUSED */
1278 int
ffs_vptofh(vp,fhp)1279 ffs_vptofh(vp, fhp)
1280 struct vnode *vp;
1281 struct fid *fhp;
1282 {
1283 register struct inode *ip;
1284 register struct ufid *ufhp;
1285
1286 ip = VTOI(vp);
1287 ufhp = (struct ufid *)fhp;
1288 ufhp->ufid_len = sizeof(struct ufid);
1289 ufhp->ufid_ino = ip->i_number;
1290 ufhp->ufid_gen = ip->i_ffs_gen;
1291 return (0);
1292 }
1293
1294 /*
1295 * Write a superblock and associated information back to disk.
1296 */
1297 int
ffs_sbupdate(mp,waitfor)1298 ffs_sbupdate(mp, waitfor)
1299 struct ufsmount *mp;
1300 int waitfor;
1301 {
1302 register struct fs *dfs, *fs = mp->um_fs;
1303 register struct buf *bp;
1304 int blks;
1305 caddr_t space;
1306 int i, size, error, allerror = 0;
1307
1308 /*
1309 * First write back the summary information.
1310 */
1311 blks = howmany(fs->fs_cssize, fs->fs_fsize);
1312 space = (caddr_t)fs->fs_csp;
1313 for (i = 0; i < blks; i += fs->fs_frag) {
1314 size = fs->fs_bsize;
1315 if (i + fs->fs_frag > blks)
1316 size = (blks - i) * fs->fs_fsize;
1317 bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
1318 size, 0, 0);
1319 bcopy(space, bp->b_data, (u_int)size);
1320 space += size;
1321 if (waitfor != MNT_WAIT)
1322 bawrite(bp);
1323 else if ((error = bwrite(bp)))
1324 allerror = error;
1325 }
1326 /*
1327 * Now write back the superblock itself. If any errors occurred
1328 * up to this point, then fail so that the superblock avoids
1329 * being written out as clean.
1330 */
1331 if (allerror)
1332 return (allerror);
1333
1334 bp = getblk(mp->um_devvp, SBOFF >> (fs->fs_fshift - fs->fs_fsbtodb),
1335 (int)fs->fs_sbsize, 0, 0);
1336 fs->fs_fmod = 0;
1337 fs->fs_time = time.tv_sec;
1338 bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
1339 /* Restore compatibility to old file systems. XXX */
1340 dfs = (struct fs *)bp->b_data; /* XXX */
1341 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
1342 dfs->fs_nrpos = -1; /* XXX */
1343 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
1344 int32_t *lp, tmp; /* XXX */
1345 /* XXX */
1346 lp = (int32_t *)&dfs->fs_qbmask; /* XXX */
1347 tmp = lp[4]; /* XXX */
1348 for (i = 4; i > 0; i--) /* XXX */
1349 lp[i] = lp[i-1]; /* XXX */
1350 lp[0] = tmp; /* XXX */
1351 } /* XXX */
1352 dfs->fs_maxfilesize = mp->um_savedmaxfilesize; /* XXX */
1353 if (waitfor != MNT_WAIT)
1354 bawrite(bp);
1355 else if ((error = bwrite(bp)))
1356 allerror = error;
1357 return (allerror);
1358 }
1359
1360 int
ffs_init(vfsp)1361 ffs_init(vfsp)
1362 struct vfsconf *vfsp;
1363 {
1364 static int done;
1365
1366 if (done)
1367 return (0);
1368 done = 1;
1369 pool_init(&ffs_ino_pool, sizeof(struct inode), 0, 0, 0, "ffsino",
1370 &pool_allocator_nointr);
1371 softdep_initialize();
1372 return (ufs_init(vfsp));
1373 }
1374
1375 /*
1376 * fast filesystem related variables.
1377 */
1378 int
ffs_sysctl(name,namelen,oldp,oldlenp,newp,newlen,p)1379 ffs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
1380 int *name;
1381 u_int namelen;
1382 void *oldp;
1383 size_t *oldlenp;
1384 void *newp;
1385 size_t newlen;
1386 struct proc *p;
1387 {
1388 extern int doclusterread, doclusterwrite, doreallocblks, doasyncfree;
1389 #ifdef FFS_SOFTUPDATES
1390 extern int max_softdeps, tickdelay, stat_worklist_push;
1391 extern int stat_blk_limit_push, stat_ino_limit_push, stat_blk_limit_hit;
1392 extern int stat_ino_limit_hit, stat_sync_limit_hit, stat_indir_blk_ptrs;
1393 extern int stat_inode_bitmap, stat_direct_blk_ptrs, stat_dir_entry;
1394 #endif
1395
1396 /* all sysctl names at this level are terminal */
1397 if (namelen != 1)
1398 return (ENOTDIR); /* overloaded */
1399
1400 switch (name[0]) {
1401 case FFS_CLUSTERREAD:
1402 return (sysctl_int(oldp, oldlenp, newp, newlen,
1403 &doclusterread));
1404 case FFS_CLUSTERWRITE:
1405 return (sysctl_int(oldp, oldlenp, newp, newlen,
1406 &doclusterwrite));
1407 case FFS_REALLOCBLKS:
1408 return (sysctl_int(oldp, oldlenp, newp, newlen,
1409 &doreallocblks));
1410 case FFS_ASYNCFREE:
1411 return (sysctl_int(oldp, oldlenp, newp, newlen, &doasyncfree));
1412 #ifdef FFS_SOFTUPDATES
1413 case FFS_MAX_SOFTDEPS:
1414 return (sysctl_int(oldp, oldlenp, newp, newlen, &max_softdeps));
1415 case FFS_SD_TICKDELAY:
1416 return (sysctl_int(oldp, oldlenp, newp, newlen, &tickdelay));
1417 case FFS_SD_WORKLIST_PUSH:
1418 return (sysctl_rdint(oldp, oldlenp, newp, stat_worklist_push));
1419 case FFS_SD_BLK_LIMIT_PUSH:
1420 return (sysctl_rdint(oldp, oldlenp, newp, stat_blk_limit_push));
1421 case FFS_SD_INO_LIMIT_PUSH:
1422 return (sysctl_rdint(oldp, oldlenp, newp, stat_ino_limit_push));
1423 case FFS_SD_BLK_LIMIT_HIT:
1424 return (sysctl_rdint(oldp, oldlenp, newp, stat_blk_limit_hit));
1425 case FFS_SD_INO_LIMIT_HIT:
1426 return (sysctl_rdint(oldp, oldlenp, newp, stat_ino_limit_hit));
1427 case FFS_SD_SYNC_LIMIT_HIT:
1428 return (sysctl_rdint(oldp, oldlenp, newp, stat_sync_limit_hit));
1429 case FFS_SD_INDIR_BLK_PTRS:
1430 return (sysctl_rdint(oldp, oldlenp, newp, stat_indir_blk_ptrs));
1431 case FFS_SD_INODE_BITMAP:
1432 return (sysctl_rdint(oldp, oldlenp, newp, stat_inode_bitmap));
1433 case FFS_SD_DIRECT_BLK_PTRS:
1434 return (sysctl_rdint(oldp, oldlenp, newp, stat_direct_blk_ptrs));
1435 case FFS_SD_DIR_ENTRY:
1436 return (sysctl_rdint(oldp, oldlenp, newp, stat_dir_entry));
1437 #endif
1438 #ifdef UFS_DIRHASH
1439 case FFS_DIRHASH_DIRSIZE:
1440 return (sysctl_int(oldp, oldlenp, newp, newlen,
1441 &ufs_mindirhashsize));
1442 case FFS_DIRHASH_MAXMEM:
1443 return (sysctl_int(oldp, oldlenp, newp, newlen,
1444 &ufs_dirhashmaxmem));
1445 case FFS_DIRHASH_MEM:
1446 return (sysctl_rdint(oldp, oldlenp, newp, ufs_dirhashmem));
1447 #endif
1448
1449 default:
1450 return (EOPNOTSUPP);
1451 }
1452 /* NOTREACHED */
1453 }
1454