コード例 #1
0
static int
fuse_device_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
{
	struct fuse_data *data;
	struct fuse_ticket *tick;
	int error;

	error = devfs_get_cdevpriv((void **)&data);
	if (error != 0)
		return (error);
	if (!data)
		panic("no fuse data upon fuse device close");
	fdata_set_dead(data);

	FUSE_LOCK();
	fuse_lck_mtx_lock(data->aw_mtx);
	/* wakup poll()ers */
	selwakeuppri(&data->ks_rsel, PZERO + 1);
	/* Don't let syscall handlers wait in vain */
	while ((tick = fuse_aw_pop(data))) {
		fuse_lck_mtx_lock(tick->tk_aw_mtx);
		fticket_set_answered(tick);
		tick->tk_aw_errno = ENOTCONN;
		wakeup(tick);
		fuse_lck_mtx_unlock(tick->tk_aw_mtx);
		FUSE_ASSERT_AW_DONE(tick);
		fuse_ticket_drop(tick);
	}
	fuse_lck_mtx_unlock(data->aw_mtx);
	FUSE_UNLOCK();

	SDT_PROBE2(fuse, , device, trace, 1, "device close");
	return (0);
}
コード例 #2
0
static int
fticket_wait_answer(struct fuse_ticket *ftick)
{
	sigset_t tset;
	int err = 0;
	struct fuse_data *data;

	debug_printf("ftick=%p\n", ftick);
	fuse_lck_mtx_lock(ftick->tk_aw_mtx);

	if (fticket_answered(ftick)) {
		goto out;
	}
	data = ftick->tk_data;

	if (fdata_get_dead(data)) {
		err = ENOTCONN;
		fticket_set_answered(ftick);
		goto out;
	}
	fuse_block_sigs(&tset);
	err = msleep(ftick, &ftick->tk_aw_mtx, PCATCH, "fu_ans",
	    data->daemon_timeout * hz);
	fuse_restore_sigs(&tset);
	if (err == EAGAIN) {		/* same as EWOULDBLOCK */
#ifdef XXXIP				/* die conditionally */
		if (!fdata_get_dead(data)) {
			fdata_set_dead(data);
		}
#endif
		err = ETIMEDOUT;
		fticket_set_answered(ftick);
	}
out:
	if (!(err || fticket_answered(ftick))) {
		debug_printf("FUSE: requester was woken up but still no answer");
		err = ENXIO;
	}
	fuse_lck_mtx_unlock(ftick->tk_aw_mtx);

	return err;
}
コード例 #3
0
static int
fuse_standard_handler(struct fuse_ticket *ftick, struct uio *uio)
{
	int err = 0;

	debug_printf("ftick=%p, uio=%p\n", ftick, uio);

	err = fticket_pull(ftick, uio);

	fuse_lck_mtx_lock(ftick->tk_aw_mtx);

	if (!fticket_answered(ftick)) {
		fticket_set_answered(ftick);
		ftick->tk_aw_errno = err;
		wakeup(ftick);
	}
	fuse_lck_mtx_unlock(ftick->tk_aw_mtx);

	return err;
}
コード例 #4
0
int
fdisp_wait_answ(struct fuse_dispatcher *fdip)
{
	int err = 0;

	fdip->answ_stat = 0;
	fuse_insert_callback(fdip->tick, fuse_standard_handler);
	fuse_insert_message(fdip->tick);

	if ((err = fticket_wait_answer(fdip->tick))) {
		debug_printf("IPC: interrupted, err = %d\n", err);

		fuse_lck_mtx_lock(fdip->tick->tk_aw_mtx);

		if (fticket_answered(fdip->tick)) {
			/*
	                 * Just between noticing the interrupt and getting here,
	                 * the standard handler has completed his job.
	                 * So we drop the ticket and exit as usual.
	                 */
			debug_printf("IPC: already answered\n");
			fuse_lck_mtx_unlock(fdip->tick->tk_aw_mtx);
			goto out;
		} else {
			/*
	                 * So we were faster than the standard handler.
	                 * Then by setting the answered flag we get *him*
	                 * to drop the ticket.
	                 */
			debug_printf("IPC: setting to answered\n");
			fticket_set_answered(fdip->tick);
			fuse_lck_mtx_unlock(fdip->tick->tk_aw_mtx);
			return err;
		}
	}
	debug_printf("IPC: not interrupted, err = %d\n", err);

	if (fdip->tick->tk_aw_errno) {
		debug_printf("IPC: explicit EIO-ing, tk_aw_errno = %d\n",
		    fdip->tick->tk_aw_errno);
		err = EIO;
		goto out;
	}
	if ((err = fdip->tick->tk_aw_ohead.error)) {
		debug_printf("IPC: setting status to %d\n",
		    fdip->tick->tk_aw_ohead.error);
		/*
	         * This means a "proper" fuse syscall error.
	         * We record this value so the caller will
	         * be able to know it's not a boring messaging
	         * failure, if she wishes so (and if not, she can
	         * just simply propagate the return value of this routine).
	         * [XXX Maybe a bitflag would do the job too,
	         * if other flags needed, this will be converted thusly.]
	         */
		fdip->answ_stat = err;
		goto out;
	}
	fdip->answ = fticket_resp(fdip->tick)->base;
	fdip->iosize = fticket_resp(fdip->tick)->len;

	debug_printf("IPC: all is well\n");

	return 0;

out:
	debug_printf("IPC: dropping ticket, err = %d\n", err);

	return err;
}