Change the kernel dev_t, representing a pointer to a specinfo structure,
[dragonfly.git] / sys / vfs / mfs / mfs_vfsops.c
index 2645393..3f9ec17 100644 (file)
  *
  *     @(#)mfs_vfsops.c        8.11 (Berkeley) 6/19/95
  * $FreeBSD: src/sys/ufs/mfs/mfs_vfsops.c,v 1.81.2.3 2001/07/04 17:35:21 tegge Exp $
- * $DragonFly: src/sys/vfs/mfs/mfs_vfsops.c,v 1.23 2005/07/26 15:43:35 hmp Exp $
+ * $DragonFly: src/sys/vfs/mfs/mfs_vfsops.c,v 1.35 2006/09/10 01:26:41 dillon Exp $
  */
 
 
-#include "opt_mfs.h"
-
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/conf.h>
+#include <sys/device.h>
 #include <sys/kernel.h>
 #include <sys/proc.h>
 #include <sys/buf.h>
 #include <sys/linker.h>
 #include <sys/fcntl.h>
 
-#include <sys/buf2.h>
+#include <vm/vm.h>
+#include <vm/vm_object.h>
+#include <vm/vm_page.h>
+#include <vm/vm_pager.h>
+#include <vm/vnode_pager.h>
 
+#include <sys/buf2.h>
 #include <sys/thread2.h>
 
 #include <vfs/ufs/quota.h>
 
 MALLOC_DEFINE(M_MFSNODE, "MFS node", "MFS vnode private part");
 
-
-extern struct vop_ops *mfs_vnode_vops;
+extern struct vop_ops *mfs_vnode_vops_p;
 
 static int     mfs_mount (struct mount *mp,
-                       char *path, caddr_t data, struct thread *td);
-static int     mfs_start (struct mount *mp, int flags, struct thread *td);
-static int     mfs_statfs (struct mount *mp, struct statfs *sbp, 
-                       struct thread *td);
+                       char *path, caddr_t data, struct ucred *td);
+static int     mfs_start (struct mount *mp, int flags);
+static int     mfs_statfs (struct mount *mp, struct statfs *sbp,
+                       struct ucred *cred); 
 static int     mfs_init (struct vfsconf *);
 
 d_open_t       mfsopen;
@@ -83,23 +86,13 @@ d_strategy_t        mfsstrategy;
 
 #define MFS_CDEV_MAJOR 253
 
