Device layer rollup commit.
[dragonfly.git] / sys / vfs / ufs / ffs_vfsops.c
index 9c63b76..ec2711d 100644 (file)
  *
  *     @(#)ffs_vfsops.c        8.31 (Berkeley) 5/20/95
  * $FreeBSD: src/sys/ufs/ffs/ffs_vfsops.c,v 1.117.2.10 2002/06/23 22:34:52 iedowse Exp $
- * $DragonFly: src/sys/vfs/ufs/ffs_vfsops.c,v 1.2 2003/06/17 04:28:59 dillon Exp $
+ * $DragonFly: src/sys/vfs/ufs/ffs_vfsops.c,v 1.18 2004/05/19 22:53:06 dillon Exp $
  */
 
 #include "opt_quota.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
-#include <sys/namei.h>
 #include <sys/proc.h>
+#include <sys/namei.h>
 #include <sys/kernel.h>
 #include <sys/vnode.h>
 #include <sys/mount.h>
 #include <sys/disklabel.h>
 #include <sys/malloc.h>
 
-#include <ufs/ufs/quota.h>
-#include <ufs/ufs/ufsmount.h>
-#include <ufs/ufs/inode.h>
-#include <ufs/ufs/ufs_extern.h>
+#include "quota.h"
+#include "ufsmount.h"
+#include "inode.h"
+#include "ufs_extern.h"
 
-#include <ufs/ffs/fs.h>
-#include <ufs/ffs/ffs_extern.h>
+#include "fs.h"
+#include "ffs_extern.h"
 
 #include <vm/vm.h>
 #include <vm/vm_page.h>
 
 static MALLOC_DEFINE(M_FFSNODE, "FFS node", "FFS vnode private part");
 
-static int     ffs_sbupdate __P((struct ufsmount *, int));
-static int     ffs_reload __P((struct mount *,struct ucred *,struct proc *));
-static int     ffs_oldfscompat __P((struct fs *));
-static int     ffs_mount __P((struct mount *, char *, caddr_t,
-                               struct nameidata *, struct proc *));
-static int     ffs_init __P((struct vfsconf *));
+static int     ffs_sbupdate (struct ufsmount *, int);
+static int     ffs_reload (struct mount *,struct ucred *,struct thread *);
+static int     ffs_oldfscompat (struct fs *);
+static int     ffs_mount (struct mount *, char *, caddr_t,
+                               struct nameidata *, struct thread *);
+static int     ffs_init (struct vfsconf *);
 
 static struct vfsops ufs_vfsops = {
        ffs_mount,
@@ -128,12 +128,11 @@ VFS_SET(ufs_vfsops, ufs, 0);
  *             namei() if it is a genuine NULL from the user.
  */
 static int
-ffs_mount( mp, path, data, ndp, p)
-        struct mount           *mp;    /* mount struct pointer*/
-        char                   *path;  /* path to mount point*/
-        caddr_t                        data;   /* arguments to FS specific mount*/
-        struct nameidata       *ndp;   /* mount point credentials*/
-        struct proc            *p;     /* process requesting mount*/
+ffs_mount(struct mount *mp,            /* mount struct pointer */
+          char *path,                  /* path to mount point */
+          caddr_t data,                        /* arguments to FS specific mount */
+          struct nameidata *ndp,       /* mount point credentials */
+          struct thread        *td)            /* process requesting mount */
 {
        size_t          size;
        int             err = 0;
@@ -141,9 +140,13 @@ ffs_mount( mp, path, data, ndp, p)
 
        struct ufs_args args;
        struct ufsmount *ump = 0;
-       register struct fs *fs;
+       struct fs *fs;
        int error, flags, ronly = 0;
        mode_t accessmode;
+       struct ucred *cred;
+
+       KKASSERT(td->td_proc);
+       cred = td->td_proc->p_ucred;
 
        /*
         * Use NULL path to flag a root mount
@@ -160,7 +163,7 @@ ffs_mount( mp, path, data, ndp, p)
                        return (err);
                }
 
-               if( ( err = ffs_mountfs(rootvp, mp, p, M_FFSNODE)) != 0) {
+               if( ( err = ffs_mountfs(rootvp, mp, td, M_FFSNODE)) != 0) {
                        /* fs specific cleanup (if any)*/
                        goto error_1;
                }
@@ -194,7 +197,7 @@ ffs_mount( mp, path, data, ndp, p)
                        /*
                         * Flush any dirty data.
                         */
-                       VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p);
+                       VFS_SYNC(mp, MNT_WAIT, td);
                        /*
                         * Check for and optionally get rid of files open
                         * for writing.
@@ -203,14 +206,14 @@ ffs_mount( mp, path, data, ndp, p)
                        if (mp->mnt_flag & MNT_FORCE)
                                flags |= FORCECLOSE;
                        if (mp->mnt_flag & MNT_SOFTDEP) {
-                               err = softdep_flushfiles(mp, flags, p);
+                               err = softdep_flushfiles(mp, flags, td);
                        } else {
-                               err = ffs_flushfiles(mp, flags, p);
+                               err = ffs_flushfiles(mp, flags, td);
                        }
                        ronly = 1;
                }
                if (!err && (mp->mnt_flag & MNT_RELOAD))
-                       err = ffs_reload(mp, ndp->ni_cnd.cn_cred, p);
+                       err = ffs_reload(mp, ndp->ni_cnd.cn_cred, td);
                if (err) {
                        goto error_1;
                }
@@ -219,14 +222,14 @@ ffs_mount( mp, path, data, ndp, p)
                         * If upgrade to read-write by non-root, then verify
                         * that user has necessary permissions on the device.
                         */
-                       if (p->p_ucred->cr_uid != 0) {
-                               vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
+                       if (cred->cr_uid != 0) {
+                               vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
                                if ((error = VOP_ACCESS(devvp, VREAD | VWRITE,
-                                   p->p_ucred, p)) != 0) {
-                                       VOP_UNLOCK(devvp, 0, p);
+                                   cred, td)) != 0) {
+                                       VOP_UNLOCK(devvp, NULL, 0, td);
                                        return (error);
                                }
-                               VOP_UNLOCK(devvp, 0, p);
+                               VOP_UNLOCK(devvp, NULL, 0, td);
                        }
 
                        fs->fs_flags &= ~FS_UNCLEAN;
