summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_physio.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/kern_physio.c')
-rw-r--r--sys/kern/kern_physio.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/sys/kern/kern_physio.c b/sys/kern/kern_physio.c
index ab9c344..88cd0cf 100644
--- a/sys/kern/kern_physio.c
+++ b/sys/kern/kern_physio.c
@@ -54,6 +54,36 @@ physio(struct cdev *dev, struct uio *uio, int ioflag)
dev->si_iosize_max = DFLTPHYS;
}
+ /*
+ * If the driver does not want I/O to be split, that means that we
+ * need to reject any requests that will not fit into one buffer.
+ */
+ if ((dev->si_flags & SI_NOSPLIT) &&
+ ((uio->uio_resid > dev->si_iosize_max) ||
+ (uio->uio_resid > MAXPHYS) ||
+ (uio->uio_iovcnt > 1))) {
+ /*
+ * Tell the user why his I/O was rejected.
+ */
+ if (uio->uio_resid > dev->si_iosize_max)
+ printf("%s: request size %zd > si_iosize_max=%d, "
+ "cannot split request\n", devtoname(dev),
+ uio->uio_resid, dev->si_iosize_max);
+
+ if (uio->uio_resid > MAXPHYS)
+ printf("%s: request size %zd > MAXPHYS=%d, "
+ "cannot split request\n", devtoname(dev),
+ uio->uio_resid, MAXPHYS);
+
+ if (uio->uio_iovcnt > 1)
+ printf("%s: request vectors=%d > 1, "
+ "cannot split request\n", devtoname(dev),
+ uio->uio_iovcnt);
+
+ error = EFBIG;
+ goto doerror;
+ }
+
for (i = 0; i < uio->uio_iovcnt; i++) {
while (uio->uio_iov[i].iov_len) {
bp->b_flags = 0;
@@ -83,6 +113,17 @@ physio(struct cdev *dev, struct uio *uio, int ioflag)
*/
iolen = ((vm_offset_t) bp->b_data) & PAGE_MASK;
if ((bp->b_bcount + iolen) > bp->b_kvasize) {
+ /*
+ * This device does not want I/O to be split.
+ */
+ if (dev->si_flags & SI_NOSPLIT) {
+ printf("%s: request ptr %#jx is not "
+ "on a page boundary, cannot split "
+ "request\n", devtoname(dev),
+ (uintmax_t)bp->b_data);
+ error = EFBIG;
+ goto doerror;
+ }
bp->b_bcount = bp->b_kvasize;
if (iolen != 0)
bp->b_bcount -= PAGE_SIZE;
OpenPOWER on IntegriCloud