--- a/sys/vfs/fuse/fuse_device.c +++ b/sys/vfs/fuse/fuse_device.c @@ -40,8 +40,16 @@ { struct fuse_mount *fmp = data; - if (!fuse_cdevpriv_close(fmp)) + if (fmp->devvp) { + /* mounted: kill it if still alive and drop the open ref */ + fuse_cdevpriv_close(fmp); fuse_mount_free(fmp); + } else { + /* never mounted: refcnt==1, no locks, no cred -- just free + * (the old code leaked this object: fuse_cdevpriv_close() + * returned ENODEV and skipped fuse_mount_free()). */ + kfree(fmp, M_TEMP); + } } static int @@ -49,12 +57,17 @@ { struct fuse_mount *fmp; struct file *fp = ap->a_fpp ? *ap->a_fpp : NULL; + int error; fmp = kmalloc(sizeof(*fmp), M_TEMP, M_WAITOK | M_ZERO); KKASSERT(fmp); refcount_init(&fmp->refcnt, 1); - devfs_set_cdevpriv(fp, fmp, fuse_cdevpriv_dtor); + error = devfs_set_cdevpriv(fp, fmp, fuse_cdevpriv_dtor); + if (error) { + kfree(fmp, M_TEMP); + return error; + } fuse_dbg("open %s\n", ap->a_head.a_dev->si_name); return 0;