UFS VFS: initialize f_mntonname for the root mp
[dragonfly.git] / sys / vfs / ufs / ffs_vfsops.c
1 /*
2  * Copyright (c) 1989, 1991, 1993, 1994
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  *      @(#)ffs_vfsops.c        8.31 (Berkeley) 5/20/95
34  * $FreeBSD: src/sys/ufs/ffs/ffs_vfsops.c,v 1.117.2.10 2002/06/23 22:34:52 iedowse Exp $
35  */
36
37 #include "opt_quota.h"
38
39 #include <sys/disk.h>
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/proc.h>
43 #include <sys/nlookup.h>
44 #include <sys/kernel.h>
45 #include <sys/vnode.h>
46 #include <sys/mount.h>
47 #include <sys/buf.h>
48 #include <sys/conf.h>
49 #include <sys/fcntl.h>
50 #include <sys/diskslice.h>
51 #include <sys/malloc.h>
52
53 #include "quota.h"
54 #include "ufsmount.h"
55 #include "inode.h"
56 #include "ufs_extern.h"
57
58 #include "fs.h"
59 #include "ffs_extern.h"
60
61 #include <vm/vm.h>
62 #include <vm/vm_page.h>
63 #include <vm/vm_zone.h>
64
65 #include <sys/buf2.h>
66
67 static MALLOC_DEFINE(M_FFSNODE, "FFS node", "FFS vnode private part");
68
69 static int      ffs_sbupdate (struct ufsmount *, int);
70 static int      ffs_reload (struct mount *, struct ucred *);
71 static int      ffs_oldfscompat (struct fs *);
72 static int      ffs_mount (struct mount *, char *, caddr_t, struct ucred *);
73 static int      ffs_init (struct vfsconf *);
74
75 static struct vfsops ufs_vfsops = {
76         .vfs_mount =            ffs_mount,
77         .vfs_unmount =          ffs_unmount,
78         .vfs_root =             ufs_root,
79         .vfs_quotactl =         ufs_quotactl,
80         .vfs_statfs =           ffs_statfs,
81         .vfs_sync =             ffs_sync,
82         .vfs_vget =             ffs_vget,
83         .vfs_fhtovp =           ffs_fhtovp,
84         .vfs_checkexp =         ufs_check_export,
85         .vfs_vptofh =           ffs_vptofh,
86         .vfs_init =             ffs_init,
87         .vfs_uninit =           ufs_uninit
88 };
89
90 VFS_SET(ufs_vfsops, ufs, 0);
91 MODULE_VERSION(ufs, 1);
92
93 extern struct vop_ops ffs_vnode_vops;
94 extern struct vop_ops ffs_spec_vops;
95 extern struct vop_ops ffs_fifo_vops;
96
97 /*
98  * ffs_mount
99  *
100  * Called when mounting local physical media
101  *
102  * PARAMETERS:
103  *              mountroot
104  *                      mp      mount point structure
105  *                      path    NULL (flag for root mount!!!)
106  *                      data    <unused>
107  *                      p       process (user credentials check [statfs])
108  *
109  *              mount
110  *                      mp      mount point structure
111  *                      path    path to mount point
112  *                      data    pointer to argument struct in user space
113  *                      p       process (user credentials check)
114  *
115  * RETURNS:     0       Success
116  *              !0      error number (errno.h)
117  *
118  * LOCK STATE:
119  *
120  *              ENTRY
121  *                      mount point is locked
122  *              EXIT
123  *                      mount point is locked
124  *
125  * NOTES:
126  *              A NULL path can be used for a flag since the mount
127  *              system call will fail with EFAULT in copyinstr in
128  *              nlookup() if it is a genuine NULL from the user.
129  */
130 static int
131 ffs_mount(struct mount *mp,             /* mount struct pointer */
132           char *path,                   /* path to mount point */
133           caddr_t data,                 /* arguments to FS specific mount */
134           struct ucred  *cred)          /* process requesting mount */
135 {
136         size_t          size;
137         int             error;
138         struct vnode    *devvp;
139
140         struct ufs_args args;
141         struct ufsmount *ump = 0;
142         struct fs *fs;
143         int flags, ronly = 0;
144         mode_t accessmode;
145         struct nlookupdata nd;
146         struct vnode *rootvp;
147
148         devvp = NULL;
149         error = 0;
150
151         /*
152          * Use NULL path to flag a root mount
153          */
154         if (path == NULL) {
155                 /*
156                  ***
157                  * Mounting root filesystem
158                  ***
159                  */
160         
161                 if ((error = bdevvp(rootdev, &rootvp))) {
162                         kprintf("ffs_mountroot: can't find rootvp\n");
163                         return (error);
164                 }
165
166                 if( ( error = ffs_mountfs(rootvp, mp, M_FFSNODE)) != 0) {
167                         /* fs specific cleanup (if any)*/
168                         goto error_1;
169                 }
170                 devvp = rootvp;
171
172                 goto dostatfs;          /* success*/
173
174         }
175
176         /*
177          ***
178          * Mounting non-root filesystem or updating a filesystem
179          ***
180          */
181
182         /* copy in user arguments*/
183         error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args));
184         if (error)
185                 goto error_1;           /* can't get arguments*/
186
187         /*
188          * If updating, check whether changing from read-only to
189          * read/write; if there is no device name, that's all we do.
190          */
191         if (mp->mnt_flag & MNT_UPDATE) {
192                 ump = VFSTOUFS(mp);
193                 fs = ump->um_fs;
194                 devvp = ump->um_devvp;
195                 error = 0;
196                 ronly = fs->fs_ronly;   /* MNT_RELOAD might change this */
197                 if (ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
198                         /*
199                          * Flush any dirty data.
200                          */
201                         VFS_SYNC(mp, MNT_WAIT);
202                         /*
203                          * Check for and optionally get rid of files open
204                          * for writing.
205                          */
206                         flags = WRITECLOSE;
207                         if (mp->mnt_flag & MNT_FORCE)
208                                 flags |= FORCECLOSE;
209                         if (mp->mnt_flag & MNT_SOFTDEP) {
210                                 error = softdep_flushfiles(mp, flags);
211                         } else {
212                                 error = ffs_flushfiles(mp, flags);
213                         }
214                         ronly = 1;
215                 }
216                 if (!error && (mp->mnt_flag & MNT_RELOAD)) {
217                         error = ffs_reload(mp, NULL);
218                 }
219                 if (error) {
220                         goto error_1;
221                 }
222                 if (ronly && (mp->mnt_kern_flag & MNTK_WANTRDWR)) {
223                         /*
224                          * If upgrade to read-write by non-root, then verify
225                          * that user has necessary permissions on the device.
226                          */
227                         if (cred->cr_uid != 0) {
228                                 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
229                                 if ((error = VOP_EACCESS(devvp, VREAD | VWRITE,
230                                     cred)) != 0) {
231                                         vn_unlock(devvp);
232                                         return (error);
233                                 }
234                                 vn_unlock(devvp);
235                         }
236
237                         fs->fs_flags &= ~FS_UNCLEAN;
238                         if (fs->fs_clean == 0) {
239                                 fs->fs_flags |= FS_UNCLEAN;
240                                 if (mp->mnt_flag & MNT_FORCE) {
241                                         kprintf(
242 "WARNING: %s was not properly dismounted\n",
243                                             fs->fs_fsmnt);
244                                 } else {
245                                         kprintf(
246 "WARNING: R/W mount of %s denied.  Filesystem is not clean - run fsck\n",
247                                             fs->fs_fsmnt);
248                                         error = EPERM;
249                                         goto error_1;
250                                 }
251                         }
252
253                         /* check to see if we need to start softdep */
254                         if (fs->fs_flags & FS_DOSOFTDEP) {
255                                 error = softdep_mount(devvp, mp, fs);
256                                 if (error)
257                                         goto error_1;
258                         }
259                         ronly = 0;
260                 }
261                 /*
262                  * Soft updates is incompatible with "async",
263                  * so if we are doing softupdates stop the user
264                  * from setting the async flag in an update.
265                  * Softdep_mount() clears it in an initial mount 
266                  * or ro->rw remount.
267                  */
268                 if (mp->mnt_flag & MNT_SOFTDEP) {
269                         mp->mnt_flag &= ~MNT_ASYNC;
270                 }
271                 /* if not updating name...*/
272                 if (args.fspec == 0) {
273                         /*
274                          * Process export requests.  Jumping to "success"
275                          * will return the vfs_export() error code.
276                          */
277                         error = vfs_export(mp, &ump->um_export, &args.export);
278                         goto success;
279                 }
280         }
281
282         /*
283          * Not an update, or updating the name: look up the name
284          * and verify that it refers to a sensible block device.
285          */
286         devvp = NULL;
287         error = nlookup_init(&nd, args.fspec, UIO_USERSPACE, NLC_FOLLOW);
288         if (error == 0)
289                 error = nlookup(&nd);
290         if (error == 0)
291                 error = cache_vref(&nd.nl_nch, nd.nl_cred, &devvp);
292         nlookup_done(&nd);
293         if (error)
294                 goto error_1;
295
296         if (!vn_isdisk(devvp, &error))
297                 goto error_2;
298
299         /*
300          * If mount by non-root, then verify that user has necessary
301          * permissions on the device.
302          */
303         if (cred->cr_uid != 0) {
304                 accessmode = VREAD;
305                 if ((mp->mnt_flag & MNT_RDONLY) == 0)
306                         accessmode |= VWRITE;
307                 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
308                 if ((error = VOP_EACCESS(devvp, accessmode, cred)) != 0) {
309                         vput(devvp);
310                         return (error);
311                 }
312                 vn_unlock(devvp);
313         }
314
315         if (mp->mnt_flag & MNT_UPDATE) {
316                 /*
317                  * UPDATE - make sure the resolved vnode represents the same
318                  * device.  Note that devvp->v_rdev may be NULL since we 
319                  * haven't opened it, so compare udev instead.
320                  *
321                  * Our current open/writecount state is associated with
322                  * um_devvp, so continue using um_devvp and throw away devvp.
323                  */
324                 if (devvp != ump->um_devvp) {
325                         if (devvp->v_umajor == ump->um_devvp->v_umajor &&
326                             devvp->v_uminor == ump->um_devvp->v_uminor) {
327                                 vrele(devvp);
328                                 devvp = ump->um_devvp;
329                         } else {
330                                 kprintf("cannot update mount, udev does"
331                                         " not match %08x:%08x vs %08x:%08x\n",
332                                         devvp->v_umajor, devvp->v_uminor,
333                                         ump->um_devvp->v_umajor,
334                                         ump->um_devvp->v_uminor);
335                                 error = EINVAL; /* needs translation */
336                         }
337                 } else {
338                         vrele(devvp);
339                 }
340                 /*
341                  * Update device name only on success
342                  */
343                 if (!error) {
344                         /* Save "mounted from" info for mount point (NULL pad)*/
345                         copyinstr(      args.fspec,
346                                         mp->mnt_stat.f_mntfromname,
347                                         MNAMELEN - 1,
348                                         &size);
349                         bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
350                 }
351         } else {
352                 /*
353                  ********************
354                  * NEW MOUNT
355                  ********************
356                  */
357
358                 /* Save "mounted from" info for mount point (NULL pad)*/
359                 copyinstr(      args.fspec,                     /* device name*/
360                                 mp->mnt_stat.f_mntfromname,     /* save area*/
361                                 MNAMELEN - 1,                   /* max size*/
362                                 &size);                         /* real size*/
363                 bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
364
365                 /* Save "last mounted on" info for mount point (NULL pad)*/
366                 bzero(mp->mnt_stat.f_mntonname,
367                       sizeof(mp->mnt_stat.f_mntonname));
368                 if (path) {
369                         copyinstr(path, mp->mnt_stat.f_mntonname,
370                                   sizeof(mp->mnt_stat.f_mntonname) - 1,
371                                   &size);
372                 } else {        /* Root mount */
373                         mp->mnt_stat.f_mntonname[0] = '/';
374                 }
375
376                 error = ffs_mountfs(devvp, mp, M_FFSNODE);
377         }
378         if (error) {
379                 goto error_2;
380         }
381
382 dostatfs:
383         /*
384          * Initialize FS stat information in mount struct; uses
385          * mp->mnt_stat.f_mntfromname.
386          *
387          * This code is common to root and non-root mounts
388          */
389         (void)VFS_STATFS(mp, &mp->mnt_stat, cred);
390
391         goto success;
392
393
394 error_2:        /* error with devvp held*/
395
396         /* release devvp before failing*/
397         vrele(devvp);
398
399 error_1:        /* no state to back out*/
400
401 success:
402         if (!error && path && (mp->mnt_flag & MNT_UPDATE)) {
403                 /* Update clean flag after changing read-onlyness. */
404                 fs = ump->um_fs;
405                 if (ronly != fs->fs_ronly) {
406                         fs->fs_ronly = ronly;
407                         fs->fs_clean = ronly &&
408                             (fs->fs_flags & FS_UNCLEAN) == 0 ? 1 : 0;
409
410                         /*
411                          * The device must be re-opened as appropriate or
412                          * the device close at unmount time will panic.
413                          */
414                         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
415                         if (ronly) {
416                                 VOP_OPEN(devvp, FREAD, FSCRED, NULL);
417                                 VOP_CLOSE(devvp, FREAD|FWRITE);
418                         } else {
419                                 VOP_OPEN(devvp, FREAD|FWRITE, FSCRED, NULL);
420                                 VOP_CLOSE(devvp, FREAD);
421                         }
422                         vn_unlock(devvp);
423                         ffs_sbupdate(ump, MNT_WAIT);
424                 }
425         }
426         return (error);
427 }
428
429 /*
430  * Reload all incore data for a filesystem (used after running fsck on
431  * the root filesystem and finding things to fix). The filesystem must
432  * be mounted read-only.
433  *
434  * Things to do to update the mount:
435  *      1) invalidate all cached meta-data.
436  *      2) re-read superblock from disk.
437  *      3) re-read summary information from disk.
438  *      4) invalidate all inactive vnodes.
439  *      5) invalidate all cached file data.
440  *      6) re-read inode data for all active vnodes.
441  */
442
443 static int ffs_reload_scan2(struct mount *mp, struct vnode *vp, void *data);
444
445 struct scaninfo {
446         int rescan;
447         struct fs *fs;
448         struct vnode *devvp;
449         int waitfor;
450         int allerror;
451 };
452
453 static int
454 ffs_reload(struct mount *mp, struct ucred *cred)
455 {
456         struct vnode *devvp;
457         void *space;
458         struct buf *bp;
459         struct fs *fs, *newfs;
460         struct partinfo dpart;
461         cdev_t dev;
462         int i, blks, size, error;
463         struct scaninfo scaninfo;
464         int32_t *lp;
465
466         if ((mp->mnt_flag & MNT_RDONLY) == 0)
467                 return (EINVAL);
468         /*
469          * Step 1: invalidate all cached meta-data.
470          */
471         devvp = VFSTOUFS(mp)->um_devvp;
472         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
473         error = vinvalbuf(devvp, 0, 0, 0);
474         vn_unlock(devvp);
475         if (error)
476                 panic("ffs_reload: dirty1");
477
478         dev = devvp->v_rdev;
479
480         /*
481          * The backing device must be VMIO-capable because we use getblk().
482          * NOTE: the MFS driver now returns a VMIO-enabled descriptor.
483          */
484         if (devvp->v_object == NULL)
485                 panic("ffs_reload: devvp has no VM object!");
486
487         /*
488          * Step 2: re-read superblock from disk.
489          */
490         if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD,
491             cred, NULL) != 0) {
492                 size = DEV_BSIZE;
493         } else {
494                 size = dpart.media_blksize;
495         }
496         if ((error = bread(devvp, SBOFF, SBSIZE, &bp)) != 0) {
497                 brelse(bp);
498                 return (error);
499         }
500         newfs = (struct fs *)bp->b_data;
501         if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE ||
502                 newfs->fs_bsize < sizeof(struct fs)) {
503                         brelse(bp);
504                         return (EIO);           /* XXX needs translation */
505         }
506         fs = VFSTOUFS(mp)->um_fs;
507         /*
508          * Copy pointer fields back into superblock before copying in   XXX
509          * new superblock. These should really be in the ufsmount.      XXX
510          * Note that important parameters (eg fs_ncg) are unchanged.
511          */
512         newfs->fs_csp = fs->fs_csp;
513         newfs->fs_maxcluster = fs->fs_maxcluster;
514         newfs->fs_contigdirs = fs->fs_contigdirs;
515         /* The filesystem is still read-only. */
516         newfs->fs_ronly = 1;
517         bcopy(newfs, fs, (uint)fs->fs_sbsize);
518         if (fs->fs_sbsize < SBSIZE)
519                 bp->b_flags |= B_INVAL;
520         brelse(bp);
521         mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
522         ffs_oldfscompat(fs);
523         /* An old fsck may have zeroed these fields, so recheck them. */
524         if (fs->fs_avgfilesize <= 0)            /* XXX */
525                 fs->fs_avgfilesize = AVFILESIZ; /* XXX */
526         if (fs->fs_avgfpdir <= 0)               /* XXX */
527                 fs->fs_avgfpdir = AFPDIR;       /* XXX */
528
529         /*
530          * Step 3: re-read summary information from disk.
531          */
532         blks = howmany(fs->fs_cssize, fs->fs_fsize);
533         space = fs->fs_csp;
534         for (i = 0; i < blks; i += fs->fs_frag) {
535                 size = fs->fs_bsize;
536                 if (i + fs->fs_frag > blks)
537                         size = (blks - i) * fs->fs_fsize;
538                 error = bread(devvp, fsbtodoff(fs, fs->fs_csaddr + i), size, &bp);
539                 if (error) {
540                         brelse(bp);
541                         return (error);
542                 }
543                 bcopy(bp->b_data, space, (uint)size);
544                 space = (char *)space + size;
545                 brelse(bp);
546         }
547         /*
548          * We no longer know anything about clusters per cylinder group.
549          */
550         if (fs->fs_contigsumsize > 0) {
551                 lp = fs->fs_maxcluster;
552                 for (i = 0; i < fs->fs_ncg; i++)
553                         *lp++ = fs->fs_contigsumsize;
554         }
555
556         scaninfo.rescan = 0;
557         scaninfo.fs = fs;
558         scaninfo.devvp = devvp;
559         while (error == 0 && scaninfo.rescan) {
560                 scaninfo.rescan = 0;
561                 error = vmntvnodescan(mp, VMSC_GETVX, 
562                                         NULL, ffs_reload_scan2, &scaninfo);
563         }
564         return(error);
565 }
566
567 static int
568 ffs_reload_scan2(struct mount *mp, struct vnode *vp, void *data)
569 {
570         struct scaninfo *info = data;
571         struct inode *ip;
572         struct buf *bp;
573         int error;
574
575         /*
576          * Try to recycle
577          */
578         if (vrecycle(vp))
579                 return(0);
580
581         if (vinvalbuf(vp, 0, 0, 0))
582                 panic("ffs_reload: dirty2");
583         /*
584          * Step 6: re-read inode data for all active vnodes.
585          */
586         ip = VTOI(vp);
587         error = bread(info->devvp,
588                     fsbtodoff(info->fs, ino_to_fsba(info->fs, ip->i_number)),
589                     (int)info->fs->fs_bsize, &bp);
590         if (error) {
591                 brelse(bp);
592                 return (error);
593         }
594         ip->i_din = *((struct ufs1_dinode *)bp->b_data +
595             ino_to_fsbo(info->fs, ip->i_number));
596         ip->i_effnlink = ip->i_nlink;
597         brelse(bp);
598         return(0);
599 }
600
601 /*
602  * Common code for mount and mountroot
603  */
604 int
605 ffs_mountfs(struct vnode *devvp, struct mount *mp, struct malloc_type *mtype)
606 {
607         struct ufsmount *ump;
608         struct buf *bp;
609         struct fs *fs;
610         cdev_t dev;
611         struct partinfo dpart;
612         void *space;
613         int error, i, blks, size, ronly;
614         int32_t *lp;
615         uint64_t maxfilesize;                                   /* XXX */
616
617         /*
618          * Disallow multiple mounts of the same device.
619          * Disallow mounting of a device that is currently in use
620          * Flush out any old buffers remaining from a previous use.
621          */
622         error = vfs_mountedon(devvp);
623         if (error)
624                 return (error);
625         if (vcount(devvp) > 0)
626                 return (EBUSY);
627         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
628         error = vinvalbuf(devvp, V_SAVE, 0, 0);
629         vn_unlock(devvp);
630         if (error)
631                 return (error);
632
633         ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
634         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
635         error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, NULL);
636         vn_unlock(devvp);
637         if (error)
638                 return (error);
639         dev = devvp->v_rdev;
640         if (dev->si_iosize_max != 0)
641                 mp->mnt_iosize_max = dev->si_iosize_max;
642         if (mp->mnt_iosize_max > MAXPHYS)
643                 mp->mnt_iosize_max = MAXPHYS;
644
645         /*
646          * Filesystem supports native FSMIDs
647          */
648         mp->mnt_kern_flag |= MNTK_FSMID;
649
650         /*
651          * The backing device must be VMIO-capable because we use getblk().
652          * NOTE: the MFS driver now returns a VMIO-enabled descriptor.
653          * The VOP_OPEN() call above should have associated a VM object
654          * with devvp.
655          */
656         if (devvp->v_object == NULL)
657                 panic("ffs_reload: devvp has no VM object!");
658
659         if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD,
660                       proc0.p_ucred, NULL) != 0) {
661                 size = DEV_BSIZE;
662         } else {
663                 size = dpart.media_blksize;
664         }
665
666         bp = NULL;
667         ump = NULL;
668         if ((error = bread(devvp, SBOFF, SBSIZE, &bp)) != 0)
669                 goto out;
670         fs = (struct fs *)bp->b_data;
671         if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
672             fs->fs_bsize < sizeof(struct fs)) {
673                 error = EINVAL;         /* XXX needs translation */
674                 goto out;
675         }
676         fs->fs_fmod = 0;
677         fs->fs_flags &= ~FS_UNCLEAN;
678         if (fs->fs_clean == 0) {
679                 fs->fs_flags |= FS_UNCLEAN;
680                 if (ronly || (mp->mnt_flag & MNT_FORCE)) {
681                         kprintf(
682 "WARNING: %s was not properly dismounted\n",
683                             fs->fs_fsmnt);
684                 } else {
685                         kprintf(
686 "WARNING: R/W mount of %s denied.  Filesystem is not clean - run fsck\n",
687                             fs->fs_fsmnt);
688                         error = EPERM;
689                         goto out;
690                 }
691         }
692         /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */
693         if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) {
694                 error = EROFS;          /* needs translation */
695                 goto out;
696         }
697         ump = kmalloc(sizeof *ump, M_UFSMNT, M_WAITOK | M_ZERO);
698         ump->um_malloctype = mtype;
699         ump->um_i_effnlink_valid = 1;
700         ump->um_fs = kmalloc((u_long)fs->fs_sbsize, M_UFSMNT,
701             M_WAITOK);
702         bcopy(bp->b_data, ump->um_fs, (uint)fs->fs_sbsize);
703         if (fs->fs_sbsize < SBSIZE)
704                 bp->b_flags |= B_INVAL;
705         brelse(bp);
706         bp = NULL;
707         fs = ump->um_fs;
708         fs->fs_ronly = ronly;
709         size = fs->fs_cssize;
710         blks = howmany(size, fs->fs_fsize);
711         if (fs->fs_contigsumsize > 0)
712                 size += fs->fs_ncg * sizeof(int32_t);
713         size += fs->fs_ncg * sizeof(uint8_t);
714         space = kmalloc((u_long)size, M_UFSMNT, M_WAITOK);
715         fs->fs_csp = space;
716         for (i = 0; i < blks; i += fs->fs_frag) {
717                 size = fs->fs_bsize;
718                 if (i + fs->fs_frag > blks)
719                         size = (blks - i) * fs->fs_fsize;
720                 if ((error = bread(devvp, fsbtodoff(fs, fs->fs_csaddr + i),
721                                    size, &bp)) != 0) {
722                         kfree(fs->fs_csp, M_UFSMNT);
723                         goto out;
724                 }
725                 bcopy(bp->b_data, space, (uint)size);
726                 space = (char *)space + size;
727                 brelse(bp);
728                 bp = NULL;
729         }
730         if (fs->fs_contigsumsize > 0) {
731                 fs->fs_maxcluster = lp = space;
732                 for (i = 0; i < fs->fs_ncg; i++)
733                         *lp++ = fs->fs_contigsumsize;
734                 space = lp;
735         }
736         size = fs->fs_ncg * sizeof(uint8_t);
737         fs->fs_contigdirs = (uint8_t *)space;
738         bzero(fs->fs_contigdirs, size);
739         /* Compatibility for old filesystems       XXX */
740         if (fs->fs_avgfilesize <= 0)            /* XXX */
741                 fs->fs_avgfilesize = AVFILESIZ; /* XXX */
742         if (fs->fs_avgfpdir <= 0)               /* XXX */
743                 fs->fs_avgfpdir = AFPDIR;       /* XXX */
744         mp->mnt_data = (qaddr_t)ump;
745         mp->mnt_stat.f_fsid.val[0] = fs->fs_id[0];
746         mp->mnt_stat.f_fsid.val[1] = fs->fs_id[1];
747         if (fs->fs_id[0] == 0 || fs->fs_id[1] == 0 || 
748             vfs_getvfs(&mp->mnt_stat.f_fsid)) 
749                 vfs_getnewfsid(mp);
750         mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
751         mp->mnt_flag |= MNT_LOCAL;
752         ump->um_mountp = mp;
753         ump->um_dev = dev;
754         ump->um_devvp = devvp;
755         ump->um_nindir = fs->fs_nindir;
756         ump->um_bptrtodb = fs->fs_fsbtodb;
757         ump->um_seqinc = fs->fs_frag;
758         for (i = 0; i < MAXQUOTAS; i++)
759                 ump->um_quotas[i] = NULLVP;
760         dev->si_mountpoint = mp;
761         ffs_oldfscompat(fs);
762
763         /* restore "last mounted on" here */
764         bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt));
765         ksnprintf(fs->fs_fsmnt, sizeof(fs->fs_fsmnt),
766                  "%s", mp->mnt_stat.f_mntonname);
767
768         if( mp->mnt_flag & MNT_ROOTFS) {
769                 /*
770                  * Root mount; update timestamp in mount structure.
771                  * this will be used by the common root mount code
772                  * to update the system clock.
773                  */
774                 mp->mnt_time = fs->fs_time;
775         }
776
777         ump->um_savedmaxfilesize = fs->fs_maxfilesize;          /* XXX */
778         maxfilesize = (uint64_t)0x40000000 * fs->fs_bsize - 1;  /* XXX */
779         /* Enforce limit caused by vm object backing (32 bits vm_pindex_t). */
780         if (maxfilesize > (uint64_t)0x80000000u * PAGE_SIZE - 1)
781                 maxfilesize = (uint64_t)0x80000000u * PAGE_SIZE - 1;
782         if (fs->fs_maxfilesize > maxfilesize)                   /* XXX */
783                 fs->fs_maxfilesize = maxfilesize;               /* XXX */
784         if (ronly == 0) {
785                 if ((fs->fs_flags & FS_DOSOFTDEP) &&
786                     (error = softdep_mount(devvp, mp, fs)) != 0) {
787                         kfree(fs->fs_csp, M_UFSMNT);
788                         goto out;
789                 }
790                 fs->fs_fmod = 1;
791                 fs->fs_clean = 0;
792                 (void) ffs_sbupdate(ump, MNT_WAIT);
793         }
794         vfs_add_vnodeops(mp, &ffs_vnode_vops, &mp->mnt_vn_norm_ops);
795         vfs_add_vnodeops(mp, &ffs_spec_vops, &mp->mnt_vn_spec_ops);
796         vfs_add_vnodeops(mp, &ffs_fifo_vops, &mp->mnt_vn_fifo_ops);
797
798         return (0);
799 out:
800         dev->si_mountpoint = NULL;
801         if (bp)
802                 brelse(bp);
803         VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE);
804         if (ump) {
805                 kfree(ump->um_fs, M_UFSMNT);
806                 kfree(ump, M_UFSMNT);
807                 mp->mnt_data = (qaddr_t)0;
808         }
809         return (error);
810 }
811
812 /*
813  * Sanity checks for old filesystems.
814  *
815  * XXX - goes away some day.
816  */
817 static int
818 ffs_oldfscompat(struct fs *fs)
819 {
820         fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect);       /* XXX */
821         fs->fs_interleave = max(fs->fs_interleave, 1);          /* XXX */
822         if (fs->fs_postblformat == FS_42POSTBLFMT)              /* XXX */
823                 fs->fs_nrpos = 8;                               /* XXX */
824         if (fs->fs_inodefmt < FS_44INODEFMT) {                  /* XXX */
825 #if 0
826                 int i;                                          /* XXX */
827                 uint64_t sizepb = fs->fs_bsize;         /* XXX */
828                                                                 /* XXX */
829                 fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
830                 for (i = 0; i < NIADDR; i++) {                  /* XXX */
831                         sizepb *= NINDIR(fs);                   /* XXX */
832                         fs->fs_maxfilesize += sizepb;           /* XXX */
833                 }                                               /* XXX */
834 #endif
835                 fs->fs_maxfilesize = (u_quad_t) 1LL << 39;
836                 fs->fs_qbmask = ~fs->fs_bmask;                  /* XXX */
837                 fs->fs_qfmask = ~fs->fs_fmask;                  /* XXX */
838         }                                                       /* XXX */
839         return (0);
840 }
841
842 /*
843  * unmount system call
844  */
845 int
846 ffs_unmount(struct mount *mp, int mntflags)
847 {
848         struct ufsmount *ump;
849         struct fs *fs;
850         int error, flags;
851
852         flags = 0;
853         if (mntflags & MNT_FORCE) {
854                 flags |= FORCECLOSE;
855         }
856         if (mp->mnt_flag & MNT_SOFTDEP) {
857                 if ((error = softdep_flushfiles(mp, flags)) != 0)
858                         return (error);
859         } else {
860                 if ((error = ffs_flushfiles(mp, flags)) != 0)
861                         return (error);
862         }
863         ump = VFSTOUFS(mp);
864         fs = ump->um_fs;
865         if (fs->fs_ronly == 0) {
866                 fs->fs_clean = fs->fs_flags & FS_UNCLEAN ? 0 : 1;
867                 error = ffs_sbupdate(ump, MNT_WAIT);
868                 if (error) {
869                         fs->fs_clean = 0;
870                         return (error);
871                 }
872         }
873         ump->um_devvp->v_rdev->si_mountpoint = NULL;
874
875         vinvalbuf(ump->um_devvp, V_SAVE, 0, 0);
876         error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE);
877
878         vrele(ump->um_devvp);
879
880         kfree(fs->fs_csp, M_UFSMNT);
881         kfree(fs, M_UFSMNT);
882         kfree(ump, M_UFSMNT);
883         mp->mnt_data = (qaddr_t)0;
884         mp->mnt_flag &= ~MNT_LOCAL;
885         return (error);
886 }
887
888 /*
889  * Flush out all the files in a filesystem.
890  */
891 int
892 ffs_flushfiles(struct mount *mp, int flags)
893 {
894         struct ufsmount *ump;
895         int error;
896
897         ump = VFSTOUFS(mp);
898 #ifdef QUOTA
899         if (mp->mnt_flag & MNT_QUOTA) {
900                 int i;
901                 error = vflush(mp, 0, SKIPSYSTEM|flags);
902                 if (error)
903                         return (error);
904                 /* Find out how many quota files  we have open. */
905                 for (i = 0; i < MAXQUOTAS; i++) {
906                         if (ump->um_quotas[i] == NULLVP)
907                                 continue;
908                         ufs_quotaoff(mp, i);
909                 }
910                 /*
911                  * Here we fall through to vflush again to ensure
912                  * that we have gotten rid of all the system vnodes.
913                  */
914         }
915 #endif
916         /*
917          * Flush all the files.
918          */
919         if ((error = vflush(mp, 0, flags)) != 0)
920                 return (error);
921         /*
922          * Flush filesystem metadata.
923          */
924         vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
925         error = VOP_FSYNC(ump->um_devvp, MNT_WAIT, 0);
926         vn_unlock(ump->um_devvp);
927         return (error);
928 }
929
930 /*
931  * Get filesystem statistics.
932  */
933 int
934 ffs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
935 {
936         struct ufsmount *ump;
937         struct fs *fs;
938
939         ump = VFSTOUFS(mp);
940         fs = ump->um_fs;
941         if (fs->fs_magic != FS_MAGIC)
942                 panic("ffs_statfs");
943         sbp->f_bsize = fs->fs_fsize;
944         sbp->f_iosize = fs->fs_bsize;
945         sbp->f_blocks = fs->fs_dsize;
946         sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
947                 fs->fs_cstotal.cs_nffree;
948         sbp->f_bavail = freespace(fs, fs->fs_minfree);
949         sbp->f_files =  fs->fs_ncg * fs->fs_ipg - ROOTINO;
950         sbp->f_ffree = fs->fs_cstotal.cs_nifree;
951         if (sbp != &mp->mnt_stat) {
952                 sbp->f_type = mp->mnt_vfc->vfc_typenum;
953                 bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
954                         (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
955         }
956         return (0);
957 }
958
959 /*
960  * Go through the disk queues to initiate sandbagged IO;
961  * go through the inodes to write those that have been modified;
962  * initiate the writing of the super block if it has been modified.
963  *
964  * Note: we are always called with the filesystem marked `MPBUSY'.
965  */
966
967
968 static int ffs_sync_scan1(struct mount *mp, struct vnode *vp, void *data);
969 static int ffs_sync_scan2(struct mount *mp, struct vnode *vp, void *data);
970
971 int
972 ffs_sync(struct mount *mp, int waitfor)
973 {
974         struct ufsmount *ump = VFSTOUFS(mp);
975         struct fs *fs;
976         int error;
977         struct scaninfo scaninfo;
978
979         fs = ump->um_fs;
980         if (fs->fs_fmod != 0 && fs->fs_ronly != 0) {            /* XXX */
981                 kprintf("fs = %s\n", fs->fs_fsmnt);
982                 panic("ffs_sync: rofs mod");
983         }
984
985         /*
986          * Write back each (modified) inode.
987          */
988         scaninfo.allerror = 0;
989         scaninfo.rescan = 1;
990         scaninfo.waitfor = waitfor;
991         while (scaninfo.rescan) {
992                 scaninfo.rescan = 0;
993                 vmntvnodescan(mp, VMSC_GETVP|VMSC_NOWAIT,
994                                 ffs_sync_scan1, ffs_sync_scan2, &scaninfo);
995         }
996
997         /*
998          * Force stale filesystem control information to be flushed.
999          */
1000         if ((waitfor & MNT_LAZY) == 0) {
1001                 if (ump->um_mountp->mnt_flag & MNT_SOFTDEP)
1002                         waitfor = MNT_NOWAIT;
1003                 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
1004                 if ((error = VOP_FSYNC(ump->um_devvp, waitfor, 0)) != 0)
1005                         scaninfo.allerror = error;
1006                 vn_unlock(ump->um_devvp);
1007         }
1008 #ifdef QUOTA
1009         ufs_qsync(mp);
1010 #endif
1011         /*
1012          * Write back modified superblock.
1013          */
1014         if (fs->fs_fmod != 0 && (error = ffs_sbupdate(ump, waitfor)) != 0)
1015                 scaninfo.allerror = error;
1016         return (scaninfo.allerror);
1017 }
1018
1019 static int
1020 ffs_sync_scan1(struct mount *mp, struct vnode *vp, void *data)
1021 {
1022         struct inode *ip;
1023
1024         /*
1025          * Depend on the mount list's vnode lock to keep things stable 
1026          * enough for a quick test.  Since there might be hundreds of 
1027          * thousands of vnodes, we cannot afford even a subroutine
1028          * call unless there's a good chance that we have work to do.
1029          */
1030         ip = VTOI(vp);
1031         /* Restart out whole search if this guy is locked
1032          * or is being reclaimed.
1033          */
1034         if (vp->v_type == VNON || ((ip->i_flag &
1035              (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
1036              RB_EMPTY(&vp->v_rbdirty_tree))) {
1037                 return(-1);
1038         }
1039         return(0);
1040 }
1041
1042 static int 
1043 ffs_sync_scan2(struct mount *mp, struct vnode *vp, void *data)
1044 {
1045         struct scaninfo *info = data;
1046         struct inode *ip;
1047         int error;
1048
1049         /*
1050          * We have to recheck after having obtained the vnode interlock.
1051          */
1052         ip = VTOI(vp);
1053         if (vp->v_type == VNON || vp->v_type == VBAD ||
1054              ((ip->i_flag &
1055               (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
1056              RB_EMPTY(&vp->v_rbdirty_tree))) {
1057                 return(0);
1058         }
1059         if (vp->v_type != VCHR) {
1060                 if ((error = VOP_FSYNC(vp, info->waitfor, 0)) != 0)
1061                         info->allerror = error;
1062         } else {
1063                 /*
1064                  * We must reference the vp to prevent it from
1065                  * getting ripped out from under ffs_update, since
1066                  * we are not holding a vnode lock.
1067                  */
1068                 /* ffs_update(vp, waitfor == MNT_WAIT); */
1069                 ffs_update(vp, 0);
1070         }
1071         return(0);
1072 }
1073
1074 /*
1075  * Look up a FFS dinode number to find its incore vnode, otherwise read it
1076  * in from disk.  If it is in core, wait for the lock bit to clear, then
1077  * return the inode locked.  Detection and handling of mount points must be
1078  * done by the calling routine.
1079  */
1080
1081 int
1082 ffs_vget(struct mount *mp, struct vnode *dvp, ino_t ino, struct vnode **vpp)
1083 {
1084         struct fs *fs;
1085         struct inode *ip;
1086         struct ufsmount *ump;
1087         struct buf *bp;
1088         struct vnode *vp;
1089         cdev_t dev;
1090         int error;
1091
1092         ump = VFSTOUFS(mp);
1093         dev = ump->um_dev;
1094 restart:
1095         if ((*vpp = ufs_ihashget(dev, ino)) != NULL) {
1096                 return (0);
1097         }
1098
1099         /*
1100          * If this MALLOC() is performed after the getnewvnode()
1101          * it might block, leaving a vnode with a NULL v_data to be
1102          * found by ffs_sync() if a sync happens to fire right then,
1103          * which will cause a panic because ffs_sync() blindly
1104          * dereferences vp->v_data (as well it should).
1105          *
1106          * XXX this may no longer be true since getnewvnode returns a
1107          * VX locked vnode now.
1108          */
1109         ip = kmalloc(sizeof(struct inode), ump->um_malloctype, M_WAITOK);
1110
1111         /* Allocate a new vnode/inode. */
1112         error = getnewvnode(VT_UFS, mp, &vp, VLKTIMEOUT, LK_CANRECURSE);
1113         if (error) {
1114                 *vpp = NULL;
1115                 kfree(ip, ump->um_malloctype);
1116                 return (error);
1117         }
1118         bzero((caddr_t)ip, sizeof(struct inode));
1119         ip->i_vnode = vp;
1120         ip->i_fs = fs = ump->um_fs;
1121         ip->i_dev = dev;
1122         ip->i_number = ino;
1123 #ifdef QUOTA
1124         {
1125                 int i;
1126                 for (i = 0; i < MAXQUOTAS; i++)
1127                         ip->i_dquot[i] = NODQUOT;
1128         }
1129 #endif
1130
1131         /*
1132          * Insert it into the inode hash table and check for a collision.
1133          * If a collision occurs, throw away the vnode and try again.
1134          */
1135         if (ufs_ihashins(ip) != 0) {
1136                 kprintf("debug: ufs ihashins collision, retrying inode %ld\n",
1137                     (long)ip->i_number);
1138                 vp->v_type = VBAD;
1139                 vx_put(vp);
1140                 kfree(ip, ump->um_malloctype);
1141                 goto restart;
1142         }
1143         vp->v_data = ip;
1144
1145         /* Read in the disk contents for the inode, copy into the inode. */
1146         error = bread(ump->um_devvp, fsbtodoff(fs, ino_to_fsba(fs, ino)),
1147             (int)fs->fs_bsize, &bp);
1148         if (error) {
1149                 /*
1150                  * The inode does not contain anything useful, so it would
1151                  * be misleading to leave it on its hash chain. With mode
1152                  * still zero, it will be unlinked and returned to the free
1153                  * list by vput().
1154                  */
1155                 vp->v_type = VBAD;
1156                 brelse(bp);
1157                 vx_put(vp);
1158                 *vpp = NULL;
1159                 return (error);
1160         }
1161         ip->i_din = *((struct ufs1_dinode *)bp->b_data + ino_to_fsbo(fs, ino));
1162         if (DOINGSOFTDEP(vp))
1163                 softdep_load_inodeblock(ip);
1164         else
1165                 ip->i_effnlink = ip->i_nlink;
1166         bqrelse(bp);
1167
1168         /*
1169          * Initialize the vnode from the inode, check for aliases.
1170          * Note that the underlying vnode may have changed.
1171          */
1172         error = ufs_vinit(mp, &vp);
1173         if (error) {
1174                 vp->v_type = VBAD;
1175                 vx_put(vp);
1176                 *vpp = NULL;
1177                 return (error);
1178         }
1179         /*
1180          * Finish inode initialization now that aliasing has been resolved.
1181          */
1182         ip->i_devvp = ump->um_devvp;
1183         vref(ip->i_devvp);
1184         /*
1185          * Set up a generation number for this inode if it does not
1186          * already have one. This should only happen on old filesystems.
1187          */
1188         if (ip->i_gen == 0) {
1189                 ip->i_gen = krandom() / 2 + 1;
1190                 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
1191                         ip->i_flag |= IN_MODIFIED;
1192         }
1193         /*
1194          * Ensure that uid and gid are correct. This is a temporary
1195          * fix until fsck has been changed to do the update.
1196          */
1197         if (fs->fs_inodefmt < FS_44INODEFMT) {          /* XXX */
1198                 ip->i_uid = ip->i_din.di_ouid;          /* XXX */
1199                 ip->i_gid = ip->i_din.di_ogid;          /* XXX */
1200         }                                               /* XXX */
1201
1202         /* 
1203          * return a VX locked and refd vnode (VX == same as normal vget()
1204          * vnode so we are ok)
1205          */
1206         *vpp = vp;
1207         return (0);
1208 }
1209
1210 /*
1211  * File handle to vnode
1212  *
1213  * Have to be really careful about stale file handles:
1214  * - check that the inode number is valid
1215  * - call ffs_vget() to get the locked inode
1216  * - check for an unallocated inode (i_mode == 0)
1217  * - check that the given client host has export rights and return
1218  *   those rights via. exflagsp and credanonp
1219  */
1220 int
1221 ffs_fhtovp(struct mount *mp, struct vnode *rootvp,
1222            struct fid *fhp, struct vnode **vpp)
1223 {
1224         struct ufid *ufhp;
1225         struct fs *fs;
1226
1227         ufhp = (struct ufid *)fhp;
1228         fs = VFSTOUFS(mp)->um_fs;
1229         if (ufhp->ufid_ino < ROOTINO ||
1230             ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg)
1231                 return (ESTALE);
1232         return (ufs_fhtovp(mp, rootvp, ufhp, vpp));
1233 }
1234
1235 /*
1236  * Vnode pointer to File handle
1237  */
1238 /* ARGSUSED */
1239 int
1240 ffs_vptofh(struct vnode *vp, struct fid *fhp)
1241 {
1242         struct inode *ip;
1243         struct ufid *ufhp;
1244
1245         ip = VTOI(vp);
1246         ufhp = (struct ufid *)fhp;
1247         ufhp->ufid_len = sizeof(struct ufid);
1248         ufhp->ufid_ino = ip->i_number;
1249         ufhp->ufid_gen = ip->i_gen;
1250         return (0);
1251 }
1252
1253 /*
1254  * Initialize the filesystem; just use ufs_init.
1255  */
1256 static int
1257 ffs_init(struct vfsconf *vfsp)
1258 {
1259         softdep_initialize();
1260         kmalloc_raise_limit(M_FFSNODE, 0);
1261         return (ufs_init(vfsp));
1262 }
1263
1264 /*
1265  * Write a superblock and associated information back to disk.
1266  */
1267 static int
1268 ffs_sbupdate(struct ufsmount *mp, int waitfor)
1269 {
1270         struct fs *dfs, *fs = mp->um_fs;
1271         struct buf *bp;
1272         int blks;
1273         void *space;
1274         int i, size, error, allerror = 0;
1275
1276         /*
1277          * First write back the summary information.
1278          *
1279          * NOTE: the getblk is relative to the device vnode so bio1
1280          * contains the device block number.
1281          */
1282         blks = howmany(fs->fs_cssize, fs->fs_fsize);
1283         space = fs->fs_csp;
1284         for (i = 0; i < blks; i += fs->fs_frag) {
1285                 size = fs->fs_bsize;
1286                 if (i + fs->fs_frag > blks)
1287                         size = (blks - i) * fs->fs_fsize;
1288                 bp = getblk(mp->um_devvp, fsbtodoff(fs, fs->fs_csaddr + i),
1289                             size, 0, 0);
1290                 bcopy(space, bp->b_data, (uint)size);
1291                 space = (char *)space + size;
1292                 if (waitfor != MNT_WAIT)
1293                         bawrite(bp);
1294                 else if ((error = bwrite(bp)) != 0)
1295                         allerror = error;
1296         }
1297         /*
1298          * Now write back the superblock itself. If any errors occurred
1299          * up to this point, then fail so that the superblock avoids
1300          * being written out as clean.
1301          */
1302         if (allerror)
1303                 return (allerror);
1304         bp = getblk(mp->um_devvp, SBOFF, (int)fs->fs_sbsize, 0, 0);
1305         fs->fs_fmod = 0;
1306         fs->fs_time = time_second;
1307         bcopy((caddr_t)fs, bp->b_data, (uint)fs->fs_sbsize);
1308         /* Restore compatibility to old filesystems.               XXX */
1309         dfs = (struct fs *)bp->b_data;                          /* XXX */
1310         if (fs->fs_postblformat == FS_42POSTBLFMT)              /* XXX */
1311                 dfs->fs_nrpos = -1;                             /* XXX */
1312         if (fs->fs_inodefmt < FS_44INODEFMT) {                  /* XXX */
1313                 int32_t *lp, tmp;                               /* XXX */
1314                                                                 /* XXX */
1315                 lp = (int32_t *)&dfs->fs_qbmask;                /* XXX */
1316                 tmp = lp[4];                                    /* XXX */
1317                 for (i = 4; i > 0; i--)                         /* XXX */
1318                         lp[i] = lp[i-1];                        /* XXX */
1319                 lp[0] = tmp;                                    /* XXX */
1320         }                                                       /* XXX */
1321         dfs->fs_maxfilesize = mp->um_savedmaxfilesize;          /* XXX */
1322         if (waitfor != MNT_WAIT)
1323                 bawrite(bp);
1324         else if ((error = bwrite(bp)) != 0)
1325                 allerror = error;
1326         return (allerror);
1327 }