Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/fuse/fuse_device.c
Show First 20 Lines • Show All 270 Lines • ▼ Show 20 Lines | if (events & (POLLIN | POLLRDNORM)) { | ||||
fuse_lck_mtx_unlock(data->ms_mtx); | fuse_lck_mtx_unlock(data->ms_mtx); | ||||
} | } | ||||
if (events & (POLLOUT | POLLWRNORM)) { | if (events & (POLLOUT | POLLWRNORM)) { | ||||
revents |= events & (POLLOUT | POLLWRNORM); | revents |= events & (POLLOUT | POLLWRNORM); | ||||
} | } | ||||
return (revents); | return (revents); | ||||
} | } | ||||
SDT_PROBE_DEFINE1(fusefs, , device, read_tick, "struct fuse_ticket*"); | |||||
/* | /* | ||||
* fuse_device_read hangs on the queue of VFS messages. | * fuse_device_read hangs on the queue of VFS messages. | ||||
* When it's notified that there is a new one, it picks that and | * When it's notified that there is a new one, it picks that and | ||||
* passes up to the daemon | * passes up to the daemon | ||||
*/ | */ | ||||
int | int | ||||
fuse_device_read(struct cdev *dev, struct uio *uio, int ioflag) | fuse_device_read(struct cdev *dev, struct uio *uio, int ioflag) | ||||
{ | { | ||||
int err; | int err; | ||||
struct fuse_data *data; | struct fuse_data *data; | ||||
struct fuse_ticket *tick; | struct fuse_ticket *tick; | ||||
void *buf[] = {NULL, NULL, NULL}; | void *buf; | ||||
int buflen[3]; | int buflen; | ||||
int i; | |||||
SDT_PROBE2(fusefs, , device, trace, 1, "fuse device read"); | SDT_PROBE2(fusefs, , device, trace, 1, "fuse device read"); | ||||
err = devfs_get_cdevpriv((void **)&data); | err = devfs_get_cdevpriv((void **)&data); | ||||
if (err != 0) | if (err != 0) | ||||
return (err); | return (err); | ||||
fuse_lck_mtx_lock(data->ms_mtx); | fuse_lck_mtx_lock(data->ms_mtx); | ||||
Show All 26 Lines | if (!tick) { | ||||
* eg, by being hit by a SIGKILL | * eg, by being hit by a SIGKILL | ||||
* -- and some other cases, too, tho not totally clear, when | * -- and some other cases, too, tho not totally clear, when | ||||
* (cv_signal/wakeup_one signals the whole process ?) | * (cv_signal/wakeup_one signals the whole process ?) | ||||
*/ | */ | ||||
SDT_PROBE2(fusefs, , device, trace, 1, "no message on thread"); | SDT_PROBE2(fusefs, , device, trace, 1, "no message on thread"); | ||||
goto again; | goto again; | ||||
} | } | ||||
fuse_lck_mtx_unlock(data->ms_mtx); | fuse_lck_mtx_unlock(data->ms_mtx); | ||||
SDT_PROBE1(fusefs, , device, read_tick, tick); | |||||
if (fdata_get_dead(data)) { | if (fdata_get_dead(data)) { | ||||
/* | /* | ||||
* somebody somewhere -- eg., umount routine -- | * somebody somewhere -- eg., umount routine -- | ||||
* wants this liaison finished off | * wants this liaison finished off | ||||
*/ | */ | ||||
SDT_PROBE2(fusefs, , device, trace, 2, | SDT_PROBE2(fusefs, , device, trace, 2, | ||||
"reader is to be sacked"); | "reader is to be sacked"); | ||||
if (tick) { | if (tick) { | ||||
SDT_PROBE2(fusefs, , device, trace, 2, "weird -- " | SDT_PROBE2(fusefs, , device, trace, 2, "weird -- " | ||||
"\"kick\" is set tho there is message"); | "\"kick\" is set tho there is message"); | ||||
FUSE_ASSERT_MS_DONE(tick); | FUSE_ASSERT_MS_DONE(tick); | ||||
fuse_ticket_drop(tick); | fuse_ticket_drop(tick); | ||||
} | } | ||||
return (ENODEV); /* This should make the daemon get off | return (ENODEV); /* This should make the daemon get off | ||||
* of us */ | * of us */ | ||||
} | } | ||||
SDT_PROBE2(fusefs, , device, trace, 1, | SDT_PROBE2(fusefs, , device, trace, 1, | ||||
"fuse device read message successfully"); | "fuse device read message successfully"); | ||||
KASSERT(tick->tk_ms_bufdata || tick->tk_ms_bufsize == 0, | buf = tick->tk_ms_fiov.base; | ||||
("non-null buf pointer with positive size")); | buflen = tick->tk_ms_fiov.len; | ||||
switch (tick->tk_ms_type) { | |||||
case FT_M_FIOV: | |||||
buf[0] = tick->tk_ms_fiov.base; | |||||
buflen[0] = tick->tk_ms_fiov.len; | |||||
break; | |||||
case FT_M_BUF: | |||||
buf[0] = tick->tk_ms_fiov.base; | |||||
buflen[0] = tick->tk_ms_fiov.len; | |||||
buf[1] = tick->tk_ms_bufdata; | |||||
buflen[1] = tick->tk_ms_bufsize; | |||||
break; | |||||
default: | |||||
panic("unknown message type for fuse_ticket %p", tick); | |||||
} | |||||
for (i = 0; buf[i]; i++) { | |||||
/* | /* | ||||
* Why not ban mercilessly stupid daemons who can't keep up | * Why not ban mercilessly stupid daemons who can't keep up | ||||
* with us? (There is no much use of a partial read here...) | * with us? (There is no much use of a partial read here...) | ||||
*/ | */ | ||||
/* | /* | ||||
* XXX note that in such cases Linux FUSE throws EIO at the | * XXX note that in such cases Linux FUSE throws EIO at the | ||||
* syscall invoker and stands back to the message queue. The | * syscall invoker and stands back to the message queue. The | ||||
* rationale should be made clear (and possibly adopt that | * rationale should be made clear (and possibly adopt that | ||||
* behaviour). Keeping the current scheme at least makes | * behaviour). Keeping the current scheme at least makes | ||||
* fallacy as loud as possible... | * fallacy as loud as possible... | ||||
*/ | */ | ||||
if (uio->uio_resid < buflen[i]) { | if (uio->uio_resid < buflen) { | ||||
fdata_set_dead(data); | fdata_set_dead(data); | ||||
SDT_PROBE2(fusefs, , device, trace, 2, | SDT_PROBE2(fusefs, , device, trace, 2, | ||||
"daemon is stupid, kick it off..."); | "daemon is stupid, kick it off..."); | ||||
err = ENODEV; | err = ENODEV; | ||||
break; | } else { | ||||
} | err = uiomove(buf, buflen, uio); | ||||
err = uiomove(buf[i], buflen[i], uio); | |||||
if (err) | |||||
break; | |||||
} | } | ||||
FUSE_ASSERT_MS_DONE(tick); | FUSE_ASSERT_MS_DONE(tick); | ||||
fuse_ticket_drop(tick); | fuse_ticket_drop(tick); | ||||
return (err); | return (err); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 201 Lines • Show Last 20 Lines |