kernel/ffs: Compare v_rdev directly when updating mounts.
[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 = NULL;
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. Since devfs, devvp->v_rdev can be used directly as
319                  * it is always associated as long as the vnode exists.
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_rdev == ump->um_devvp->v_rdev) {
326                                 vrele(devvp);
327                                 devvp = ump->um_devvp;
328                         } else {
329                                 kprintf("cannot update mount, v_rdev does"
330                                         " not match (%p vs %p)\n",
331                                         devvp->v_rdev, ump->um_devvp->v_rdev);
332                                 error = EINVAL; /* needs translation */
333                         }
334                 } else {
335                         vrele(devvp);
336                 }
337                 /*
338                  * Update device name only on success
339                  */
340                 if (!error) {
341                         /* Save "mounted from" info for mount point (NULL pad)*/
342                         copyinstr(      args.fspec,
343                                         mp->mnt_stat.f_mntfromname,
344                                         MNAMELEN - 1,
345                                         &size);
346                         bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
347                 }
348         } else {
349                 /*
350                  ********************
351                  * NEW MOUNT
352                  ********************
353                  */
354
355                 /* Save "mounted from" info for mount point (NULL pad)*/
356                 copyinstr(      args.fspec,                     /* device name*/
357                                 mp->mnt_stat.f_mntfromname,     /* save area*/
358                                 MNAMELEN - 1,                   /* max size*/
359                                 &size);                         /* real size*/
360                 bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
361
362                 /* Save "last mounted on" info for mount point (NULL pad)*/
363                 bzero(mp->mnt_stat.f_mntonname,
364                       sizeof(mp->mnt_stat.f_mntonname));
365                 if (path) {
366                         copyinstr(path, mp->mnt_stat.f_mntonname,
367                                   sizeof(mp->mnt_stat.f_mntonname) - 1,
368                                   &size);
369                 } else {        /* Root mount */
370                         mp->mnt_stat.f_mntonname[0] = '/';
371                 }
372
373                 error = ffs_mountfs(devvp, mp, M_FFSNODE);
374         }
375         if (error) {
376                 goto error_2;
377         }
378
379 dostatfs:
380         /*
381          * Initialize FS stat information in mount struct; uses
382          * mp->mnt_stat.f_mntfromname.
383          *
384          * This code is common to root and non-root mounts
385          */
386         (void)VFS_STATFS(mp, &mp->mnt_stat, cred);
387
388         goto success;
389
390
391 error_2:        /* error with devvp held*/
392
393         /* release devvp before failing*/
394         vrele(devvp);
395
396 error_1:        /* no state to back out*/
397
398 success:
399         if (!error && path && (mp->mnt_flag & MNT_UPDATE)) {
400                 /* Update clean flag after changing read-onlyness. */
401                 fs = ump->um_fs;
402                 if (ronly != fs->fs_ronly) {
403                         fs->fs_ronly = ronly;
404                         fs->fs_clean = ronly &&
405                             (fs->fs_flags & FS_UNCLEAN) == 0 ? 1 : 0;
406
407                         /*
408                          * The device must be re-opened as appropriate or
409                          * the device close at unmount time will panic.
410                          */
411                         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
412                         if (ronly) {
413                                 VOP_OPEN(devvp, FREAD, FSCRED, NULL);
414                                 VOP_CLOSE(devvp, FREAD|FWRITE);
415                         } else {
416                                 VOP_OPEN(devvp, FREAD|FWRITE, FSCRED, NULL);
417                                 VOP_CLOSE(devvp, FREAD);
418                         }
419                         vn_unlock(devvp);
420                         ffs_sbupdate(ump, MNT_WAIT);
421                 }
422         }
423         return (error);
424 }
425
426 /*
427  * Reload all incore data for a filesystem (used after running fsck on
428  * the root filesystem and finding things to fix). The filesystem must
429  * be mounted read-only.
430  *
431  * Things to do to update the mount:
432  *      1) invalidate all cached meta-data.
433  *      2) re-read superblock from disk.
434  *      3) re-read summary information from disk.
435  *      4) invalidate all inactive vnodes.
436  *      5) invalidate all cached file data.
437  *      6) re-read inode data for all active vnodes.
438  */
439
440 static int ffs_reload_scan2(struct mount *mp, struct vnode *vp, void *data);
441
442 struct scaninfo {
443         int rescan;
444         struct fs *fs;
445         struct vnode *devvp;
446         int waitfor;
447         int allerror;
448 };
449
450 static int
451 ffs_reload(struct mount *mp, struct ucred *cred)
452 {
453         struct vnode *devvp;
454         void *space;
455         struct buf *bp;
456         struct fs *fs, *newfs;
457         struct partinfo dpart;
458         int i, blks, size, error;
459         struct scaninfo scaninfo;
460         int32_t *lp;
461
462         if ((mp->mnt_flag & MNT_RDONLY) == 0)
463                 return (EINVAL);
464         /*
465          * Step 1: invalidate all cached meta-data.
466          */
467         devvp = VFSTOUFS(mp)->um_devvp;
468         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
469         error = vinvalbuf(devvp, 0, 0, 0);
470         vn_unlock(devvp);
471         if (error)
472                 panic("ffs_reload: dirty1");
473
474         /*
475          * The backing device must be VMIO-capable because we use getblk().
476          * NOTE: the MFS driver now returns a VMIO-enabled descriptor.
477          */
478         if (devvp->v_object == NULL)
479                 panic("ffs_reload: devvp has no VM object!");
480
481         /*
482          * Step 2: re-read superblock from disk.
483          */
484         if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD,
485             cred, NULL) != 0) {
486                 size = DEV_BSIZE;
487         } else {
488                 size = dpart.media_blksize;
489         }
490         if ((error = bread(devvp, SBOFF, SBSIZE, &bp)) != 0) {
491                 brelse(bp);
492                 return (error);
493         }
494         newfs = (struct fs *)bp->b_data;
495         if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE ||
496                 newfs->fs_bsize < sizeof(struct fs)) {
497                         brelse(bp);
498                         return (EIO);           /* XXX needs translation */
499         }
500         fs = VFSTOUFS(mp)->um_fs;
501         /*
502          * Copy pointer fields back into superblock before copying in   XXX
503          * new superblock. These should really be in the ufsmount.      XXX
504          * Note that important parameters (eg fs_ncg) are unchanged.
505          */
506         newfs->fs_csp = fs->fs_csp;
507         newfs->fs_maxcluster = fs->fs_maxcluster;
508         newfs->fs_contigdirs = fs->fs_contigdirs;
509         /* The filesystem is still read-only. */
510         newfs->fs_ronly = 1;
511         bcopy(newfs, fs, (uint)fs->fs_sbsize);
512         if (fs->fs_sbsize < SBSIZE)
513                 bp->b_flags |= B_INVAL;
514         brelse(bp);
515         mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
516         ffs_oldfscompat(fs);
517         /* An old fsck may have zeroed these fields, so recheck them. */
518         if (fs->fs_avgfilesize <= 0)            /* XXX */
519                 fs->fs_avgfilesize = AVFILESIZ; /* XXX */
520         if (fs->fs_avgfpdir <= 0)               /* XXX */
521                 fs->fs_avgfpdir = AFPDIR;       /* XXX */
522
523         /*
524          * Step 3: re-read summary information from disk.
525          */
526         blks = howmany(fs->fs_cssize, fs->fs_fsize);
527         space = fs->fs_csp;
528         for (i = 0; i < blks; i += fs->fs_frag) {
529                 size = fs->fs_bsize;
530                 if (i + fs->fs_frag > blks)
531                         size = (blks - i) * fs->fs_fsize;
532                 error = bread(devvp, fsbtodoff(fs, fs->fs_csaddr + i), size, &bp);
533                 if (error) {
534                         brelse(bp);
535                         return (error);
536                 }
537                 bcopy(bp->b_data, space, (uint)size);
538                 space = (char *)space + size;
539                 brelse(bp);
540         }
541         /*
542          * We no longer know anything about clusters per cylinder group.
543          */
544         if (fs->fs_contigsumsize > 0) {
545                 lp = fs->fs_maxcluster;
546                 for (i = 0; i < fs->fs_ncg; i++)
547                         *lp++ = fs->fs_contigsumsize;
548         }
549
550         scaninfo.rescan = 0;
551         scaninfo.fs = fs;
552         scaninfo.devvp = devvp;
553         while (error == 0 && scaninfo.rescan) {
554                 scaninfo.rescan = 0;
555                 error = vmntvnodescan(mp, VMSC_GETVX, 
556                                         NULL, ffs_reload_scan2, &scaninfo);
557         }
558         return(error);
559 }
560
561 static int
562 ffs_reload_scan2(struct mount *mp, struct vnode *vp, void *data)
563 {
564         struct scaninfo *info = data;
565         struct inode *ip;
566         struct buf *bp;
567         int error;
568
569         /*
570          * Try to recycle
571          */
572         if (vrecycle(vp))
573                 return(0);
574
575         if (vinvalbuf(vp, 0, 0, 0))
576                 panic("ffs_reload: dirty2");
577         /*
578          * Step 6: re-read inode data for all active vnodes.
579          */
580         ip = VTOI(vp);
581         error = bread(info->devvp,
582                     fsbtodoff(info->fs, ino_to_fsba(info->fs, ip->i_number)),
583                     (int)info->fs->fs_bsize, &bp);
584         if (error) {
585                 brelse(bp);
586                 return (error);
587         }
588         ip->i_din = *((struct ufs1_dinode *)bp->b_data +
589             ino_to_fsbo(info->fs, ip->i_number));
590         ip->i_effnlink = ip->i_nlink;
591         brelse(bp);
592         return(0);
593 }
594
595 /*
596  * Common code for mount and mountroot
597  */
598 int
599 ffs_mountfs(struct vnode *devvp, struct mount *mp, struct malloc_type *mtype)
600 {
601         struct ufsmount *ump;
602         struct buf *bp;
603         struct fs *fs;
604         cdev_t dev;
605         struct partinfo dpart;
606         void *space;
607         int error, i, blks, size, ronly;
608         int32_t *lp;
609         uint64_t maxfilesize;                                   /* XXX */
610
611         /*
612          * Disallow multiple mounts of the same device.
613          * Disallow mounting of a device that is currently in use
614          * Flush out any old buffers remaining from a previous use.
615          */
616         error = vfs_mountedon(devvp);
617         if (error)
618                 return (error);
619         if (vcount(devvp) > 0)
620                 return (EBUSY);
621         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
622         error = vinvalbuf(devvp, V_SAVE, 0, 0);
623         vn_unlock(devvp);
624         if (error)
625                 return (error);
626
627         ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
628         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
629         error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, NULL);
630         vn_unlock(devvp);
631         if (error)
632                 return (error);
633         dev = devvp->v_rdev;
634         if (dev->si_iosize_max != 0)
635                 mp->mnt_iosize_max = dev->si_iosize_max;
636         if (mp->mnt_iosize_max > MAXPHYS)
637                 mp->mnt_iosize_max = MAXPHYS;
638
639         /*
640          * Filesystem supports native FSMIDs
641          */
642         mp->mnt_kern_flag |= MNTK_FSMID;
643
644         /*
645          * The backing device must be VMIO-capable because we use getblk().
646          * NOTE: the MFS driver now returns a VMIO-enabled descriptor.
647          * The VOP_OPEN() call above should have associated a VM object
648          * with devvp.
649          */
650         if (devvp->v_object == NULL)
651                 panic("ffs_reload: devvp has no VM object!");
652
653         if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD,
654                       proc0.p_ucred, NULL) != 0) {
655                 size = DEV_BSIZE;
656         } else {
657                 size = dpart.media_blksize;
658         }
659
660         bp = NULL;
661         ump = NULL;
662         if ((error = bread(devvp, SBOFF, SBSIZE, &bp)) != 0)
663                 goto out;
664         fs = (struct fs *)bp->b_data;
665         if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
666             fs->fs_bsize < sizeof(struct fs)) {
667                 error = EINVAL;         /* XXX needs translation */
668                 goto out;
669         }
670         fs->fs_fmod = 0;
671         fs->fs_flags &= ~FS_UNCLEAN;
672         if (fs->fs_clean == 0) {
673                 fs->fs_flags |= FS_UNCLEAN;
674                 if (ronly || (mp->mnt_flag & MNT_FORCE)) {
675                         kprintf(
676 "WARNING: %s was not properly dismounted\n",
677                             fs->fs_fsmnt);
678                 } else {
679                         kprintf(
680 "WARNING: R/W mount of %s denied.  Filesystem is not clean - run fsck\n",
681                             fs->fs_fsmnt);
682                         error = EPERM;
683                         goto out;
684                 }
685         }
686         /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */
687         if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) {
688                 error = EROFS;          /* needs translation */
689                 goto out;
690         }
691         ump = kmalloc(sizeof *ump, M_UFSMNT, M_WAITOK | M_ZERO);
692         ump->um_malloctype = mtype;
693         ump->um_i_effnlink_valid = 1;
694         ump->um_fs = kmalloc((u_long)fs->fs_sbsize, M_UFSMNT,
695             M_WAITOK);
696         bcopy(bp->b_data, ump->um_fs, (uint)fs->fs_sbsize);
697         if (fs->fs_sbsize < SBSIZE)
698                 bp->b_flags |= B_INVAL;
699         brelse(bp);
700         bp = NULL;
701         fs = ump->um_fs;
702         fs->fs_ronly = ronly;
703         size = fs->fs_cssize;
704         blks = howmany(size, fs->fs_fsize);
705         if (fs->fs_contigsumsize > 0)
706                 size += fs->fs_ncg * sizeof(int32_t);
707         size += fs->fs_ncg * sizeof(uint8_t);
708         space = kmalloc((u_long)size, M_UFSMNT, M_WAITOK);
709         fs->fs_csp = space;
710         for (i = 0; i < blks; i += fs->fs_frag) {
711                 size = fs->fs_bsize;
712                 if (i + fs->fs_frag > blks)
713                         size = (blks - i) * fs->fs_fsize;
714                 if ((error = bread(devvp, fsbtodoff(fs, fs->fs_csaddr + i),
715                                    size, &bp)) != 0) {
716                         kfree(fs->fs_csp, M_UFSMNT);
717                         goto out;
718                 }
719                 bcopy(bp->b_data, space, (uint)size);
720                 space = (char *)space + size;
721                 brelse(bp);
722                 bp = NULL;
723         }
724         if (fs->fs_contigsumsize > 0) {
725                 fs->fs_maxcluster = lp = space;
726                 for (i = 0; i < fs->fs_ncg; i++)
727                         *lp++ = fs->fs_contigsumsize;
728                 space = lp;
729         }
730         size = fs->fs_ncg * sizeof(uint8_t);
731         fs->fs_contigdirs = (uint8_t *)space;
732         bzero(fs->fs_contigdirs, size);
733         /* Compatibility for old filesystems       XXX */
734         if (fs->fs_avgfilesize <= 0)            /* XXX */
735                 fs->fs_avgfilesize = AVFILESIZ; /* XXX */
736         if (fs->fs_avgfpdir <= 0)               /* XXX */
737                 fs->fs_avgfpdir = AFPDIR;       /* XXX */
738         mp->mnt_data = (qaddr_t)ump;
739         mp->mnt_stat.f_fsid.val[0] = fs->fs_id[0];
740         mp->mnt_stat.f_fsid.val[1] = fs->fs_id[1];
741         if (fs->fs_id[0] == 0 || fs->fs_id[1] == 0 || 
742             vfs_getvfs(&mp->mnt_stat.f_fsid)) 
743                 vfs_getnewfsid(mp);
744         mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
745         mp->mnt_flag |= MNT_LOCAL;
746         ump->um_mountp = mp;
747         ump->um_dev = dev;
748         ump->um_devvp = devvp;
749         ump->um_nindir = fs->fs_nindir;
750         ump->um_bptrtodb = fs->fs_fsbtodb;
751         ump->um_seqinc = fs->fs_frag;
752         for (i = 0; i < MAXQUOTAS; i++)
753                 ump->um_quotas[i] = NULLVP;
754         dev->si_mountpoint = mp;
755         ffs_oldfscompat(fs);
756
757         /* restore "last mounted on" here */
758         bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt));
759         ksnprintf(fs->fs_fsmnt, sizeof(fs->fs_fsmnt),
760                  "%s", mp->mnt_stat.f_mntonname);
761
762         if( mp->mnt_flag & MNT_ROOTFS) {
763                 /*
764                  * Root mount; update timestamp in mount structure.
765                  * this will be used by the common root mount code
766                  * to update the system clock.
767                  */
768                 mp->mnt_time = fs->fs_time;
769         }
770
771         ump->um_savedmaxfilesize = fs->fs_maxfilesize;          /* XXX */
772         maxfilesize = (uint64_t)0x40000000 * fs->fs_bsize - 1;  /* XXX */
773         /* Enforce limit caused by vm object backing (32 bits vm_pindex_t). */
774         if (maxfilesize > (uint64_t)0x80000000u * PAGE_SIZE - 1)
775                 maxfilesize = (uint64_t)0x80000000u * PAGE_SIZE - 1;
776         if (fs->fs_maxfilesize > maxfilesize)                   /* XXX */
777                 fs->fs_maxfilesize = maxfilesize;               /* XXX */
778         if (ronly == 0) {
779                 if ((fs->fs_flags & FS_DOSOFTDEP) &&
780                     (error = softdep_mount(devvp, mp, fs)) != 0) {
781                         kfree(fs->fs_csp, M_UFSMNT);
782                         goto out;
783                 }
784                 fs->fs_fmod = 1;
785                 fs->fs_clean = 0;
786                 (void) ffs_sbupdate(ump, MNT_WAIT);
787         }
788         vfs_add_vnodeops(mp, &ffs_vnode_vops, &mp->mnt_vn_norm_ops);
789         vfs_add_vnodeops(mp, &ffs_spec_vops, &mp->mnt_vn_spec_ops);
790         vfs_add_vnodeops(mp, &ffs_fifo_vops, &mp->mnt_vn_fifo_ops);
791
792         return (0);
793 out:
794         dev->si_mountpoint = NULL;
795         if (bp)
796                 brelse(bp);
797         VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE);
798         if (ump) {
799                 kfree(ump->um_fs, M_UFSMNT);
800                 kfree(ump, M_UFSMNT);
801                 mp->mnt_data = (qaddr_t)0;
802         }
803         return (error);
804 }
805
806 /*
807  * Sanity checks for old filesystems.
808  *
809  * XXX - goes away some day.
810  */
811 static int
812 ffs_oldfscompat(struct fs *fs)
813 {
814         fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect);       /* XXX */
815         fs->fs_interleave = max(fs->fs_interleave, 1);          /* XXX */
816         if (fs->fs_postblformat == FS_42POSTBLFMT)              /* XXX */
817                 fs->fs_nrpos = 8;                               /* XXX */
818         if (fs->fs_inodefmt < FS_44INODEFMT) {                  /* XXX */
819 #if 0
820                 int i;                                          /* XXX */
821                 uint64_t sizepb = fs->fs_bsize;         /* XXX */
822                                                                 /* XXX */
823                 fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
824                 for (i = 0; i < NIADDR; i++) {                  /* XXX */
825                         sizepb *= NINDIR(fs);                   /* XXX */
826                         fs->fs_maxfilesize += sizepb;           /* XXX */
827                 }                                               /* XXX */
828 #endif
829                 fs->fs_maxfilesize = (u_quad_t) 1LL << 39;
830                 fs->fs_qbmask = ~fs->fs_bmask;                  /* XXX */
831                 fs->fs_qfmask = ~fs->fs_fmask;                  /* XXX */
832         }                                                       /* XXX */
833         return (0);
834 }
835
836 /*
837  * unmount system call
838  */
839 int
840 ffs_unmount(struct mount *mp, int mntflags)
841 {
842         struct ufsmount *ump;
843         struct fs *fs;
844         int error, flags;
845
846         flags = 0;
847         if (mntflags & MNT_FORCE) {
848                 flags |= FORCECLOSE;
849         }
850         if (mp->mnt_flag & MNT_SOFTDEP) {
851                 if ((error = softdep_flushfiles(mp, flags)) != 0)
852                         return (error);
853         } else {
854                 if ((error = ffs_flushfiles(mp, flags)) != 0)
855                         return (error);
856         }
857         ump = VFSTOUFS(mp);
858         fs = ump->um_fs;
859         if (fs->fs_ronly == 0) {
860                 fs->fs_clean = fs->fs_flags & FS_UNCLEAN ? 0 : 1;
861                 error = ffs_sbupdate(ump, MNT_WAIT);
862                 if (error) {
863                         fs->fs_clean = 0;
864                         return (error);
865                 }
866         }
867         ump->um_devvp->v_rdev->si_mountpoint = NULL;
868
869         vinvalbuf(ump->um_devvp, V_SAVE, 0, 0);
870         error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE);
871
872         vrele(ump->um_devvp);
873
874         kfree(fs->fs_csp, M_UFSMNT);
875         kfree(fs, M_UFSMNT);
876         kfree(ump, M_UFSMNT);
877         mp->mnt_data = (qaddr_t)0;
878         mp->mnt_flag &= ~MNT_LOCAL;
879         return (error);
880 }
881
882 /*
883  * Flush out all the files in a filesystem.
884  */
885 int
886 ffs_flushfiles(struct mount *mp, int flags)
887 {
888         struct ufsmount *ump;
889         int error;
890
891         ump = VFSTOUFS(mp);
892 #ifdef QUOTA
893         if (mp->mnt_flag & MNT_QUOTA) {
894                 int i;
895                 error = vflush(mp, 0, SKIPSYSTEM|flags);
896                 if (error)
897                         return (error);
898                 /* Find out how many quota files  we have open. */
899                 for (i = 0; i < MAXQUOTAS; i++) {
900                         if (ump->um_quotas[i] == NULLVP)
901                                 continue;
902                         ufs_quotaoff(mp, i);
903                 }
904                 /*
905                  * Here we fall through to vflush again to ensure
906                  * that we have gotten rid of all the system vnodes.
907                  */
908         }
909 #endif
910         /*
911          * Flush all the files.
912          */
913         if ((error = vflush(mp, 0, flags)) != 0)
914                 return (error);
915         /*
916          * Flush filesystem metadata.
917          */
918         vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
919         error = VOP_FSYNC(ump->um_devvp, MNT_WAIT, 0);
920         vn_unlock(ump->um_devvp);
921         return (error);
922 }
923
924 /*
925  * Get filesystem statistics.
926  */
927 int
928 ffs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
929 {
930         struct ufsmount *ump;
931         struct fs *fs;
932
933         ump = VFSTOUFS(mp);
934         fs = ump->um_fs;
935         if (fs->fs_magic != FS_MAGIC)
936                 panic("ffs_statfs");
937         sbp->f_bsize = fs->fs_fsize;
938         sbp->f_iosize = fs->fs_bsize;
939         sbp->f_blocks = fs->fs_dsize;
940         sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
941                 fs->fs_cstotal.cs_nffree;
942         sbp->f_bavail = freespace(fs, fs->fs_minfree);
943         sbp->f_files =  fs->fs_ncg * fs->fs_ipg - ROOTINO;
944         sbp->f_ffree = fs->fs_cstotal.cs_nifree;
945         if (sbp != &mp->mnt_stat) {
946                 sbp->f_type = mp->mnt_vfc->vfc_typenum;
947                 bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
948                         (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
949         }
950         return (0);
951 }
952
953 /*
954  * Go through the disk queues to initiate sandbagged IO;
955  * go through the inodes to write those that have been modified;
956  * initiate the writing of the super block if it has been modified.
957  *
958  * Note: we are always called with the filesystem marked `MPBUSY'.
959  */
960
961
962 static int ffs_sync_scan1(struct mount *mp, struct vnode *vp, void *data);
963 static int ffs_sync_scan2(struct mount *mp, struct vnode *vp, void *data);
964
965 int
966 ffs_sync(struct mount *mp, int waitfor)
967 {
968         struct ufsmount *ump = VFSTOUFS(mp);
969         struct fs *fs;
970         int error;
971         struct scaninfo scaninfo;
972
973         fs = ump->um_fs;
974         if (fs->fs_fmod != 0 && fs->fs_ronly != 0) {            /* XXX */
975                 kprintf("fs = %s\n", fs->fs_fsmnt);
976                 panic("ffs_sync: rofs mod");
977         }
978
979         /*
980          * Write back each (modified) inode.
981          */
982         scaninfo.allerror = 0;
983         scaninfo.rescan = 1;
984         scaninfo.waitfor = waitfor;
985         while (scaninfo.rescan) {
986                 scaninfo.rescan = 0;
987                 vmntvnodescan(mp, VMSC_GETVP|VMSC_NOWAIT,
988                                 ffs_sync_scan1, ffs_sync_scan2, &scaninfo);
989         }
990
991         /*
992          * Force stale filesystem control information to be flushed.
993          */
994         if ((waitfor & MNT_LAZY) == 0) {
995                 if (ump->um_mountp->mnt_flag & MNT_SOFTDEP)
996                         waitfor = MNT_NOWAIT;
997                 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
998                 if ((error = VOP_FSYNC(ump->um_devvp, waitfor, 0)) != 0)
999                         scaninfo.allerror = error;
1000                 vn_unlock(ump->um_devvp);
1001         }
1002 #ifdef QUOTA
1003         ufs_qsync(mp);
1004 #endif
1005         /*
1006          * Write back modified superblock.
1007          */
1008         if (fs->fs_fmod != 0 && (error = ffs_sbupdate(ump, waitfor)) != 0)
1009                 scaninfo.allerror = error;
1010         return (scaninfo.allerror);
1011 }
1012
1013 static int
1014 ffs_sync_scan1(struct mount *mp, struct vnode *vp, void *data)
1015 {
1016         struct inode *ip;
1017
1018         /*
1019          * Depend on the mount list's vnode lock to keep things stable 
1020          * enough for a quick test.  Since there might be hundreds of 
1021          * thousands of vnodes, we cannot afford even a subroutine
1022          * call unless there's a good chance that we have work to do.
1023          */
1024         ip = VTOI(vp);
1025         /* Restart out whole search if this guy is locked
1026          * or is being reclaimed.
1027          */
1028         if (vp->v_type == VNON || (ip == NULL) || ((ip->i_flag &
1029              (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
1030              RB_EMPTY(&vp->v_rbdirty_tree))) {
1031                 return(-1);
1032         }
1033         return(0);
1034 }
1035
1036 static int 
1037 ffs_sync_scan2(struct mount *mp, struct vnode *vp, void *data)
1038 {
1039         struct scaninfo *info = data;
1040         struct inode *ip;
1041         int error;
1042
1043         /*
1044          * We have to recheck after having obtained the vnode interlock.
1045          */
1046         ip = VTOI(vp);
1047         if (vp->v_type == VNON || vp->v_type == VBAD ||
1048              ((ip->i_flag &
1049               (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
1050              RB_EMPTY(&vp->v_rbdirty_tree))) {
1051                 return(0);
1052         }
1053         if (vp->v_type != VCHR) {
1054                 if ((error = VOP_FSYNC(vp, info->waitfor, 0)) != 0)
1055                         info->allerror = error;
1056         } else {
1057                 /*
1058                  * We must reference the vp to prevent it from
1059                  * getting ripped out from under ffs_update, since
1060                  * we are not holding a vnode lock.
1061                  */
1062                 /* ffs_update(vp, waitfor == MNT_WAIT); */
1063                 ffs_update(vp, 0);
1064         }
1065         return(0);
1066 }
1067
1068 /*
1069  * Look up a FFS dinode number to find its incore vnode, otherwise read it
1070  * in from disk.  If it is in core, wait for the lock bit to clear, then
1071  * return the inode locked.  Detection and handling of mount points must be
1072  * done by the calling routine.
1073  */
1074
1075 int
1076 ffs_vget(struct mount *mp, struct vnode *dvp, ino_t ino, struct vnode **vpp)
1077 {
1078         struct fs *fs;
1079         struct inode *ip;
1080         struct ufsmount *ump;
1081         struct buf *bp;
1082         struct vnode *vp;
1083         cdev_t dev;
1084         int error;
1085
1086         ump = VFSTOUFS(mp);
1087         dev = ump->um_dev;
1088 restart:
1089         if ((*vpp = ufs_ihashget(dev, ino)) != NULL) {
1090                 return (0);
1091         }
1092
1093         /*
1094          * If this MALLOC() is performed after the getnewvnode()
1095          * it might block, leaving a vnode with a NULL v_data to be
1096          * found by ffs_sync() if a sync happens to fire right then,
1097          * which will cause a panic because ffs_sync() blindly
1098          * dereferences vp->v_data (as well it should).
1099          *
1100          * XXX this may no longer be true since getnewvnode returns a
1101          * VX locked vnode now.
1102          */
1103         ip = kmalloc(sizeof(struct inode), ump->um_malloctype, M_WAITOK);
1104
1105         /* Allocate a new vnode/inode. */
1106         error = getnewvnode(VT_UFS, mp, &vp, VLKTIMEOUT, LK_CANRECURSE);
1107         if (error) {
1108                 *vpp = NULL;
1109                 kfree(ip, ump->um_malloctype);
1110                 return (error);
1111         }
1112         bzero((caddr_t)ip, sizeof(struct inode));
1113         ip->i_vnode = vp;
1114         ip->i_fs = fs = ump->um_fs;
1115         ip->i_dev = dev;
1116         ip->i_number = ino;
1117 #ifdef QUOTA
1118         {
1119                 int i;
1120                 for (i = 0; i < MAXQUOTAS; i++)
1121                         ip->i_dquot[i] = NODQUOT;
1122         }
1123 #endif
1124
1125         /*
1126          * Insert it into the inode hash table and check for a collision.
1127          * If a collision occurs, throw away the vnode and try again.
1128          */
1129         if (ufs_ihashins(ip) != 0) {
1130                 kprintf("debug: ufs ihashins collision, retrying inode %ld\n",
1131                     (long)ip->i_number);
1132                 vp->v_type = VBAD;
1133                 vx_put(vp);
1134                 kfree(ip, ump->um_malloctype);
1135                 goto restart;
1136         }
1137         vp->v_data = ip;
1138
1139         /* Read in the disk contents for the inode, copy into the inode. */
1140         error = bread(ump->um_devvp, fsbtodoff(fs, ino_to_fsba(fs, ino)),
1141             (int)fs->fs_bsize, &bp);
1142         if (error) {
1143                 /*
1144                  * The inode does not contain anything useful, so it would
1145                  * be misleading to leave it on its hash chain. With mode
1146                  * still zero, it will be unlinked and returned to the free
1147                  * list by vput().
1148                  */
1149                 vp->v_type = VBAD;
1150                 brelse(bp);
1151                 vx_put(vp);
1152                 *vpp = NULL;
1153                 return (error);
1154         }
1155         ip->i_din = *((struct ufs1_dinode *)bp->b_data + ino_to_fsbo(fs, ino));
1156         if (DOINGSOFTDEP(vp))
1157                 softdep_load_inodeblock(ip);
1158         else
1159                 ip->i_effnlink = ip->i_nlink;
1160         bqrelse(bp);
1161
1162         /*
1163          * Initialize the vnode from the inode, check for aliases.
1164          * Note that the underlying vnode may have changed.
1165          */
1166         error = ufs_vinit(mp, &vp);
1167         if (error) {
1168                 vp->v_type = VBAD;
1169                 vx_put(vp);
1170                 *vpp = NULL;
1171                 return (error);
1172         }
1173         /*
1174          * Finish inode initialization now that aliasing has been resolved.
1175          */
1176         ip->i_devvp = ump->um_devvp;
1177         vref(ip->i_devvp);
1178         /*
1179          * Set up a generation number for this inode if it does not
1180          * already have one. This should only happen on old filesystems.
1181          */
1182         if (ip->i_gen == 0) {
1183                 ip->i_gen = krandom() / 2 + 1;
1184                 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
1185                         ip->i_flag |= IN_MODIFIED;
1186         }
1187         /*
1188          * Ensure that uid and gid are correct. This is a temporary
1189          * fix until fsck has been changed to do the update.
1190          */
1191         if (fs->fs_inodefmt < FS_44INODEFMT) {          /* XXX */
1192                 ip->i_uid = ip->i_din.di_ouid;          /* XXX */
1193                 ip->i_gid = ip->i_din.di_ogid;          /* XXX */
1194         }                                               /* XXX */
1195
1196         /* 
1197          * return a VX locked and refd vnode (VX == same as normal vget()
1198          * vnode so we are ok)
1199          */
1200         *vpp = vp;
1201         return (0);
1202 }
1203
1204 /*
1205  * File handle to vnode
1206  *
1207  * Have to be really careful about stale file handles:
1208  * - check that the inode number is valid
1209  * - call ffs_vget() to get the locked inode
1210  * - check for an unallocated inode (i_mode == 0)
1211  * - check that the given client host has export rights and return
1212  *   those rights via. exflagsp and credanonp
1213  */
1214 int
1215 ffs_fhtovp(struct mount *mp, struct vnode *rootvp,
1216            struct fid *fhp, struct vnode **vpp)
1217 {
1218         struct ufid *ufhp;
1219         struct fs *fs;
1220
1221         ufhp = (struct ufid *)fhp;
1222         fs = VFSTOUFS(mp)->um_fs;
1223         if (ufhp->ufid_ino < ROOTINO ||
1224             ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg)
1225                 return (ESTALE);
1226         return (ufs_fhtovp(mp, rootvp, ufhp, vpp));
1227 }
1228
1229 /*
1230  * Vnode pointer to File handle
1231  */
1232 /* ARGSUSED */
1233 int
1234 ffs_vptofh(struct vnode *vp, struct fid *fhp)
1235 {
1236         struct inode *ip;
1237         struct ufid *ufhp;
1238
1239         ip = VTOI(vp);
1240         ufhp = (struct ufid *)fhp;
1241         ufhp->ufid_len = sizeof(struct ufid);
1242         ufhp->ufid_ino = ip->i_number;
1243         ufhp->ufid_gen = ip->i_gen;
1244         return (0);
1245 }
1246
1247 /*
1248  * Initialize the filesystem; just use ufs_init.
1249  */
1250 static int
1251 ffs_init(struct vfsconf *vfsp)
1252 {
1253         softdep_initialize();
1254         kmalloc_raise_limit(M_FFSNODE, 0);
1255         return (ufs_init(vfsp));
1256 }
1257
1258 /*
1259  * Write a superblock and associated information back to disk.
1260  */
1261 static int
1262 ffs_sbupdate(struct ufsmount *mp, int waitfor)
1263 {
1264         struct fs *dfs, *fs = mp->um_fs;
1265         struct buf *bp;
1266         int blks;
1267         void *space;
1268         int i, size, error, allerror = 0;
1269
1270         /*
1271          * First write back the summary information.
1272          *
1273          * NOTE: the getblk is relative to the device vnode so bio1
1274          * contains the device block number.
1275          */
1276         blks = howmany(fs->fs_cssize, fs->fs_fsize);
1277         space = fs->fs_csp;
1278         for (i = 0; i < blks; i += fs->fs_frag) {
1279                 size = fs->fs_bsize;
1280                 if (i + fs->fs_frag > blks)
1281                         size = (blks - i) * fs->fs_fsize;
1282                 bp = getblk(mp->um_devvp, fsbtodoff(fs, fs->fs_csaddr + i),
1283                             size, 0, 0);
1284                 bcopy(space, bp->b_data, (uint)size);
1285                 space = (char *)space + size;
1286                 if (waitfor != MNT_WAIT)
1287                         bawrite(bp);
1288                 else if ((error = bwrite(bp)) != 0)
1289                         allerror = error;
1290         }
1291         /*
1292          * Now write back the superblock itself. If any errors occurred
1293          * up to this point, then fail so that the superblock avoids
1294          * being written out as clean.
1295          */
1296         if (allerror)
1297                 return (allerror);
1298         bp = getblk(mp->um_devvp, SBOFF, (int)fs->fs_sbsize, 0, 0);
1299         fs->fs_fmod = 0;
1300         fs->fs_time = time_second;
1301         bcopy((caddr_t)fs, bp->b_data, (uint)fs->fs_sbsize);
1302         /* Restore compatibility to old filesystems.               XXX */
1303         dfs = (struct fs *)bp->b_data;                          /* XXX */
1304         if (fs->fs_postblformat == FS_42POSTBLFMT)              /* XXX */
1305                 dfs->fs_nrpos = -1;                             /* XXX */
1306         if (fs->fs_inodefmt < FS_44INODEFMT) {                  /* XXX */
1307                 int32_t *lp, tmp;                               /* XXX */
1308                                                                 /* XXX */
1309                 lp = (int32_t *)&dfs->fs_qbmask;                /* XXX */
1310                 tmp = lp[4];                                    /* XXX */
1311                 for (i = 4; i > 0; i--)                         /* XXX */
1312                         lp[i] = lp[i-1];                        /* XXX */
1313                 lp[0] = tmp;                                    /* XXX */
1314         }                                                       /* XXX */
1315         dfs->fs_maxfilesize = mp->um_savedmaxfilesize;          /* XXX */
1316         if (waitfor != MNT_WAIT)
1317                 bawrite(bp);
1318         else if ((error = bwrite(bp)) != 0)
1319                 allerror = error;
1320         return (allerror);
1321 }