@@ -247,7 +250,7 @@ ffs_mount( mp, path, data, ndp, p)
 
                        /* check to see if we need to start softdep */
                        if (fs->fs_flags & FS_DOSOFTDEP) {
-                               err = softdep_mount(devvp, mp, fs, p->p_ucred);
+                               err = softdep_mount(devvp, mp, fs);
                                if (err)
                                        goto error_1;
                        }
@@ -279,7 +282,7 @@ ffs_mount( mp, path, data, ndp, p)
         * Not an update, or updating the name: look up the name
         * and verify that it refers to a sensible block device.
         */
-       NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
+       NDINIT(ndp, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, args.fspec, td);
        err = namei(ndp);
        if (err) {
                /* can't get devvp!*/
@@ -296,16 +299,16 @@ ffs_mount( mp, path, data, ndp, p)
         * If mount by non-root, then verify that user has necessary
         * permissions on the device.
         */
-       if (p->p_ucred->cr_uid != 0) {
+       if (cred->cr_uid != 0) {
                accessmode = VREAD;
                if ((mp->mnt_flag & MNT_RDONLY) == 0)
                        accessmode |= VWRITE;
-               vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
-               if ((error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) != 0) {
+               vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
+               if ((error = VOP_ACCESS(devvp, accessmode, cred, td)) != 0) {
                        vput(devvp);
                        return (error);
                }
-               VOP_UNLOCK(devvp, 0, p);
+               VOP_UNLOCK(devvp, NULL, 0, td);
        }
 
        if (mp->mnt_flag & MNT_UPDATE) {
@@ -313,18 +316,22 @@ ffs_mount( mp, path, data, ndp, p)
                 ********************
                 * UPDATE
                 * If it's not the same vnode, or at least the same device
-                * then it's not correct.
+                * then it's not correct.  NOTE: devvp->v_rdev may be NULL
+                * since we haven't opened it, so we compare udev instead.
                 ********************
                 */
-
                if (devvp != ump->um_devvp) {
-                       if ( devvp->v_rdev == ump->um_devvp->v_rdev) {
+                       if (devvp->v_udev == ump->um_devvp->v_udev) {
                                vrele(devvp);
                        } else {
+                               printf("cannot update mount, udev does"
+                                       " not match %08x vs %08x\n",
+                                       devvp->v_udev, ump->um_devvp->v_udev);
                                err = EINVAL;   /* needs translation */
                        }
-               } else
+               } else {
                        vrele(devvp);
+               }
                /*
                 * Update device name only on success
                 */
@@ -363,7 +370,7 @@ ffs_mount( mp, path, data, ndp, p)
                                &size);                         /* real size*/
                bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
 
-               err = ffs_mountfs(devvp, mp, p, M_FFSNODE);
+               err = ffs_mountfs(devvp, mp, td, M_FFSNODE);
        }
        if (err) {
                goto error_2;
@@ -376,7 +383,7 @@ dostatfs:
         *
         * This code is common to root and non-root mounts
         */
-       (void)VFS_STATFS(mp, &mp->mnt_stat, p);
+       (void)VFS_STATFS(mp, &mp->mnt_stat, td);
 
        goto success;
 
@@ -415,20 +422,32 @@ success:
  *     5) invalidate all cached file data.
  *     6) re-read inode data for all active vnodes.
  */
+
+static int ffs_reload_scan1(struct mount *mp, struct vnode *vp, void *data);
+static int ffs_reload_scan2(struct mount *mp, struct vnode *vp,
+                               lwkt_tokref_t vlock, void *data);
+
+struct scaninfo {
+       int rescan;
+       struct fs *fs;
+       struct vnode *devvp;
+       thread_t td;
+       int waitfor;
+       int allerror;
+};
+
 static int
-ffs_reload(mp, cred, p)
-       register struct mount *mp;
-       struct ucred *cred;
-       struct proc *p;
+ffs_reload(struct mount *mp, struct ucred *cred, struct thread *td)
 {
-       register struct vnode *vp, *nvp, *devvp;
-       struct inode *ip;
+       struct vnode *devvp;
        void *space;
        struct buf *bp;
        struct fs *fs, *newfs;
        struct partinfo dpart;
        dev_t dev;
        int i, blks, size, error;
+       lwkt_tokref vlock;
+       struct scaninfo scaninfo;
        int32_t *lp;
 
        if ((mp->mnt_flag & MNT_RDONLY) == 0)
@@ -437,33 +456,32 @@ ffs_reload(mp, cred, p)
         * Step 1: invalidate all cached meta-data.
         */
        devvp = VFSTOUFS(mp)->um_devvp;
-       vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
-       error = vinvalbuf(devvp, 0, cred, p, 0, 0);
-       VOP_UNLOCK(devvp, 0, p);
+       vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
+       error = vinvalbuf(devvp, 0, td, 0, 0);
+       VOP_UNLOCK(devvp, NULL, 0, td);
        if (error)
                panic("ffs_reload: dirty1");
 
        dev = devvp->v_rdev;
-
        /*
         * Only VMIO the backing device if the backing device is a real
         * block device.  See ffs_mountmfs() for more details.
         */
        if (devvp->v_tag != VT_MFS && vn_isdisk(devvp, NULL)) {
-               vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
-               vfs_object_create(devvp, p, p->p_ucred);
-               simple_lock(&devvp->v_interlock);
-               VOP_UNLOCK(devvp, LK_INTERLOCK, p);
+               vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
+               vfs_object_create(devvp, td);
+               lwkt_gettoken(&vlock, devvp->v_interlock);
+               VOP_UNLOCK(devvp, &vlock, LK_INTERLOCK, td);
        }
 
        /*
         * Step 2: re-read superblock from disk.
         */
-       if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
+       if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, td) != 0)
                size = DEV_BSIZE;
        else
                size = dpart.disklab->d_secsize;
