Esempio n. 1
0
int
fp_read(file_t fp, void *buf, size_t nbytes, ssize_t *res, int all,
	enum uio_seg seg)
{
    struct uio auio;
    struct iovec aiov;
    int error;
    int lastresid;

    if (res)
	*res = 0;
    if (nbytes > LONG_MAX)
	return (EINVAL);
    bzero(&auio, sizeof(auio));
    aiov.iov_base = (caddr_t)buf;
    aiov.iov_len = nbytes;
    auio.uio_iov = &aiov;
    auio.uio_iovcnt = 1;
    auio.uio_offset = 0;
    auio.uio_resid = nbytes;
    auio.uio_rw = UIO_READ;
    auio.uio_segflg = seg;
    auio.uio_td = curthread;

    /*
     * If all is false call fo_read() once.
     * If all is true we attempt to read the entire request.  We have to
     * break out of the loop if an unrecoverable error or EOF occurs.
     */
    do {
	lastresid = auio.uio_resid;
	error = fo_read(fp, &auio, fp->f_cred, 0);
    } while (all && auio.uio_resid &&
	     ((error == 0 && auio.uio_resid != lastresid) || 
	     error == ERESTART || error == EINTR));
    if (all && error == 0 && auio.uio_resid)
	error = ESPIPE;

    /*
     * If an error occured but some data was read, silently forget the
     * error.  However, if this is a non-blocking descriptor and 'all'
     * was specified, return an error even if some data was read (this
     * is considered a bug in the caller for using an illegal combination
     * of 'all' and a non-blocking descriptor).
     */
    if (error) {
	if (auio.uio_resid != nbytes) {
	    if (error == ERESTART || error == EINTR)
		error = 0;
	    if (error == EWOULDBLOCK && all == 0)
		error = 0;
	}
    }
    if (res)
	*res = nbytes - auio.uio_resid;
    return(error);
}
Esempio n. 2
0
/*
 * Our version of vn_rdwr, here "vp" is not actually a vnode, but a ptr
 * to the node allocated in getf(). We use the "fp" part of the node to
 * be able to issue IO.
 * You must call getf() before calling spl_vn_rdwr().
 */
int spl_vn_rdwr(enum uio_rw rw,
                struct vnode *vp,
                caddr_t base,
                ssize_t len,
                offset_t offset,
                enum uio_seg seg,
                int ioflag,
                rlim64_t ulimit,    /* meaningful only if rw is UIO_WRITE */
                cred_t *cr,
                ssize_t *residp)
{
    struct spl_fileproc *sfp = (struct spl_fileproc*)vp;
    uio_t *auio;
    int spacetype;
    int error=0;
    vfs_context_t vctx;

    spacetype = UIO_SEG_IS_USER_SPACE(seg) ? UIO_USERSPACE32 : UIO_SYSSPACE;

    vctx = vfs_context_create((vfs_context_t)0);
    auio = uio_create(1, 0, spacetype, rw);
    uio_reset(auio, offset, spacetype, rw);
    uio_addiov(auio, (uint64_t)(uintptr_t)base, len);

    if (rw == UIO_READ) {
        error = fo_read(sfp->f_fp, auio, ioflag, vctx);
    } else {
        error = fo_write(sfp->f_fp, auio, ioflag, vctx);
        sfp->f_writes = 1;
    }

    if (residp) {
        *residp = uio_resid(auio);
    } else {
        if (uio_resid(auio) && error == 0)
            error = EIO;
    }

    uio_free(auio);
    vfs_context_rele(vctx);

    return (error);
}
Esempio n. 3
0
/*
 * Read from filp inside kernel
 */
int
kern_file_read (cfs_file_t *fp, void *buf, size_t nbyte, loff_t *pos)
{
	struct uio auio;
	struct iovec aiov;
	struct proc *p = current_proc();
	long cnt, error = 0;
        int  flags = 0;
        CFS_DECL_CONE_DATA;

	aiov.iov_base = (caddr_t)buf;
	aiov.iov_len = nbyte;
	auio.uio_iov = &aiov;
	auio.uio_iovcnt = 1;
        if (pos != NULL) {
	        auio.uio_offset = *pos;
                flags |= FOF_OFFSET;
        } else
                auio.uio_offset = (off_t)-1;
	if (nbyte > INT_MAX)
		return (EINVAL);
	auio.uio_resid = nbyte;
	auio.uio_rw = UIO_READ;
	auio.uio_segflg = UIO_SYSSPACE;
	auio.uio_procp = p;

	cnt = nbyte;
        CFS_CONE_IN;
	if ((error = fo_read(fp, &auio, fp->f_cred, flags, p)) != 0) {
		if (auio.uio_resid != cnt && (error == ERESTART ||
		    error == EINTR || error == EWOULDBLOCK))
			error = 0;
	}
        CFS_CONE_EX;
	if (error != 0)
		cnt = -error;
	else
		cnt -= auio.uio_resid;
        if (pos != NULL)
                *pos += cnt;

	return cnt;
}
Esempio n. 4
0
/*
 * fp_*read() is meant to operate like the normal descriptor based syscalls
 * would.  Note that if 'buf' points to user memory a UIO_USERSPACE
 * transfer will be used.
 */
int
fp_pread(file_t fp, void *buf, size_t nbytes, off_t offset, ssize_t *res,
	 enum uio_seg seg)
{
    struct uio auio;
    struct iovec aiov;
    size_t count;
    int error;

    if (res)
	*res = 0;
    if (nbytes > LONG_MAX)
	return (EINVAL);
    bzero(&auio, sizeof(auio));
    aiov.iov_base = (caddr_t)buf;
    aiov.iov_len = nbytes;
    auio.uio_iov = &aiov;
    auio.uio_iovcnt = 1;
    auio.uio_offset = offset;
    auio.uio_resid = nbytes;
    auio.uio_rw = UIO_READ;
    auio.uio_segflg = seg;
    auio.uio_td = curthread;

    count = nbytes;
    error = fo_read(fp, &auio, fp->f_cred, O_FOFFSET);
    if (error) {
	if (auio.uio_resid != nbytes && (error == ERESTART || error == EINTR ||
	    error == EWOULDBLOCK)
	) {
	    error = 0;
	}
    }
    count -= auio.uio_resid;
    if (res)
	*res = count;
    return(error);
}