Skip to content

Commit

Permalink
fusefs: FUSE_NOTIFY_INVAL_* must busy the mountpoint
Browse files Browse the repository at this point in the history
Unusually, the FUSE_NOTIFY_INVAL_INODE and FUSE_NOTIFY_INVAL_ENTRY
messages are fully asynchronous.  The server sends them to the kernel
unsolicited.  That means that unlike every other fuse message coming
from the server, these two arrive to a potentially unbusied mountpoint.
So they must explicitly busy it.  Otherwise a page fault could result if
the mountpoint were being unmounted.

Reported by:	[email protected]
MFC after:	2 weeks
  • Loading branch information
asomers committed Dec 13, 2024
1 parent 8ae6247 commit 9899985
Showing 1 changed file with 8 additions and 1 deletion.
9 changes: 8 additions & 1 deletion sys/fs/fuse/fuse_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,6 @@ 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,
Expand Down Expand Up @@ -542,6 +541,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);
Expand All @@ -566,6 +572,7 @@ fuse_device_write(struct cdev *dev, struct uio *uio, int ioflag)
/* Not implemented */
err = ENOSYS;
}
vfs_unbusy(mp);
} else {
/* no callback at all! */
SDT_PROBE1(fusefs, , device, fuse_device_write_missing_ticket,
Expand Down

0 comments on commit 9899985

Please sign in to comment.