aboutsummaryrefslogtreecommitdiff
path: root/sys/fs/fuse/fuse_device.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/fs/fuse/fuse_device.c')
-rw-r--r--sys/fs/fuse/fuse_device.c49
1 files changed, 32 insertions, 17 deletions
diff --git a/sys/fs/fuse/fuse_device.c b/sys/fs/fuse/fuse_device.c
index 892793993ecc..57b3559731f7 100644
--- a/sys/fs/fuse/fuse_device.c
+++ b/sys/fs/fuse/fuse_device.c
@@ -82,6 +82,8 @@
#include <sys/sysctl.h>
#include <sys/poll.h>
#include <sys/selinfo.h>
+#define EXTERR_CATEGORY EXTERR_CAT_FUSE
+#include <sys/exterrvar.h>
#include "fuse.h"
#include "fuse_internal.h"
@@ -120,13 +122,13 @@ static int fuse_device_filt_read(struct knote *kn, long hint);
static int fuse_device_filt_write(struct knote *kn, long hint);
static void fuse_device_filt_detach(struct knote *kn);
-struct filterops fuse_device_rfiltops = {
+static const struct filterops fuse_device_rfiltops = {
.f_isfd = 1,
.f_detach = fuse_device_filt_detach,
.f_event = fuse_device_filt_read,
};
-struct filterops fuse_device_wfiltops = {
+static const struct filterops fuse_device_wfiltops = {
.f_isfd = 1,
.f_event = fuse_device_filt_write,
};
@@ -152,7 +154,7 @@ fdata_dtor(void *arg)
FUSE_LOCK();
fuse_lck_mtx_lock(fdata->aw_mtx);
/* wakup poll()ers */
- selwakeuppri(&fdata->ks_rsel, PZERO + 1);
+ selwakeuppri(&fdata->ks_rsel, PZERO);
/* Don't let syscall handlers wait in vain */
while ((tick = fuse_aw_pop(fdata))) {
fuse_lck_mtx_lock(tick->tk_aw_mtx);
@@ -193,7 +195,7 @@ fuse_device_filter(struct cdev *dev, struct knote *kn)
kn->kn_fop = &fuse_device_wfiltops;
error = 0;
} else if (error == 0) {
- error = EINVAL;
+ error = EXTERROR(EINVAL, "Unsupported kevent filter");
kn->kn_data = error;
}
@@ -319,7 +321,7 @@ again:
"we know early on that reader should be kicked so we "
"don't wait for news");
fuse_lck_mtx_unlock(data->ms_mtx);
- return (ENODEV);
+ return (EXTERROR(ENODEV, "This FUSE session is about to be closed"));
}
if (!(tick = fuse_ms_pop(data))) {
/* check if we may block */
@@ -331,7 +333,10 @@ again:
err = msleep(data, &data->ms_mtx, PCATCH, "fu_msg", 0);
if (err != 0) {
fuse_lck_mtx_unlock(data->ms_mtx);
- return (fdata_get_dead(data) ? ENODEV : err);
+ if (fdata_get_dead(data))
+ err = EXTERROR(ENODEV,
+ "This FUSE session is about to be closed");
+ return (err);
}
tick = fuse_ms_pop(data);
}
@@ -361,8 +366,8 @@ again:
FUSE_ASSERT_MS_DONE(tick);
fuse_ticket_drop(tick);
}
- return (ENODEV); /* This should make the daemon get off
- * of us */
+ /* This should make the daemon get off of us */
+ return (EXTERROR(ENODEV, "This FUSE session is about to be closed"));
}
SDT_PROBE2(fusefs, , device, trace, 1,
"fuse device read message successfully");
@@ -385,7 +390,7 @@ again:
fdata_set_dead(data);
SDT_PROBE2(fusefs, , device, trace, 2,
"daemon is stupid, kick it off...");
- err = ENODEV;
+ err = EXTERROR(ENODEV, "Partial read attempted");
} else {
err = uiomove(buf, buflen, uio);
}
@@ -403,12 +408,14 @@ fuse_ohead_audit(struct fuse_out_header *ohead, struct uio *uio)
SDT_PROBE2(fusefs, , device, trace, 1,
"Format error: body size "
"differs from size claimed by header");
- return (EINVAL);
+ return (EXTERROR(EINVAL, "Format error: body size "
+ "differs from size claimed by header"));
}
if (uio->uio_resid && ohead->unique != 0 && ohead->error) {
SDT_PROBE2(fusefs, , device, trace, 1,
"Format error: non zero error but message had a body");
- return (EINVAL);
+ return (EXTERROR(EINVAL, "Format error: non zero error, "
+ "but message had a body"));
}
return (0);
@@ -439,13 +446,12 @@ fuse_device_write(struct cdev *dev, struct uio *uio, int ioflag)
err = devfs_get_cdevpriv((void **)&data);
if (err != 0)
return (err);
- mp = data->mp;
if (uio->uio_resid < sizeof(struct fuse_out_header)) {
SDT_PROBE2(fusefs, , device, trace, 1,
"fuse_device_write got less than a header!");
fdata_set_dead(data);
- return (EINVAL);
+ return (EXTERROR(EINVAL, "fuse_device_write got less than a header!"));
}
if ((err = uiomove(&ohead, sizeof(struct fuse_out_header), uio)) != 0)
return (err);
@@ -453,7 +459,7 @@ fuse_device_write(struct cdev *dev, struct uio *uio, int ioflag)
if (data->linux_errnos != 0 && ohead.error != 0) {
err = -ohead.error;
if (err < 0 || err >= nitems(linux_to_bsd_errtbl))
- return (EINVAL);
+ return (EXTERROR(EINVAL, "Unknown Linux errno", err));
/* '-', because it will get flipped again below */
ohead.error = -linux_to_bsd_errtbl[err];
@@ -521,7 +527,7 @@ fuse_device_write(struct cdev *dev, struct uio *uio, int ioflag)
memcpy(&tick->tk_aw_ohead, &ohead,
sizeof(ohead));
tick->tk_aw_handler(tick, uio);
- err = EINVAL;
+ err = EXTERROR(EINVAL, "Unknown errno", ohead.error);
} else {
memcpy(&tick->tk_aw_ohead, &ohead,
sizeof(ohead));
@@ -542,6 +548,13 @@ fuse_device_write(struct cdev *dev, struct uio *uio, int ioflag)
} else if (ohead.unique == 0){
/* unique == 0 means asynchronous notification */
SDT_PROBE1(fusefs, , device, fuse_device_write_notify, &ohead);
+ mp = data->mp;
+ vfs_ref(mp);
+ err = vfs_busy(mp, 0);
+ vfs_rel(mp);
+ if (err)
+ return (err);
+
switch (ohead.error) {
case FUSE_NOTIFY_INVAL_ENTRY:
err = fuse_internal_invalidate_entry(mp, uio);
@@ -564,8 +577,10 @@ fuse_device_write(struct cdev *dev, struct uio *uio, int ioflag)
/* Unimplemented. See comments in fuse_vnops */
default:
/* Not implemented */
- err = ENOSYS;
+ err = EXTERROR(ENOSYS, "Unimplemented FUSE notification code",
+ ohead.error);
}
+ vfs_unbusy(mp);
} else {
/* no callback at all! */
SDT_PROBE1(fusefs, , device, fuse_device_write_missing_ticket,
@@ -582,7 +597,7 @@ fuse_device_write(struct cdev *dev, struct uio *uio, int ioflag)
*/
err = 0;
} else {
- err = EINVAL;
+ err = EXTERROR(EINVAL, "FUSE ticket is missing");
}
}