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)
This commit is contained in:
Alexander Kabaev 2013-03-26 01:17:06 +00:00
parent 5472787377
commit 31932fae1e
3 changed files with 14 additions and 3 deletions

View File

@ -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;

View File

@ -91,11 +91,21 @@ physio(struct cdev *dev, struct uio *uio, int ioflag)
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)

View File

@ -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.