-       if ((error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, NOCRED,&bp)) != 0)
+       if ((error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, &bp)) != 0)
                return (error);
        newfs = (struct fs *)bp->b_data;
        if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE ||
@@ -480,6 +498,8 @@ ffs_reload(mp, cred, p)
        newfs->fs_csp = fs->fs_csp;
        newfs->fs_maxcluster = fs->fs_maxcluster;
        newfs->fs_contigdirs = fs->fs_contigdirs;
+       /* The file system is still read-only. */
+       newfs->fs_ronly = 1;
        bcopy(newfs, fs, (u_int)fs->fs_sbsize);
        if (fs->fs_sbsize < SBSIZE)
                bp->b_flags |= B_INVAL;
@@ -501,8 +521,7 @@ ffs_reload(mp, cred, p)
                size = fs->fs_bsize;
                if (i + fs->fs_frag > blks)
                        size = (blks - i) * fs->fs_fsize;
-               error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
-                   NOCRED, &bp);
+               error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, &bp);
                if (error)
                        return (error);
                bcopy(bp->b_data, space, (u_int)size);
@@ -518,76 +537,90 @@ ffs_reload(mp, cred, p)
                        *lp++ = fs->fs_contigsumsize;
        }
 
-loop:
-       simple_lock(&mntvnode_slock);
-       for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist); vp != NULL; vp = nvp) {
-               if (vp->v_mount != mp) {
-                       simple_unlock(&mntvnode_slock);
-                       goto loop;
-               }
-               nvp = TAILQ_NEXT(vp, v_nmntvnodes);
-               /*
-                * Step 4: invalidate all inactive vnodes.
-                */
-               if (vrecycle(vp, &mntvnode_slock, p))
-                       goto loop;
-               /*
-                * Step 5: invalidate all cached file data.
-                */
-               simple_lock(&vp->v_interlock);
-               simple_unlock(&mntvnode_slock);
-               if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) {
-                       goto loop;
-               }
-               if (vinvalbuf(vp, 0, cred, p, 0, 0))
-                       panic("ffs_reload: dirty2");
-               /*
-                * Step 6: re-read inode data for all active vnodes.
-                */
-               ip = VTOI(vp);
-               error =
-                   bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
-                   (int)fs->fs_bsize, NOCRED, &bp);
-               if (error) {
-                       vput(vp);
-                       return (error);
-               }
-               ip->i_din = *((struct dinode *)bp->b_data +
-                   ino_to_fsbo(fs, ip->i_number));
-               ip->i_effnlink = ip->i_nlink;
-               brelse(bp);
+       scaninfo.rescan = 0;
+       scaninfo.fs = fs;
+       scaninfo.devvp = devvp;
+       scaninfo.td = td;
+       while (error == 0 && scaninfo.rescan) {
+               scaninfo.rescan = 0;
+               error = vmntvnodescan(mp, ffs_reload_scan1, 
+                                   ffs_reload_scan2, &scaninfo);
+       }
+       return(error);
+}
+
+static 
+int
+ffs_reload_scan1(struct mount *mp, struct vnode *vp, void *data)
+{
+       struct scaninfo *info = data;
+
+       /*
+        * Step 4: invalidate all inactive vnodes. 
+        */
+       if (vrecycle(vp, NULL, info->td)) {
+               info->rescan = 1;
+               return(-1);     /* continue loop, do not call scan2 */
+       }
+       return(0);
+}
+
+static
+int
+ffs_reload_scan2(struct mount *mp, struct vnode *vp, lwkt_tokref_t vlock, void *data)
+{
+       struct scaninfo *info = data;
+       struct inode *ip;
+       struct buf *bp;
+       int error;
+
+       /*
+        * Step 5: invalidate all cached file data.
+        */
+       if (vget(vp, vlock, LK_EXCLUSIVE | LK_INTERLOCK, info->td)) {
+               info->rescan = 1;
+               return(0);
+       }
+       if (vinvalbuf(vp, 0, info->td, 0, 0))
+               panic("ffs_reload: dirty2");
+       /*
+        * Step 6: re-read inode data for all active vnodes.
+        */
+       ip = VTOI(vp);
+       error = bread(info->devvp,
+                       fsbtodb(info->fs, ino_to_fsba(info->fs, ip->i_number)),
+                       (int)info->fs->fs_bsize, &bp);
+       if (error) {
                vput(vp);
-               simple_lock(&mntvnode_slock);
+               return (error);
        }
-       simple_unlock(&mntvnode_slock);
-       return (0);
+       ip->i_din = *((struct dinode *)bp->b_data +
+           ino_to_fsbo(info->fs, ip->i_number));
+       ip->i_effnlink = ip->i_nlink;
+       brelse(bp);
+       vput(vp);
+       return(0);
 }
 
 /*
  * Common code for mount and mountroot
  */
 int
