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