예제 #1
0
int
pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd)
{
	struct proc *p;
	cap_rights_t rights;
	int error;

	sx_assert(&pmc_sx, SA_XLOCKED);
	PMCDBG2(LOG,CFG,1, "config po=%p logfd=%d", po, logfd);

	p = po->po_owner;

	/* return EBUSY if a log file was already present */
	if (po->po_flags & PMC_PO_OWNS_LOGFILE)
		return (EBUSY);

	KASSERT(po->po_file == NULL,
	    ("[pmclog,%d] po=%p file (%p) already present", __LINE__, po,
		po->po_file));

	/* get a reference to the file state */
	error = fget_write(curthread, logfd,
	    cap_rights_init(&rights, CAP_WRITE), &po->po_file);
	if (error)
		goto error;

	/* mark process as owning a log file */
	po->po_flags |= PMC_PO_OWNS_LOGFILE;

	/* mark process as using HWPMCs */
	PROC_LOCK(p);
	p->p_flag |= P_HWPMC;
	PROC_UNLOCK(p);

	/* create a log initialization entry */
	PMCLOG_RESERVE_WITH_ERROR(po, INITIALIZE,
	    sizeof(struct pmclog_initialize));
	PMCLOG_EMIT32(PMC_VERSION);
	PMCLOG_EMIT32(md->pmd_cputype);
	PMCLOG_DESPATCH(po);

	return (0);

 error:
	KASSERT(po->po_kthread == NULL, ("[pmclog,%d] po=%p kthread not "
	    "stopped", __LINE__, po));

	if (po->po_file)
		(void) fdrop(po->po_file, curthread);
	po->po_file  = NULL;	/* clear file and error state */
	po->po_error = 0;
	po->po_flags &= ~PMC_PO_OWNS_LOGFILE;

	return (error);
}
예제 #2
0
static int
filemon_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag __unused,
    struct thread *td)
{
	int error = 0;
	struct filemon *filemon;
	struct proc *p;
	cap_rights_t rights;

	if ((error = devfs_get_cdevpriv((void **) &filemon)) != 0)
		return (error);

	sx_xlock(&filemon->lock);

	switch (cmd) {
	/* Set the output file descriptor. */
	case FILEMON_SET_FD:
		if (filemon->fp != NULL) {
			error = EEXIST;
			break;
		}

		error = fget_write(td, *(int *)data,
		    cap_rights_init(&rights, CAP_PWRITE),
		    &filemon->fp);
		if (error == 0)
			/* Write the file header. */
			filemon_write_header(filemon);
		break;

	/* Set the monitored process ID. */
	case FILEMON_SET_PID:
		/* Invalidate any existing processes already set. */
		filemon_untrack_processes(filemon);

		error = pget(*((pid_t *)data),
		    PGET_CANDEBUG | PGET_NOTWEXIT | PGET_NOTINEXEC, &p);
		if (error == 0) {
			KASSERT(p->p_filemon != filemon,
			    ("%s: proc %p didn't untrack filemon %p",
			    __func__, p, filemon));
			error = filemon_attach_proc(filemon, p);
			PROC_UNLOCK(p);
		}
		break;

	default:
		error = EINVAL;
		break;
	}

	sx_xunlock(&filemon->lock);
	return (error);
}
예제 #3
0
파일: filemon.c 프로젝트: ChaosJohn/freebsd
static int
filemon_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag __unused,
    struct thread *td)
{
	int error = 0;
	struct filemon *filemon;
	struct proc *p;
#if __FreeBSD_version >= 900041
	cap_rights_t rights;
#endif

	devfs_get_cdevpriv((void **) &filemon);

	switch (cmd) {
	/* Set the output file descriptor. */
	case FILEMON_SET_FD:
		error = fget_write(td, *(int *)data,
#if __FreeBSD_version >= 900041
		    cap_rights_init(&rights, CAP_PWRITE),
#endif
		    &filemon->fp);
		if (error == 0)
			/* Write the file header. */
			filemon_comment(filemon);
		break;

	/* Set the monitored process ID. */
	case FILEMON_SET_PID:
		error = pget(*((pid_t *)data), PGET_CANDEBUG | PGET_NOTWEXIT,
		    &p);
		if (error == 0) {
			filemon->pid = p->p_pid;
			PROC_UNLOCK(p);
		}
		break;

	default:
		error = EINVAL;
		break;
	}

	return (error);
}
예제 #4
0
int
pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd)
{
	int error;
	struct proc *p;

	/*
	 * As long as it is possible to get a LOR between pmc_sx lock and
	 * proctree/allproc sx locks used for adding a new process, assure
	 * the former is not held here.
	 */
	sx_assert(&pmc_sx, SA_UNLOCKED);
	PMCDBG(LOG,CFG,1, "config po=%p logfd=%d", po, logfd);

	p = po->po_owner;

	/* return EBUSY if a log file was already present */
	if (po->po_flags & PMC_PO_OWNS_LOGFILE)
		return (EBUSY);

	KASSERT(po->po_kthread == NULL,
	    ("[pmclog,%d] po=%p kthread (%p) already present", __LINE__, po,
		po->po_kthread));
	KASSERT(po->po_file == NULL,
	    ("[pmclog,%d] po=%p file (%p) already present", __LINE__, po,
		po->po_file));

	/* get a reference to the file state */
	error = fget_write(curthread, logfd, CAP_WRITE, &po->po_file);
	if (error)
		goto error;

	/* mark process as owning a log file */
	po->po_flags |= PMC_PO_OWNS_LOGFILE;
	error = kproc_create(pmclog_loop, po, &po->po_kthread,
	    RFHIGHPID, 0, "hwpmc: proc(%d)", p->p_pid);
	if (error)
		goto error;

	/* mark process as using HWPMCs */
	PROC_LOCK(p);
	p->p_flag |= P_HWPMC;
	PROC_UNLOCK(p);

	/* create a log initialization entry */
	PMCLOG_RESERVE_WITH_ERROR(po, INITIALIZE,
	    sizeof(struct pmclog_initialize));
	PMCLOG_EMIT32(PMC_VERSION);
	PMCLOG_EMIT32(md->pmd_cputype);
	PMCLOG_DESPATCH(po);

	return (0);

 error:
	/* shutdown the thread */
	if (po->po_kthread)
		pmclog_stop_kthread(po);

	KASSERT(po->po_kthread == NULL, ("[pmclog,%d] po=%p kthread not "
	    "stopped", __LINE__, po));

	if (po->po_file)
		(void) fdrop(po->po_file, curthread);
	po->po_file  = NULL;	/* clear file and error state */
	po->po_error = 0;

	return (error);
}