-ffs_mountfs(devvp, mp, p, malloctype)
-       register struct vnode *devvp;
-       struct mount *mp;
-       struct proc *p;
-       struct malloc_type *malloctype;
+ffs_mountfs(struct vnode *devvp, struct mount *mp, struct thread *td,
+           struct malloc_type *malloctype)
 {
-       register struct ufsmount *ump;
+       struct ufsmount *ump;
        struct buf *bp;
-       register struct fs *fs;
+       struct fs *fs;
        dev_t dev;
        struct partinfo dpart;
        void *space;
        int error, i, blks, size, ronly;
+       lwkt_tokref vlock;
        int32_t *lp;
-       struct ucred *cred;
        u_int64_t maxfilesize;                                  /* XXX */
        size_t strsize;
-       int ncount;
 
-       dev = devvp->v_rdev;
-       cred = p ? p->p_ucred : NOCRED;
        /*
         * Disallow multiple mounts of the same device.
         * Disallow mounting of a device that is currently in use
@@ -597,13 +630,11 @@ ffs_mountfs(devvp, mp, p, malloctype)
        error = vfs_mountedon(devvp);
        if (error)
                return (error);
-       ncount = vcount(devvp);
-
-       if (ncount > 1 && devvp != rootvp)
+       if (count_udev(devvp->v_udev) > 0 && devvp != rootvp)
                return (EBUSY);
-       vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
-       error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0);
-       VOP_UNLOCK(devvp, 0, p);
+       vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
+       error = vinvalbuf(devvp, V_SAVE, td, 0, 0);
+       VOP_UNLOCK(devvp, NULL, 0, td);
        if (error)
                return (error);
 
@@ -614,31 +645,32 @@ ffs_mountfs(devvp, mp, p, malloctype)
         * increases the opportunity for metadata caching.
         */
        if (devvp->v_tag != VT_MFS && vn_isdisk(devvp, NULL)) {
-               vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
-               vfs_object_create(devvp, p, p->p_ucred);
-               simple_lock(&devvp->v_interlock);
-               VOP_UNLOCK(devvp, LK_INTERLOCK, p);
+               vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
+               vfs_object_create(devvp, td);
+               lwkt_gettoken(&vlock, devvp->v_interlock);
+               VOP_UNLOCK(devvp, &vlock, LK_INTERLOCK, td);
        }
 
        ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
-       vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
-       error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
-       VOP_UNLOCK(devvp, 0, p);
+       vn_lock(devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
+       error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, td);
+       VOP_UNLOCK(devvp, NULL, 0, td);
        if (error)
                return (error);
-       if (devvp->v_rdev->si_iosize_max != 0)
-               mp->mnt_iosize_max = devvp->v_rdev->si_iosize_max;
+       dev = devvp->v_rdev;
+       if (dev->si_iosize_max != 0)
+               mp->mnt_iosize_max = dev->si_iosize_max;
        if (mp->mnt_iosize_max > MAXPHYS)
                mp->mnt_iosize_max = MAXPHYS;
 
-       if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0)
+       if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, proc0.p_ucred, td) != 0)
                size = DEV_BSIZE;
        else
                size = dpart.disklab->d_secsize;
 
        bp = NULL;
        ump = NULL;
