xref: /csrg-svn/sys/kern/kern_physio.c (revision 63174)
149589Sbostic /*-
2*63174Sbostic  * Copyright (c) 1982, 1986, 1990, 1993
3*63174Sbostic  *	The Regents of the University of California.  All rights reserved.
423461Smckusick  *
549589Sbostic  * %sccs.include.proprietary.c%
649589Sbostic  *
7*63174Sbostic  *	@(#)kern_physio.c	8.1 (Berkeley) 06/10/93
823461Smckusick  */
98Sbill 
1051454Sbostic #include <sys/param.h>
1151454Sbostic #include <sys/systm.h>
1251454Sbostic #include <sys/buf.h>
1351454Sbostic #include <sys/conf.h>
1451454Sbostic #include <sys/proc.h>
1551454Sbostic #include <sys/vnode.h>
168Sbill 
1751454Sbostic static void freeswbuf __P((struct buf *));
1851454Sbostic static struct buf *getswbuf __P((int));
1948414Skarels 
2091Sbill /*
2149672Smckusick  * This routine does device I/O for a user process.
2249672Smckusick  *
2351759Storek  * If the user has the proper access privileges, the process is
248Sbill  * marked 'delayed unlock' and the pages involved in the I/O are
2549672Smckusick  * faulted and locked. After the completion of the I/O, the pages
268Sbill  * are unlocked.
278Sbill  */
287724Swnj physio(strat, bp, dev, rw, mincnt, uio)
297724Swnj 	int (*strat)();
307724Swnj 	register struct buf *bp;
317724Swnj 	dev_t dev;
327724Swnj 	int rw;
3334215Sbostic 	u_int (*mincnt)();
347724Swnj 	struct uio *uio;
358Sbill {
3617313Skarels 	register struct iovec *iov;
3752424Storek 	register int requested = 0, done = 0;
3847540Skarels 	register struct proc *p = curproc;
398Sbill 	char *a;
4034215Sbostic 	int s, allocbuf = 0, error = 0;
418Sbill 
4234215Sbostic 	if (bp == NULL) {
4334215Sbostic 		allocbuf = 1;
4434215Sbostic 		bp = getswbuf(PRIBIO+1);
4534215Sbostic 	}
4634215Sbostic 	for (; uio->uio_iovcnt; uio->uio_iov++, uio->uio_iovcnt--) {
4730750Skarels 		iov = uio->uio_iov;
4852424Storek 		if (iov->iov_len == 0)
4952424Storek 			continue;
5034215Sbostic 		if (!useracc(iov->iov_base, (u_int)iov->iov_len,
5134215Sbostic 		    rw == B_READ ? B_WRITE : B_READ)) {
5234215Sbostic 			error = EFAULT;
5334215Sbostic 			break;
5430750Skarels 		}
5534215Sbostic 		if (!allocbuf) {	/* only if sharing caller's buffer */
5634215Sbostic 			s = splbio();
5734215Sbostic 			while (bp->b_flags&B_BUSY) {
5834215Sbostic 				bp->b_flags |= B_WANTED;
5934215Sbostic 				sleep((caddr_t)bp, PRIBIO+1);
6034215Sbostic 			}
6134215Sbostic 			splx(s);
6234215Sbostic 		}
6330750Skarels 		bp->b_error = 0;
6447540Skarels 		bp->b_proc = p;
6542001Smckusick #ifdef HPUXCOMPAT
6642001Smckusick 		if (ISHPMMADDR(iov->iov_base))
6742001Smckusick 			bp->b_un.b_addr = (caddr_t)HPMMBASEADDR(iov->iov_base);
6842001Smckusick 		else
6942001Smckusick #endif
7030750Skarels 		bp->b_un.b_addr = iov->iov_base;
7130750Skarels 		while (iov->iov_len > 0) {
7234215Sbostic 			bp->b_flags = B_BUSY | B_PHYS | B_RAW | rw;
7330750Skarels 			bp->b_dev = dev;
7430750Skarels 			bp->b_blkno = btodb(uio->uio_offset);
7530750Skarels 			bp->b_bcount = iov->iov_len;
7630750Skarels 			(*mincnt)(bp);
7738794Skarels 			requested = bp->b_bcount;
7847540Skarels 			p->p_flag |= SPHYSIO;
7938794Skarels 			vslock(a = bp->b_un.b_addr, requested);
8042001Smckusick 			vmapbuf(bp);
8134215Sbostic 			(*strat)(bp);
8234215Sbostic 			s = splbio();
8334215Sbostic 			while ((bp->b_flags & B_DONE) == 0)
8434215Sbostic 				sleep((caddr_t)bp, PRIBIO);
8542001Smckusick 			vunmapbuf(bp);
8638794Skarels 			vsunlock(a, requested, rw);
8747540Skarels 			p->p_flag &= ~SPHYSIO;
8834215Sbostic 			if (bp->b_flags&B_WANTED)	/* rare */
8930750Skarels 				wakeup((caddr_t)bp);
9030750Skarels 			splx(s);
9138794Skarels 			done = bp->b_bcount - bp->b_resid;
9238794Skarels 			bp->b_un.b_addr += done;
9338794Skarels 			iov->iov_len -= done;
9438794Skarels 			uio->uio_resid -= done;
9538794Skarels 			uio->uio_offset += done;
9638794Skarels 			/* temp kludge for disk drives */
9738794Skarels 			if (done < requested || bp->b_flags & B_ERROR)
9830750Skarels 				break;
9930750Skarels 		}
10034215Sbostic 		bp->b_flags &= ~(B_BUSY | B_WANTED | B_PHYS | B_RAW);
10137729Smckusick 		error = biowait(bp);
10238794Skarels 		/* temp kludge for disk drives */
10338794Skarels 		if (done < requested || bp->b_flags & B_ERROR)
10434215Sbostic 			break;
1058Sbill 	}
10634215Sbostic 	if (allocbuf)
10734215Sbostic 		freeswbuf(bp);
10834215Sbostic 	return (error);
1098Sbill }
1108Sbill 
11149672Smckusick /*
11249672Smckusick  * Calculate the maximum size of I/O request that can be requested
11349672Smckusick  * in a single operation. This limit is necessary to prevent a single
11449672Smckusick  * process from being able to lock more than a fixed amount of memory
11549672Smckusick  * in the kernel.
11649672Smckusick  */
11734215Sbostic u_int
1188Sbill minphys(bp)
1197724Swnj 	struct buf *bp;
1208Sbill {
12110400Ssam 	if (bp->b_bcount > MAXPHYS)
12210400Ssam 		bp->b_bcount = MAXPHYS;
1238Sbill }
12434215Sbostic 
12551454Sbostic static struct buf *
12634215Sbostic getswbuf(prio)
12734215Sbostic 	int prio;
12834215Sbostic {
12934215Sbostic 	int s;
13034215Sbostic 	struct buf *bp;
13134215Sbostic 
13234215Sbostic 	s = splbio();
13356387Smckusick 	while (bswlist.b_actf == NULL) {
13434215Sbostic 		bswlist.b_flags |= B_WANTED;
13534215Sbostic 		sleep((caddr_t)&bswlist, prio);
13634215Sbostic 	}
13756387Smckusick 	bp = bswlist.b_actf;
13856387Smckusick 	bswlist.b_actf = bp->b_actf;
13934215Sbostic 	splx(s);
14034215Sbostic 	return (bp);
14134215Sbostic }
14234215Sbostic 
14351454Sbostic static void
14434215Sbostic freeswbuf(bp)
14534215Sbostic 	struct buf *bp;
14634215Sbostic {
14734215Sbostic 	int s;
14834215Sbostic 
14934215Sbostic 	s = splbio();
15056387Smckusick 	bp->b_actf = bswlist.b_actf;
15156387Smckusick 	bswlist.b_actf = bp;
15239148Smckusick 	if (bp->b_vp)
15339148Smckusick 		brelvp(bp);
15434215Sbostic 	if (bswlist.b_flags & B_WANTED) {
15534215Sbostic 		bswlist.b_flags &= ~B_WANTED;
15634215Sbostic 		wakeup((caddr_t)&bswlist);
15747540Skarels 		wakeup((caddr_t)pageproc);
15834215Sbostic 	}
15934215Sbostic 	splx(s);
16034215Sbostic }
16134215Sbostic 
16249672Smckusick /*
16349672Smckusick  * Do a read on a device for a user process.
16449672Smckusick  */
16534215Sbostic rawread(dev, uio)
16634215Sbostic 	dev_t dev;
16734215Sbostic 	struct uio *uio;
16834215Sbostic {
16934215Sbostic 	return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL,
17034215Sbostic 	    dev, B_READ, minphys, uio));
17134215Sbostic }
17234215Sbostic 
17349672Smckusick /*
17449672Smckusick  * Do a write on a device for a user process.
17549672Smckusick  */
17634215Sbostic rawwrite(dev, uio)
17734215Sbostic 	dev_t dev;
17834215Sbostic 	struct uio *uio;
17934215Sbostic {
18034215Sbostic 	return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL,
18134215Sbostic 	    dev, B_WRITE, minphys, uio));
18234215Sbostic }
183