126f9a767SRodney W. Grimes /* 226f9a767SRodney W. Grimes * Copyright (c) 1994 John S. Dyson 326f9a767SRodney W. Grimes * All rights reserved. 4df8bae1dSRodney W. Grimes * 5df8bae1dSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 6df8bae1dSRodney W. Grimes * modification, are permitted provided that the following conditions 7df8bae1dSRodney W. Grimes * are met: 8df8bae1dSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 926f9a767SRodney W. Grimes * notice immediately at the beginning of the file, without modification, 1026f9a767SRodney W. Grimes * this list of conditions, and the following disclaimer. 11df8bae1dSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 12df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 13df8bae1dSRodney W. Grimes * documentation and/or other materials provided with the distribution. 1426f9a767SRodney W. Grimes * 3. Absolutely no warranty of function or purpose is made by the author 1526f9a767SRodney W. Grimes * John S. Dyson. 1626f9a767SRodney W. Grimes * 4. Modifications may be freely made to this file if the above conditions 1726f9a767SRodney W. Grimes * are met. 183c4dd356SDavid Greenman * 19c3aac50fSPeter Wemm * $FreeBSD$ 20df8bae1dSRodney W. Grimes */ 21df8bae1dSRodney W. Grimes 22df8bae1dSRodney W. Grimes #include <sys/param.h> 23df8bae1dSRodney W. Grimes #include <sys/systm.h> 249626b608SPoul-Henning Kamp #include <sys/bio.h> 25df8bae1dSRodney W. Grimes #include <sys/buf.h> 26df8bae1dSRodney W. Grimes #include <sys/conf.h> 27df8bae1dSRodney W. Grimes #include <sys/proc.h> 2808637435SBruce Evans #include <sys/uio.h> 2908637435SBruce Evans 3026f9a767SRodney W. Grimes #include <vm/vm.h> 31efeaf95aSDavid Greenman #include <vm/vm_extern.h> 32df8bae1dSRodney W. Grimes 337179e74fSPoul-Henning Kamp static void 347179e74fSPoul-Henning Kamp physwakeup(struct buf *bp) 35c48d1775SPoul-Henning Kamp { 367f05b035SAlfred Perlstein wakeup(bp); 37c48d1775SPoul-Henning Kamp } 38c48d1775SPoul-Henning Kamp 39c48d1775SPoul-Henning Kamp int 407179e74fSPoul-Henning Kamp physio(dev_t dev, struct uio *uio, int ioflag) 41df8bae1dSRodney W. Grimes { 4226f9a767SRodney W. Grimes int i; 4326f9a767SRodney W. Grimes int error; 4426f9a767SRodney W. Grimes int spl; 4516f62314SDavid Greenman caddr_t sa; 467179e74fSPoul-Henning Kamp u_int iolen; 477179e74fSPoul-Henning Kamp struct buf *bp; 48df8bae1dSRodney W. Grimes 497179e74fSPoul-Henning Kamp /* Keep the process UPAGES from being swapped. XXX: why ? */ 5057dc5948SPeter Wemm PHOLD(curproc); 5126f9a767SRodney W. Grimes 527179e74fSPoul-Henning Kamp bp = getpbuf(NULL); 537179e74fSPoul-Henning Kamp sa = bp->b_data; 5426f9a767SRodney W. Grimes error = bp->b_error = 0; 5526f9a767SRodney W. Grimes 567179e74fSPoul-Henning Kamp /* XXX: sanity check */ 577179e74fSPoul-Henning Kamp if(dev->si_iosize_max < PAGE_SIZE) { 587179e74fSPoul-Henning Kamp printf("WARNING: %s si_iosize_max=%d, using DFLTPHYS.\n", 597179e74fSPoul-Henning Kamp devtoname(dev), dev->si_iosize_max); 607179e74fSPoul-Henning Kamp dev->si_iosize_max = DFLTPHYS; 617179e74fSPoul-Henning Kamp } 627179e74fSPoul-Henning Kamp 6326f9a767SRodney W. Grimes for (i = 0; i < uio->uio_iovcnt; i++) { 6426f9a767SRodney W. Grimes while (uio->uio_iov[i].iov_len) { 6521144e3bSPoul-Henning Kamp bp->b_flags = B_PHYS; 667179e74fSPoul-Henning Kamp if (uio->uio_rw == UIO_READ) 6721144e3bSPoul-Henning Kamp bp->b_iocmd = BIO_READ; 687179e74fSPoul-Henning Kamp else 6921144e3bSPoul-Henning Kamp bp->b_iocmd = BIO_WRITE; 7050ce7ff4SJohn Dyson bp->b_dev = dev; 714b83b27fSJohn Dyson bp->b_iodone = physwakeup; 724b83b27fSJohn Dyson bp->b_data = uio->uio_iov[i].iov_base; 737179e74fSPoul-Henning Kamp bp->b_bcount = uio->uio_iov[i].iov_len; 747179e74fSPoul-Henning Kamp bp->b_offset = uio->uio_offset; 7516f62314SDavid Greenman bp->b_saveaddr = sa; 767179e74fSPoul-Henning Kamp 777179e74fSPoul-Henning Kamp /* Don't exceed drivers iosize limit */ 787179e74fSPoul-Henning Kamp if (bp->b_bcount > dev->si_iosize_max) 797179e74fSPoul-Henning Kamp bp->b_bcount = dev->si_iosize_max; 807179e74fSPoul-Henning Kamp 817179e74fSPoul-Henning Kamp /* 827179e74fSPoul-Henning Kamp * Make sure the pbuf can map the request 837179e74fSPoul-Henning Kamp * XXX: The pbuf has kvasize = MAXPHYS so a request 847179e74fSPoul-Henning Kamp * XXX: larger than MAXPHYS - PAGE_SIZE must be 857179e74fSPoul-Henning Kamp * XXX: page aligned or it will be fragmented. 867179e74fSPoul-Henning Kamp */ 877179e74fSPoul-Henning Kamp iolen = ((vm_offset_t) bp->b_data) & PAGE_MASK; 887179e74fSPoul-Henning Kamp if ((bp->b_bcount + iolen) > bp->b_kvasize) { 897179e74fSPoul-Henning Kamp bp->b_bcount = bp->b_kvasize; 907179e74fSPoul-Henning Kamp if (iolen != 0) 917179e74fSPoul-Henning Kamp bp->b_bcount -= PAGE_SIZE; 927179e74fSPoul-Henning Kamp } 937179e74fSPoul-Henning Kamp bp->b_bufsize = bp->b_bcount; 947179e74fSPoul-Henning Kamp 95e96d018dSPoul-Henning Kamp bp->b_blkno = btodb(bp->b_offset); 9626f9a767SRodney W. Grimes 976884d2aaSPeter Wemm if (uio->uio_segflg == UIO_USERSPACE) { 982d5c7e45SMatthew Dillon /* 992d5c7e45SMatthew Dillon * Note that useracc() alone is not a 1002d5c7e45SMatthew Dillon * sufficient test. vmapbuf() can still fail 1012d5c7e45SMatthew Dillon * due to a smaller file mapped into a larger 1022d5c7e45SMatthew Dillon * area of VM, or if userland races against 1032d5c7e45SMatthew Dillon * vmapbuf() after the useracc() check. 1042d5c7e45SMatthew Dillon */ 1057179e74fSPoul-Henning Kamp if (!useracc(bp->b_data, bp->b_bufsize, 10621144e3bSPoul-Henning Kamp bp->b_iocmd == BIO_READ ? 10702c58685SPoul-Henning Kamp VM_PROT_WRITE : VM_PROT_READ)) { 10826f9a767SRodney W. Grimes error = EFAULT; 10926f9a767SRodney W. Grimes goto doerror; 11026f9a767SRodney W. Grimes } 1112d5c7e45SMatthew Dillon if (vmapbuf(bp) < 0) { 1122d5c7e45SMatthew Dillon error = EFAULT; 1132d5c7e45SMatthew Dillon goto doerror; 1142d5c7e45SMatthew Dillon } 1156884d2aaSPeter Wemm } 11626f9a767SRodney W. Grimes 117e2a3ea1cSPoul-Henning Kamp DEV_STRATEGY(bp); 11826f9a767SRodney W. Grimes spl = splbio(); 11926f9a767SRodney W. Grimes while ((bp->b_flags & B_DONE) == 0) 1207f05b035SAlfred Perlstein tsleep(bp, PRIBIO, "physstr", 0); 12126f9a767SRodney W. Grimes splx(spl); 12226f9a767SRodney W. Grimes 1236884d2aaSPeter Wemm if (uio->uio_segflg == UIO_USERSPACE) 12426f9a767SRodney W. Grimes vunmapbuf(bp); 1257179e74fSPoul-Henning Kamp iolen = bp->b_bcount - bp->b_resid; 126c244d2deSPoul-Henning Kamp if (iolen == 0 && !(bp->b_ioflags & BIO_ERROR)) 1277d7bb69dSDavid Greenman goto doerror; /* EOF */ 12826f9a767SRodney W. Grimes uio->uio_iov[i].iov_len -= iolen; 1292b7f24d2SMike Barcroft uio->uio_iov[i].iov_base = 1302b7f24d2SMike Barcroft (char *)uio->uio_iov[i].iov_base + iolen; 13126f9a767SRodney W. Grimes uio->uio_resid -= iolen; 13226f9a767SRodney W. Grimes uio->uio_offset += iolen; 133c244d2deSPoul-Henning Kamp if( bp->b_ioflags & BIO_ERROR) { 13426f9a767SRodney W. Grimes error = bp->b_error; 13526f9a767SRodney W. Grimes goto doerror; 13626f9a767SRodney W. Grimes } 13726f9a767SRodney W. Grimes } 13826f9a767SRodney W. Grimes } 13926f9a767SRodney W. Grimes doerror: 1407179e74fSPoul-Henning Kamp relpbuf(bp, NULL); 14157dc5948SPeter Wemm PRELE(curproc); 14226f9a767SRodney W. Grimes return (error); 143df8bae1dSRodney W. Grimes } 144