-       if ((error = bread(devvp, SBLOCK, SBSIZE, cred, &bp)) != 0)
+       if ((error = bread(devvp, SBLOCK, SBSIZE, &bp)) != 0)
                goto out;
        fs = (struct fs *)bp->b_data;
        if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
@@ -697,7 +729,7 @@ ffs_mountfs(devvp, mp, p, malloctype)
                if (i + fs->fs_frag > blks)
                        size = (blks - i) * fs->fs_fsize;
                if ((error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
-                   cred, &bp)) != 0) {
+                   &bp)) != 0) {
                        free(fs->fs_csp, M_UFSMNT);
                        goto out;
                }
@@ -736,7 +768,7 @@ ffs_mountfs(devvp, mp, p, malloctype)
        ump->um_seqinc = fs->fs_frag;
        for (i = 0; i < MAXQUOTAS; i++)
                ump->um_quotas[i] = NULLVP;
-       devvp->v_specmountpoint = mp;
+       dev->si_mountpoint = mp;
        ffs_oldfscompat(fs);
 
        /*
@@ -766,7 +798,7 @@ ffs_mountfs(devvp, mp, p, malloctype)
                fs->fs_maxfilesize = maxfilesize;               /* XXX */
        if (ronly == 0) {
                if ((fs->fs_flags & FS_DOSOFTDEP) &&
-                   (error = softdep_mount(devvp, mp, fs, cred)) != 0) {
+                   (error = softdep_mount(devvp, mp, fs)) != 0) {
                        free(fs->fs_csp, M_UFSMNT);
                        goto out;
                }
@@ -776,10 +808,10 @@ ffs_mountfs(devvp, mp, p, malloctype)
        }
        return (0);
 out:
-       devvp->v_specmountpoint = NULL;
+       dev->si_mountpoint = NULL;
        if (bp)
                brelse(bp);
-       (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
+       VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, td);
        if (ump) {
                free(ump->um_fs, M_UFSMNT);
                free(ump, M_UFSMNT);
@@ -794,10 +826,8 @@ out:
  * XXX - goes away some day.
  */
 static int
-ffs_oldfscompat(fs)
-       struct fs *fs;
+ffs_oldfscompat(struct fs *fs)
 {
-
        fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect);       /* XXX */
        fs->fs_interleave = max(fs->fs_interleave, 1);          /* XXX */
        if (fs->fs_postblformat == FS_42POSTBLFMT)              /* XXX */
@@ -824,13 +854,10 @@ ffs_oldfscompat(fs)
  * unmount system call
  */
 int
-ffs_unmount(mp, mntflags, p)
-       struct mount *mp;
-       int mntflags;
-       struct proc *p;
+ffs_unmount(struct mount *mp, int mntflags, struct thread *td)
 {
-       register struct ufsmount *ump;
-       register struct fs *fs;
+       struct ufsmount *ump;
+       struct fs *fs;
        int error, flags;
 
        flags = 0;
@@ -838,10 +865,10 @@ ffs_unmount(mp, mntflags, p)
                flags |= FORCECLOSE;
        }
        if (mp->mnt_flag & MNT_SOFTDEP) {
-               if ((error = softdep_flushfiles(mp, flags, p)) != 0)
+               if ((error = softdep_flushfiles(mp, flags, td)) != 0)
                        return (error);
        } else {
-               if ((error = ffs_flushfiles(mp, flags, p)) != 0)
+               if ((error = ffs_flushfiles(mp, flags, td)) != 0)
                        return (error);
        }
        ump = VFSTOUFS(mp);
@@ -854,11 +881,10 @@ ffs_unmount(mp, mntflags, p)
                        return (error);
                }
        }
