Author: kan
Date: Tue Mar 26 01:17:06 2013
New Revision: 248712
URL: http://svnweb.freebsd.org/changeset/base/248712

Log:
  Do not pass unmapped buffers to drivers that cannot handle them
  
  In physio, check if device can handle unmapped IO and pass an
  appropriately mapped buffer to the driver strategy routine. The
  only driver in the tree that can handle unmapped buffers is one
  exposed by GEOM, so mark it as such with the new flag in the
  driver cdevsw structure.
  
  This fixes insta-panics on hosts, running dconschat, as /dev/fwmem
  is an example of the driver that makes use of physio routine, but
  bypasses the g_down thread, where the buffer gets mapped normally.
  
  Discussed with: kib (earlier version)

Modified:
  head/sys/geom/geom_dev.c
  head/sys/kern/kern_physio.c
  head/sys/sys/conf.h

Modified: head/sys/geom/geom_dev.c
==============================================================================
--- head/sys/geom/geom_dev.c    Mon Mar 25 23:38:01 2013        (r248711)
+++ head/sys/geom/geom_dev.c    Tue Mar 26 01:17:06 2013        (r248712)
@@ -78,7 +78,7 @@ static struct cdevsw g_dev_cdevsw = {
        .d_ioctl =      g_dev_ioctl,
        .d_strategy =   g_dev_strategy,
        .d_name =       "g_dev",
-       .d_flags =      D_DISK | D_TRACKCLOSE,
+       .d_flags =      D_DISK | D_TRACKCLOSE | D_UNMAPPED_IO,
 };
 
 static g_taste_t g_dev_taste;

Modified: head/sys/kern/kern_physio.c
==============================================================================
--- head/sys/kern/kern_physio.c Mon Mar 25 23:38:01 2013        (r248711)
+++ head/sys/kern/kern_physio.c Tue Mar 26 01:17:06 2013        (r248712)
@@ -91,11 +91,21 @@ physio(struct cdev *dev, struct uio *uio
 
                        bp->b_blkno = btodb(bp->b_offset);
 
-                       if (uio->uio_segflg == UIO_USERSPACE)
-                               if (vmapbuf(bp, 0) < 0) {
+                       if (uio->uio_segflg == UIO_USERSPACE) {
+                               struct cdevsw *csw;
+                               int mapped;
+
+                               csw = dev->si_devsw;
+                               if (csw != NULL &&
+                                    (csw->d_flags & D_UNMAPPED_IO) != 0)
+                                       mapped = 0;
+                               else
+                                       mapped = 1;
+                               if (vmapbuf(bp, mapped) < 0) {
                                        error = EFAULT;
                                        goto doerror;
                                }
+                       }
 
                        dev_strategy(dev, bp);
                        if (uio->uio_rw == UIO_READ)

Modified: head/sys/sys/conf.h
==============================================================================
--- head/sys/sys/conf.h Mon Mar 25 23:38:01 2013        (r248711)
+++ head/sys/sys/conf.h Tue Mar 26 01:17:06 2013        (r248712)
@@ -167,6 +167,7 @@ typedef int dumper_t(
 #define        D_MMAP_ANON     0x00100000      /* special treatment in 
vm_mmap.c */
 #define        D_NEEDGIANT     0x00400000      /* driver want Giant */
 #define        D_NEEDMINOR     0x00800000      /* driver uses clone_create() */
+#define        D_UNMAPPED_IO   0x01000000      /* d_strategy can accept 
unmapped IO */
 
 /*
  * Version numbers.
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to