コード例 #1
0
ファイル: copyops.c プロジェクト: BjoKaSH/mac-zfs
int
physio(int (*strat)(struct buf *), struct buf *bp, dev_t dev,
    int rw, void (*mincnt)(struct buf *), struct uio *uio)
{
	return (default_physio(strat, bp, dev, rw, mincnt, uio));
}
コード例 #2
0
ファイル: watchpoint.c プロジェクト: andreiw/polaris
/*
 * Wrapper for the physio() function.
 * Splits one uio operation with multiple iovecs into uio operations with
 * only one iovecs to do the watchpoint handling separately for each iovecs.
 */
static int
watch_physio(int (*strat)(struct buf *), struct buf *bp, dev_t dev,
    int rw, void (*mincnt)(struct buf *), struct uio *uio)
{
	struct uio auio;
	struct iovec *iov;
	caddr_t  base;
	size_t len;
	int seg_rw;
	int error = 0;

	if (uio->uio_segflg == UIO_SYSSPACE)
		return (default_physio(strat, bp, dev, rw, mincnt, uio));

	seg_rw = (rw == B_READ) ? S_WRITE : S_READ;

	while (uio->uio_iovcnt > 0) {
		if (uio->uio_resid == 0) {
			/*
			 * Make sure to return the uio structure with the
			 * same values as default_physio() does.
			 */
			uio->uio_iov++;
			uio->uio_iovcnt--;
			continue;
		}

		iov = uio->uio_iov;
		len = MIN(iov->iov_len, uio->uio_resid);

		auio.uio_iovcnt = 1;
		auio.uio_iov = iov;
		auio.uio_resid = len;
		auio.uio_loffset = uio->uio_loffset;
		auio.uio_llimit = uio->uio_llimit;
		auio.uio_fmode = uio->uio_fmode;
		auio.uio_extflg = uio->uio_extflg;
		auio.uio_segflg = uio->uio_segflg;

		base = iov->iov_base;

		if (!pr_is_watched(base, len, seg_rw)) {
			/*
			 * The given memory references don't cover a
			 * watched page.
			 */
			error = default_physio(strat, bp, dev, rw, mincnt,
			    &auio);

			/* Update uio with values from auio. */
			len -= auio.uio_resid;
			uio->uio_resid -= len;
			uio->uio_loffset += len;

			/*
			 * Return if an error occurred or not all data
			 * was copied.
			 */
			if (auio.uio_resid || error)
				break;
			uio->uio_iov++;
			uio->uio_iovcnt--;
		} else {
			int mapped, watchcode, ta;
			caddr_t vaddr = base;
			klwp_t *lwp = ttolwp(curthread);

			watchcode = pr_is_watchpoint(&vaddr, &ta, len,
			    NULL, seg_rw);

			if (watchcode == 0 || ta != 0) {
				/*
				 * Do the io if the given memory references
				 * don't cover a watched area (watchcode=0)
				 * or if WA_TRAPAFTER was specified.
				 */
				mapped = pr_mappage(base, len, seg_rw, 1);
				error = default_physio(strat, bp, dev, rw,
				    mincnt, &auio);
				if (mapped)
					pr_unmappage(base, len, seg_rw, 1);

				len -= auio.uio_resid;
				uio->uio_resid -= len;
				uio->uio_loffset += len;
			}

			/*
			 * If we hit a watched address, do the watchpoint logic.
			 */
			if (watchcode &&
			    (!sys_watchpoint(vaddr, watchcode, ta) ||
			    lwp->lwp_sysabort)) {
				lwp->lwp_sysabort = 0;
				return (EFAULT);
			}

			/*
			 * Check for errors from default_physio().
			 */
			if (watchcode == 0 || ta != 0) {
				if (auio.uio_resid || error)
					break;
				uio->uio_iov++;
				uio->uio_iovcnt--;
			}
		}
	}

	return (error);
}