-       ump->um_devvp->v_specmountpoint = NULL;
+       ump->um_devvp->v_rdev->si_mountpoint = NULL;
 
-       vinvalbuf(ump->um_devvp, V_SAVE, NOCRED, p, 0, 0);
-       error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
-               NOCRED, p);
+       vinvalbuf(ump->um_devvp, V_SAVE, td, 0, 0);
+       error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE, td);
 
        vrele(ump->um_devvp);
 
@@ -874,12 +900,9 @@ ffs_unmount(mp, mntflags, p)
  * Flush out all the files in a filesystem.
  */
 int
-ffs_flushfiles(mp, flags, p)
-       register struct mount *mp;
-       int flags;
-       struct proc *p;
+ffs_flushfiles(struct mount *mp, int flags, struct thread *td)
 {
-       register struct ufsmount *ump;
+       struct ufsmount *ump;
        int error;
 
        ump = VFSTOUFS(mp);
@@ -892,7 +915,7 @@ ffs_flushfiles(mp, flags, p)
                for (i = 0; i < MAXQUOTAS; i++) {
                        if (ump->um_quotas[i] == NULLVP)
                                continue;
-                       quotaoff(p, mp, i);
+                       quotaoff(td, mp, i);
                }
                /*
                 * Here we fall through to vflush again to ensure
@@ -908,9 +931,9 @@ ffs_flushfiles(mp, flags, p)
        /*
         * Flush filesystem metadata.
         */
-       vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
-       error = VOP_FSYNC(ump->um_devvp, p->p_ucred, MNT_WAIT, p);
-       VOP_UNLOCK(ump->um_devvp, 0, p);
+       vn_lock(ump->um_devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
+       error = VOP_FSYNC(ump->um_devvp, MNT_WAIT, td);
+       VOP_UNLOCK(ump->um_devvp, NULL, 0, td);
        return (error);
 }
 
@@ -918,13 +941,10 @@ ffs_flushfiles(mp, flags, p)
  * Get file system statistics.
  */
 int
-ffs_statfs(mp, sbp, p)
-       struct mount *mp;
-       register struct statfs *sbp;
-       struct proc *p;
+ffs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td)
 {
-       register struct ufsmount *ump;
-       register struct fs *fs;
+       struct ufsmount *ump;
+       struct fs *fs;
 
        ump = VFSTOUFS(mp);
        fs = ump->um_fs;
@@ -955,92 +975,47 @@ ffs_statfs(mp, sbp, p)
  *
  * Note: we are always called with the filesystem marked `MPBUSY'.
  */
+
+
+static int ffs_sync_scan1(struct mount *mp, struct vnode *vp, void *data);
+static int ffs_sync_scan2(struct mount *mp, struct vnode *vp,
+                lwkt_tokref_t vlock, void *data);
+
 int
-ffs_sync(mp, waitfor, cred, p)
-       struct mount *mp;
-       int waitfor;
-       struct ucred *cred;
-       struct proc *p;
+ffs_sync(struct mount *mp, int waitfor, struct thread *td)
 {
-       struct vnode *nvp, *vp;
-       struct inode *ip;
        struct ufsmount *ump = VFSTOUFS(mp);
        struct fs *fs;
-       int error, allerror = 0;
+       int error;
+       struct scaninfo scaninfo;
 
        fs = ump->um_fs;
        if (fs->fs_fmod != 0 && fs->fs_ronly != 0) {            /* XXX */
                printf("fs = %s\n", fs->fs_fsmnt);
                panic("ffs_sync: rofs mod");
        }
+
        /*
         * Write back each (modified) inode.
         */
-       simple_lock(&mntvnode_slock);
-loop:
-       for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist); vp != NULL; vp = nvp) {
-               /*
-                * If the vnode that we are about to sync is no longer
-                * associated with this mount point, start over.
-                */
-               if (vp->v_mount != mp)
-                       goto loop;
-
-               /*
-                * Depend on the mntvnode_slock to keep things stable enough
-                * for a quick test.  Since there might be hundreds of 
-                * thousands of vnodes, we cannot afford even a subroutine
-                * call unless there's a good chance that we have work to do.
-                */
-               nvp = TAILQ_NEXT(vp, v_nmntvnodes);
-               ip = VTOI(vp);
-               if (vp->v_type == VNON || ((ip->i_flag &
-                    (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
-                    TAILQ_EMPTY(&vp->v_dirtyblkhd))) {
-                       continue;
-               }
-               if (vp->v_type != VCHR) {
-                       simple_unlock(&mntvnode_slock);
-                       error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT, p);
-                       if (error) {
-                               simple_lock(&mntvnode_slock);
-                               if (error == ENOENT)
-                                       goto loop;
-                       } else {
-                               if ((error = VOP_FSYNC(vp, cred, waitfor, p)) != 0)
-                                       allerror = error;
-                               VOP_UNLOCK(vp, 0, p);
-                               vrele(vp);
-                               simple_lock(&mntvnode_slock);
-                       }
-               } else {
-                       /*
-                        * We must reference the vp to prevent it from
-                        * getting ripped out from under UFS_UPDATE, since
-                        * we are not holding a vnode lock.  XXX why aren't
-                        * we holding a vnode lock?
-                        */
-                       VREF(vp);
-                       simple_unlock(&mntvnode_slock);
-                       /* UFS_UPDATE(vp, waitfor == MNT_WAIT); */
-                       UFS_UPDATE(vp, 0);
-                       vrele(vp);
-                       simple_lock(&mntvnode_slock);
-               }
-               if (TAILQ_NEXT(vp, v_nmntvnodes) != nvp)
-                       goto loop;
+       scaninfo.allerror = 0;
+       scaninfo.rescan = 1;
+       scaninfo.waitfor = waitfor;
+       while (scaninfo.rescan) {
+               scaninfo.rescan = 0;
+               vmntvnodescan(mp, ffs_sync_scan1, ffs_sync_scan2, &scaninfo);
        }
-       simple_unlock(&mntvnode_slock);
+
        /*
         * Force stale file system control information to be flushed.
         */
        if (waitfor != MNT_LAZY) {
                if (ump->um_mountp->mnt_flag & MNT_SOFTDEP)
                        waitfor = MNT_NOWAIT;
-               vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
-               if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0)
-                       allerror = error;
-               VOP_UNLOCK(ump->um_devvp, 0, p);
+               vn_lock(ump->um_devvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
+               if ((error = VOP_FSYNC(ump->um_devvp, waitfor, td)) != 0)
+                       scaninfo.allerror = error;
+               VOP_UNLOCK(ump->um_devvp, NULL, 0, td);
        }
 #ifdef QUOTA
        qsync(mp);
@@ -1049,8 +1024,75 @@ loop:
         * Write back modified superblock.
         */
        if (fs->fs_fmod != 0 && (error = ffs_sbupdate(ump, waitfor)) != 0)
-               allerror = error;
-       return (allerror);
+               scaninfo.allerror = error;
+       return (scaninfo.allerror);
+}
+
+static
+int
+ffs_sync_scan1(struct mount *mp, struct vnode *vp, void *data)
+{
+       struct inode *ip;
+
+       /*
+        * Depend on the mount list's vnode lock to keep things stable 
+        * enough for a quick test.  Since there might be hundreds of 
+        * thousands of vnodes, we cannot afford even a subroutine
+        * call unless there's a good chance that we have work to do.
+        */
+       ip = VTOI(vp);
+       if (vp->v_type == VNON || ((ip->i_flag &
+            (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
+            TAILQ_EMPTY(&vp->v_dirtyblkhd))) {
+               return(-1);
+       }
+       return(0);
+}
+
+static
+int 
+ffs_sync_scan2(struct mount *mp, struct vnode *vp,
+              lwkt_tokref_t vlock, void *data)
+{
+       struct scaninfo *info = data;
+       thread_t td = curthread;        /* XXX */
+       struct inode *ip;
+       int error;
+
+       /*
+        * We have to recheck after having obtained the vnode interlock.
+        */
+       ip = VTOI(vp);
+       if (vp->v_type == VNON || ((ip->i_flag &
+            (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
+            TAILQ_EMPTY(&vp->v_dirtyblkhd))) {
+               lwkt_reltoken(vlock);
+               return(0);
+       }
+       if (vp->v_type != VCHR) {
+               error = vget(vp, vlock, LK_INTERLOCK|LK_EXCLUSIVE|LK_NOWAIT, td);
+               if (error) {
+                       if (error == ENOENT)
+                               info->rescan = 1;
+               } else {
+                       if ((error = VOP_FSYNC(vp, info->waitfor, td)) != 0)
+                               info->allerror = error;
+                       VOP_UNLOCK(vp, NULL, 0, td);
+                       vrele(vp);
+               }
+       } else {
+               /*
+                * We must reference the vp to prevent it from
+                * getting ripped out from under UFS_UPDATE, since
+                * we are not holding a vnode lock.
+                */
+               vref(vp);
+               lwkt_reltoken(vlock);
+               /* UFS_UPDATE(vp, waitfor == MNT_WAIT); */
+               UFS_UPDATE(vp, 0);
+               vrele(vp);
+       }
+       return(0);
 }
 
 /*
@@ -1062,10 +1104,7 @@ loop:
 static int ffs_inode_hash_lock;
 
 int
-ffs_vget(mp, ino, vpp)
-       struct mount *mp;
-       ino_t ino;
-       struct vnode **vpp;
+ffs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
 {
        struct fs *fs;
        struct inode *ip;
@@ -1090,7 +1129,7 @@ restart:
        if (ffs_inode_hash_lock) {
                while (ffs_inode_hash_lock) {
                        ffs_inode_hash_lock = -1;
-                       tsleep(&ffs_inode_hash_lock, PVM, "ffsvgt", 0);
+                       tsleep(&ffs_inode_hash_lock, 0, "ffsvgt", 0);
                }
                goto restart;
        }
@@ -1117,7 +1156,7 @@ restart:
                return (error);
        }
        bzero((caddr_t)ip, sizeof(struct inode));
-       lockinit(&ip->i_lock, PINOD, "inode", VLKTIMEOUT, LK_CANRECURSE);
+       lockinit(&ip->i_lock, 0, "inode", VLKTIMEOUT, LK_CANRECURSE);
        vp->v_data = ip;
        /*
         * FFS supports lock sharing in the stack of vnodes
@@ -1148,7 +1187,7 @@ restart:
 
        /* Read in the disk contents for the inode, copy into the inode. */
        error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
-           (int)fs->fs_bsize, NOCRED, &bp);
+           (int)fs->fs_bsize, &bp);
        if (error) {
                /*
                 * The inode does not contain anything useful, so it would
@@ -1182,7 +1221,7 @@ restart:
         * Finish inode initialization now that aliasing has been resolved.
         */
        ip->i_devvp = ump->um_devvp;
-       VREF(ip->i_devvp);
+       vref(ip->i_devvp);
        /*
         * Set up a generation number for this inode if it does not
         * already have one. This should only happen on old filesystems.
@@ -1216,12 +1255,9 @@ restart:
  *   those rights via. exflagsp and credanonp
  */
 int
-ffs_fhtovp(mp, fhp, vpp)
-       register struct mount *mp;
-       struct fid *fhp;
-       struct vnode **vpp;
+ffs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
 {
-       register struct ufid *ufhp;
+       struct ufid *ufhp;
        struct fs *fs;
 
        ufhp = (struct ufid *)fhp;
@@ -1237,12 +1273,10 @@ ffs_fhtovp(mp, fhp, vpp)
  */
 /* ARGSUSED */
 int
-ffs_vptofh(vp, fhp)
-       struct vnode *vp;
-       struct fid *fhp;
+ffs_vptofh(struct vnode *vp, struct fid *fhp)
 {
-       register struct inode *ip;
-       register struct ufid *ufhp;
+       struct inode *ip;
+       struct ufid *ufhp;
 
        ip = VTOI(vp);
        ufhp = (struct ufid *)fhp;
@@ -1256,10 +1290,8 @@ ffs_vptofh(vp, fhp)
  * Initialize the filesystem; just use ufs_init.
  */
 static int
-ffs_init(vfsp)
-       struct vfsconf *vfsp;
+ffs_init(struct vfsconf *vfsp)
 {
-
        softdep_initialize();
        return (ufs_init(vfsp));
 }
@@ -1268,12 +1300,10 @@ ffs_init(vfsp)
  * Write a superblock and associated information back to disk.
  */
 static int
-ffs_sbupdate(mp, waitfor)
-       struct ufsmount *mp;
-       int waitfor;
+ffs_sbupdate(struct ufsmount *mp, int waitfor)
 {
-       register struct fs *dfs, *fs = mp->um_fs;
-       register struct buf *bp;
+       struct fs *dfs, *fs = mp->um_fs;
+       struct buf *bp;
        int blks;
        void *space;
        int i, size, error, allerror = 0;