Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/fuse/fuse_device.c
Show First 20 Lines • Show All 281 Lines • ▼ Show 20 Lines | |||||
* 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 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | if (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 |