static void
filemon_output(struct filemon *filemon, char *msg, size_t len)
{
	struct uio auio;
	struct iovec aiov;
	int error;

	if (filemon->fp == NULL)
		return;

	aiov.iov_base = msg;
	aiov.iov_len = len;
	auio.uio_iov = &aiov;
	auio.uio_iovcnt = 1;
	auio.uio_resid = len;
	auio.uio_segflg = UIO_SYSSPACE;
	auio.uio_rw = UIO_WRITE;
	auio.uio_td = curthread;
	auio.uio_offset = (off_t) -1;

	if (filemon->fp->f_type == DTYPE_VNODE)
		bwillwrite();

	error = fo_write(filemon->fp, &auio, curthread->td_ucred, 0, curthread);
	if (error != 0)
		filemon->error = error;
}
Beispiel #2
0
/*
 * Write buffer to filp inside kernel
 */
int
kern_file_write (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 = (void *)(uintptr_t)buf;
	aiov.iov_len = nbyte;
	auio.uio_iov = &aiov;
	auio.uio_iovcnt = 1;
        if (pos != NULL) {
	        auio.uio_offset = *pos;
                /* 
                 * Liang: If don't set FOF_OFFSET, vn_write()
                 * will use fp->f_offset as the the real offset.
                 * Same in vn_read()
                 */
                flags |= FOF_OFFSET;
        } else
                auio.uio_offset = (off_t)-1;
	if (nbyte > INT_MAX)
		return (EINVAL);
	auio.uio_resid = nbyte;
	auio.uio_rw = UIO_WRITE;
	auio.uio_segflg = UIO_SYSSPACE;
	auio.uio_procp = p;

	cnt = nbyte;
        CFS_CONE_IN;
	if (fp->f_type == DTYPE_VNODE)
		bwillwrite();	/* empty stuff now */
	if ((error = fo_write(fp, &auio, fp->f_cred, flags, p))) {
		if (auio.uio_resid != cnt && (error == ERESTART ||\
		    error == EINTR || error == EWOULDBLOCK))
			error = 0;
		/* The socket layer handles SIGPIPE */
		if (error == EPIPE && fp->f_type != DTYPE_SOCKET)
			psignal(p, SIGPIPE);
	}
        CFS_CONE_EX;
	if (error != 0)
		cnt = -error;
	else
		cnt -= auio.uio_resid;
        if (pos != NULL)
                *pos += cnt;
	return cnt;
}
Beispiel #3
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);
}
Beispiel #4
0
int
fp_pwrite(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_WRITE;
    auio.uio_segflg = seg;
    auio.uio_td = curthread;

    count = nbytes;
    error = fo_write(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);
}
Beispiel #5
0
static int
write_bytes(struct diffarg *da)
{
	struct uio auio;
	struct iovec aiov;

	aiov.iov_base = (caddr_t)&da->da_ddr;
	aiov.iov_len = sizeof (da->da_ddr);
	auio.uio_iov = &aiov;
	auio.uio_iovcnt = 1;
	auio.uio_resid = aiov.iov_len;
	auio.uio_segflg = UIO_SYSSPACE;
	auio.uio_rw = UIO_WRITE;
	auio.uio_offset = (off_t)-1;
	auio.uio_td = da->da_td;
#ifdef _KERNEL
	if (da->da_fp->f_type == DTYPE_VNODE)
		bwillwrite();
	return (fo_write(da->da_fp, &auio, da->da_td->td_ucred, 0, da->da_td));
#else
	fprintf(stderr, "%s: returning EOPNOTSUPP\n", __func__);
	return (EOPNOTSUPP);
#endif
}
static void
pmclog_loop(void *arg)
{
	int error;
	struct pmc_owner *po;
	struct pmclog_buffer *lb;
	struct proc *p;
	struct ucred *ownercred;
	struct ucred *mycred;
	struct thread *td;
	struct uio auio;
	struct iovec aiov;
	size_t nbytes;

	po = (struct pmc_owner *) arg;
	p = po->po_owner;
	td = curthread;
	mycred = td->td_ucred;

	PROC_LOCK(p);
	ownercred = crhold(p->p_ucred);
	PROC_UNLOCK(p);

	PMCDBG(LOG,INI,1, "po=%p kt=%p", po, po->po_kthread);
	KASSERT(po->po_kthread == curthread->td_proc,
	    ("[pmclog,%d] proc mismatch po=%p po/kt=%p curproc=%p", __LINE__,
		po, po->po_kthread, curthread->td_proc));

	lb = NULL;


	/*
	 * Loop waiting for I/O requests to be added to the owner
	 * struct's queue.  The loop is exited when the log file
	 * is deconfigured.
	 */

	mtx_lock(&pmc_kthread_mtx);

	for (;;) {

		/* check if we've been asked to exit */
		if ((po->po_flags & PMC_PO_OWNS_LOGFILE) == 0)
			break;

		if (lb == NULL) { /* look for a fresh buffer to write */
			mtx_lock_spin(&po->po_mtx);
			if ((lb = TAILQ_FIRST(&po->po_logbuffers)) == NULL) {
				mtx_unlock_spin(&po->po_mtx);

				/* No more buffers and shutdown required. */
				if (po->po_flags & PMC_PO_SHUTDOWN) {
					mtx_unlock(&pmc_kthread_mtx);
					/*
			 		 * Close the file to get PMCLOG_EOF
					 * error in pmclog(3).
					 */
					fo_close(po->po_file, curthread);
					mtx_lock(&pmc_kthread_mtx);
					break;
				}

				(void) msleep(po, &pmc_kthread_mtx, PWAIT,
				    "pmcloop", 0);
				continue;
			}

			TAILQ_REMOVE(&po->po_logbuffers, lb, plb_next);
			mtx_unlock_spin(&po->po_mtx);
		}

		mtx_unlock(&pmc_kthread_mtx);

		/* process the request */
		PMCDBG(LOG,WRI,2, "po=%p base=%p ptr=%p", po,
		    lb->plb_base, lb->plb_ptr);
		/* change our thread's credentials before issuing the I/O */

		aiov.iov_base = lb->plb_base;
		aiov.iov_len  = nbytes = lb->plb_ptr - lb->plb_base;

		auio.uio_iov    = &aiov;
		auio.uio_iovcnt = 1;
		auio.uio_offset = -1;
		auio.uio_resid  = nbytes;
		auio.uio_rw     = UIO_WRITE;
		auio.uio_segflg = UIO_SYSSPACE;
		auio.uio_td     = td;

		/* switch thread credentials -- see kern_ktrace.c */
		td->td_ucred = ownercred;
		error = fo_write(po->po_file, &auio, ownercred, 0, td);
		td->td_ucred = mycred;

		if (error) {
			/* XXX some errors are recoverable */
			/* send a SIGIO to the owner and exit */
			PROC_LOCK(p);
			kern_psignal(p, SIGIO);
			PROC_UNLOCK(p);

			mtx_lock(&pmc_kthread_mtx);

			po->po_error = error; /* save for flush log */

			PMCDBG(LOG,WRI,2, "po=%p error=%d", po, error);

			break;
		}

		mtx_lock(&pmc_kthread_mtx);

		/* put the used buffer back into the global pool */
		PMCLOG_INIT_BUFFER_DESCRIPTOR(lb);

		mtx_lock_spin(&pmc_bufferlist_mtx);
		TAILQ_INSERT_HEAD(&pmc_bufferlist, lb, plb_next);
		mtx_unlock_spin(&pmc_bufferlist_mtx);

		lb = NULL;
	}

	wakeup_one(po->po_kthread);
	po->po_kthread = NULL;

	mtx_unlock(&pmc_kthread_mtx);

	/* return the current I/O buffer to the global pool */
	if (lb) {
		PMCLOG_INIT_BUFFER_DESCRIPTOR(lb);

		mtx_lock_spin(&pmc_bufferlist_mtx);
		TAILQ_INSERT_HEAD(&pmc_bufferlist, lb, plb_next);
		mtx_unlock_spin(&pmc_bufferlist_mtx);
	}

	/*
	 * Exit this thread, signalling the waiter
	 */

	crfree(ownercred);

	kproc_exit(0);
}