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