* Copyright (c) 1982, 1986, 1990, 1993
* The Regents of the University of California. All rights reserved.
* %sccs.include.proprietary.c%
* @(#)kern_physio.c 8.1 (Berkeley) %G%
static void freeswbuf
__P((struct buf
*));
static struct buf
*getswbuf
__P((int));
* This routine does device I/O for a user process.
* If the user has the proper access privileges, the process is
* marked 'delayed unlock' and the pages involved in the I/O are
* faulted and locked. After the completion of the I/O, the pages
physio(strat
, bp
, dev
, rw
, mincnt
, uio
)
register struct iovec
*iov
;
register int requested
= 0, done
= 0;
register struct proc
*p
= curproc
;
int s
, allocbuf
= 0, error
= 0;
if ((unsigned)major(dev
) < nchrdev
&&
(*cdevsw
[major(dev
)].d_ioctl
)(dev
, DIOCGPART
, (caddr_t
)&dpart
,
bsize
= dpart
.disklab
->d_secsize
;
if (uio
->uio_iovcnt
== 0)
if (useracc(iov
->iov_base
, (u_int
)iov
->iov_len
,
rw
==B_READ
? B_WRITE
: B_READ
) == NULL
)
while (bp
->b_flags
&B_BUSY
) {
sleep((caddr_t
)bp
, PRIBIO
+1);
if (!allocbuf
) { /* only if sharing caller's buffer */
while (bp
->b_flags
&B_BUSY
) {
sleep((caddr_t
)bp
, PRIBIO
+1);
bp
->b_un
.b_addr
= iov
->iov_base
;
while (iov
->iov_len
> 0) {
bp
->b_flags
= B_BUSY
| B_PHYS
| rw
;
bp
->b_blkno
= uio
->uio_offset
/ bsize
;
bp
->b_blkno
= btodb(uio
->uio_offset
);
bp
->b_bcount
= iov
->iov_len
;
u
.u_procp
->p_flag
|= SPHYSIO
;
vslock(a
= bp
->b_un
.b_addr
, c
);
physstrat(bp
, strat
, PRIBIO
);
u
.u_procp
->p_flag
&= ~SPHYSIO
;
if (bp
->b_flags
&B_WANTED
)
/* temp kludge for tape drives */
if (bp
->b_resid
|| (bp
->b_flags
&B_ERROR
))
bp
->b_flags
&= ~(B_BUSY
|B_WANTED
|B_PHYS
);
if (bp
->b_resid
|| error
)
* Calculate the maximum size of I/O request that can be requested
* in a single operation. This limit is necessary to prevent a single
* process from being able to lock more than a fixed amount of memory
if (bp
->b_bcount
> MAXPHYS
)
while (bswlist
.b_actf
== NULL
) {
bswlist
.b_flags
|= B_WANTED
;
sleep((caddr_t
)&bswlist
, prio
);
bswlist
.b_actf
= bp
->b_actf
;
bp
->b_actf
= bswlist
.b_actf
;
if (bswlist
.b_flags
& B_WANTED
) {
bswlist
.b_flags
&= ~B_WANTED
;
wakeup((caddr_t
)&bswlist
);
wakeup((caddr_t
)pageproc
);
* Do a read on a device for a user process.
return (physio(cdevsw
[major(dev
)].d_strategy
, (struct buf
*)NULL
,
dev
, B_READ
, minphys
, uio
));
* Do a write on a device for a user process.
return (physio(cdevsw
[major(dev
)].d_strategy
, (struct buf
*)NULL
,
dev
, B_WRITE
, minphys
, uio
));