-static struct cdevsw mfs_cdevsw = {
-       /* name */      "MFS",
-       /* maj */       MFS_CDEV_MAJOR,
-       /* flags */     D_DISK,
-       /* port */      NULL,
-       /* clone */     NULL,
-
-       /* open */      mfsopen,
-       /* close */     mfsclose,
-       /* read */      physread,
-       /* write */     physwrite,
-       /* ioctl */     noioctl,
-       /* poll */      nopoll,
-       /* mmap */      nommap,
-       /* strategy */  mfsstrategy,
-       /* dump */      nodump,
-       /* psize */     nopsize
+static struct dev_ops mfs_ops = {
+       { "MFS", MFS_CDEV_MAJOR, D_DISK },
+       .d_open =       mfsopen,
+       .d_close =      mfsclose,
+       .d_read =       physread,
+       .d_write =      physwrite,
+       .d_strategy =   mfsstrategy,
 };
 
 /*
@@ -126,9 +119,11 @@ VFS_SET(mfs_vfsops, mfs, 0);
  * We allow the underlying MFS block device to be opened and read.
  */
 int
-mfsopen(dev_t dev, int flags, int mode, struct thread *td)
+mfsopen(struct dev_open_args *ap)
 {
-       if (flags & FWRITE)
+       cdev_t dev = ap->a_head.a_dev;
+
+       if (ap->a_oflags & FWRITE)
                return(EROFS);
        if (dev->si_drv1)
                return(0);
@@ -136,39 +131,60 @@ mfsopen(dev_t dev, int flags, int mode, struct thread *td)
 }
 
 int
-mfsclose(dev_t dev, int flags, int mode, struct thread *td)
+mfsclose(struct dev_close_args *ap)
 {
        return(0);
 }
 
-void
-mfsstrategy(struct buf *bp)
+int
+mfsstrategy(struct dev_strategy_args *ap)
 {
+       cdev_t dev = ap->a_head.a_dev;
+       struct bio *bio = ap->a_bio;
+       struct buf *bp = bio->bio_buf;
+       off_t boff = bio->bio_offset;
+       off_t eoff = boff + bp->b_bcount;
        struct mfsnode *mfsp;
 
-       if ((mfsp = bp->b_dev->si_drv1) != NULL) {
-               off_t boff = (off_t)bp->b_blkno << DEV_BSHIFT;
-               off_t eoff = boff + bp->b_bcount;
-
-               if (eoff <= mfsp->mfs_size) {
-                       bufq_insert_tail(&mfsp->buf_queue, bp);
-                       wakeup((caddr_t)mfsp);
-               } else if (boff < mfsp->mfs_size) {
-                       bp->b_bcount = mfsp->mfs_size - boff;
-                       bufq_insert_tail(&mfsp->buf_queue, bp);
-                       wakeup((caddr_t)mfsp);
-               } else if (boff == mfsp->mfs_size) {
+       if ((mfsp = dev->si_drv1) == NULL) {
+               bp->b_error = ENXIO;
+               goto error;
+       }
+       if (boff < 0)
+               goto bad;
+       if (eoff > mfsp->mfs_size) {
+               if (boff > mfsp->mfs_size || (bp->b_flags & B_BNOCLIP))
+                       goto bad;
+               /*
+                * Return EOF by completing the I/O with 0 bytes transfered.
+                * Set B_INVAL to indicate that any data in the buffer is not
+                * valid.
+                */
+               if (boff == mfsp->mfs_size) {
                        bp->b_resid = bp->b_bcount;
-                       biodone(bp);
-               } else {
-                       bp->b_error = EINVAL;
-                       biodone(bp);
+                       bp->b_flags |= B_INVAL;
+                       goto done;
                }
-       } else {
-               bp->b_error = ENXIO;
-               bp->b_flags |= B_ERROR;
-               biodone(bp);
+               bp->b_bcount = mfsp->mfs_size - boff;
        }
+
+       /*
+        * Initiate I/O
+        */
+       bioq_insert_tail(&mfsp->bio_queue, bio);
+       wakeup((caddr_t)mfsp);
+       return(0);
+
+       /*
+        * Failure conditions on bio
+        */
+bad:
+       bp->b_error = EINVAL;
+error:
+       bp->b_flags |= B_ERROR | B_INVAL;
+done:
+       biodone(bio);
+       return(0);
 }
 
 /*
@@ -210,7 +226,7 @@ mfsstrategy(struct buf *bp)
  */
 /* ARGSUSED */
 static int
-mfs_mount(struct mount *mp, char *path, caddr_t data, struct thread *td)
+mfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
 {
        struct vnode *devvp;
        struct mfs_args args;
@@ -220,7 +236,7 @@ mfs_mount(struct mount *mp, char *path, caddr_t data, struct thread *td)
        size_t size;
        int flags, err;
        int minnum;
-       dev_t dev;
+       cdev_t dev;
 
        /*
         * Use NULL path to flag a root mount
@@ -262,12 +278,14 @@ mfs_mount(struct mount *mp, char *path, caddr_t data, struct thread *td)
                        flags = WRITECLOSE;
                        if (mp->mnt_flag & MNT_FORCE)
                                flags |= FORCECLOSE;
-                       err = ffs_flushfiles(mp, flags, td);
+                       err = ffs_flushfiles(mp, flags);
                        if (err)
                                goto error_1;
                }
-               if (fs->fs_ronly && (mp->mnt_kern_flag & MNTK_WANTRDWR))
+               if (fs->fs_ronly && (mp->mnt_kern_flag & MNTK_WANTRDWR)) {
+                       /* XXX reopen the device vnode read-write */
                        fs->fs_ronly = 0;
+               }
                /* if not updating name...*/
                if (args.fspec == 0) {
                        /*
@@ -288,7 +306,7 @@ mfs_mount(struct mount *mp, char *path, caddr_t data, struct thread *td)
         */
        MALLOC(mfsp, struct mfsnode *, sizeof *mfsp, M_MFSNODE, M_WAITOK);
 
-       err = getspecialvnode(VT_MFS, NULL, &mfs_vnode_vops, &devvp, 0, 0);
+       err = getspecialvnode(VT_MFS, NULL, &mfs_vnode_vops_p, &devvp, 0, 0);
        if (err) {
                FREE(mfsp, M_MFSNODE);
                goto error_1;
@@ -298,7 +316,7 @@ mfs_mount(struct mount *mp, char *path, caddr_t data, struct thread *td)
                ((curproc->p_pid & ~0xFF) << 8);
 
        devvp->v_type = VCHR;
-       dev = make_dev(&mfs_cdevsw, minnum, UID_ROOT, GID_WHEEL, 0600,
+       dev = make_dev(&mfs_ops, minnum, UID_ROOT, GID_WHEEL, 0600,
                        "MFS%d", minnum >> 16);
        /* It is not clear that these will get initialized otherwise */
        dev->si_bsize_phys = DEV_BSIZE;
@@ -310,9 +328,24 @@ mfs_mount(struct mount *mp, char *path, caddr_t data, struct thread *td)
        mfsp->mfs_size = args.size;
        mfsp->mfs_vnode = devvp;
        mfsp->mfs_dev = reference_dev(dev);
-       mfsp->mfs_td = td;
+       mfsp->mfs_td = curthread;
        mfsp->mfs_active = 1;
-       bufq_init(&mfsp->buf_queue);
+       bioq_init(&mfsp->bio_queue);
+
+       /*
+        * Our 'block' device must be backed by a VM object.  Theoretically
+        * we could use the anonymous memory VM object supplied by userland,
+        * but it would be somewhat of a complex task to deal with it
+        * that way since it would result in I/O requests which supply
+        * the VM pages from our own object.
+        *
+        * vnode_pager_alloc() is typically called when a VM object is
+        * being referenced externally.  We have to undo the refs for
+        * the self reference between vnode and object.
+        */
+       vnode_pager_alloc(devvp, args.size, 0, 0);
+       --devvp->v_usecount;
+       --devvp->v_object->ref_count;
 
        /* Save "mounted from" info for mount point (NULL pad)*/
        copyinstr(      args.fspec,                     /* device name*/
@@ -322,7 +355,7 @@ mfs_mount(struct mount *mp, char *path, caddr_t data, struct thread *td)
        bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
 
        vx_unlock(devvp);
-       if ((err = ffs_mountfs(devvp, mp, td, M_MFSNODE)) != 0) { 
+       if ((err = ffs_mountfs(devvp, mp, M_MFSNODE)) != 0) { 
                mfsp->mfs_active = 0;
                goto error_2;
        }
@@ -333,7 +366,7 @@ mfs_mount(struct mount *mp, char *path, caddr_t data, struct thread *td)
         *
         * This code is common to root and non-root mounts
         */
-       (void) VFS_STATFS(mp, &mp->mnt_stat, td);
+       VFS_STATFS(mp, &mp->mnt_stat, cred);
 
        goto success;
 
@@ -358,12 +391,14 @@ success:
  */
 /* ARGSUSED */
 static int
-mfs_start(struct mount *mp, int flags, struct thread *td)
+mfs_start(struct mount *mp, int flags)
 {
        struct vnode *vp = VFSTOUFS(mp)->um_devvp;
        struct mfsnode *mfsp = VTOMFS(vp);
+       struct bio *bio;
        struct buf *bp;
        int gotsig = 0, sig;
+       thread_t td = curthread;
 
        /*
         * We must prevent the system from trying to swap
@@ -375,15 +410,17 @@ mfs_start(struct mount *mp, int flags, struct thread *td)
        KKASSERT(curproc);
        PHOLD(curproc);
 
-       while (mfsp->mfs_active) {
+       mfsp->mfs_td = td;
 
+       while (mfsp->mfs_active) {
                crit_enter();
 
-               while ((bp = bufq_first(&mfsp->buf_queue)) != NULL) {
-                       bufq_remove(&mfsp->buf_queue, bp);
+               while ((bio = bioq_first(&mfsp->bio_queue)) != NULL) {
+                       bioq_remove(&mfsp->bio_queue, bio);
                        crit_exit();
-                       mfs_doio(bp, mfsp);
-                       wakeup((caddr_t)bp);
+                       bp = bio->bio_buf;
+                       mfs_doio(bio, mfsp);
+                       wakeup(bp);
                        crit_enter();
                }
 
@@ -402,7 +439,7 @@ mfs_start(struct mount *mp, int flags, struct thread *td)
                 */
                if (gotsig) {
                        gotsig = 0;
-                       if (dounmount(mp, 0, td) != 0) {
+                       if (dounmount(mp, 0) != 0) {
                                KKASSERT(td->td_proc);
                                sig = CURSIG(td->td_proc);
                                if (sig)
@@ -422,11 +459,11 @@ mfs_start(struct mount *mp, int flags, struct thread *td)
  * Get file system statistics.
  */
 static int
-mfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td)
+mfs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
 {
        int error;
 
-       error = ffs_statfs(mp, sbp, td);
+       error = ffs_statfs(mp, sbp, cred);
        sbp->f_type = mp->mnt_vfc->vfc_typenum;
        return (error);
 }
@@ -437,6 +474,6 @@ mfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td)
 static int
 mfs_init(struct vfsconf *vfsp)
 {
-       cdevsw_add(&mfs_cdevsw, 0, 0);
+       dev_ops_add(&mfs_ops, 0, 0);
        return (0);
 }