Hacker News new | ask | show | jobs
by loeg 1404 days ago
Is BUSE significantly different from CUSE (“character device”)?

https://lwn.net/Articles/308445/

1 comments

Yep! Character devices are much closer to "stream of bytes", and from the FUSE perspective they look like a single file with limited operations (open, close, read, write). Think of something like a mouse (sending a stream of motion/click events) or a webcam (send stream of frames, receive basic control commands). If you've written even the most basic FUSE layer, you've got all the necessary handlers to implement CUSE too.

Block devices operate on blocks of data identified by offset. Hard disks, CD-ROM drives, USB sticks, basically anything where it'd make sense to say "read (or write) these 1024 bytes at offset 0x10000".

You can in principle implement a block device-ish API in FUSE by disabling open/close and requiring all reads/writes to be at given offsets -- IIRC this is how the "fuseblk" mode added for ntfs-3g works -- but the protocol is too chatty to be fast enough for things people want block devices for.

I've also heard the kernel's block layer error handling doesn't interact well with the FUSE protocol, but I don't know the details too well on that.

> Block devices operate on blocks of data identified by offset.

Sure, although CUSE read and write operations take offsets, too. The kernel could just send block-sized IOs to a CUSE driver and it wouldn't be all that different.

> You can in principle implement a block device-ish API in FUSE by disabling open/close and requiring all reads/writes to be at given offsets

Right, ok.

I think the historical distinction between block and character devices is largely that -- historical. Nowadays the distinction is mostly whether or not the kernel puts a block cache in front of the device. FreeBSD eliminated the distinction entirely.

There may be kernels that have simplified their device model to unify character and block devices, but Linux has not. FUSE/CUSE (and now ublk) are Linux-oriented protocols from the beginning, with relatively little thought given to cross-platform compatibility.

If you use FreeBSD then you're likely familiar with the challenges they've faced adapting FUSE to their VFS, and last time I checked they don't have plans to support CUSE at all.

You might also be interested in <https://lwn.net/Articles/343514/> (from 2009!), which discusses some of the challenges with using something like the FUSE protocol to back a block device in Linux. That message also describes a better solution which, to my eyes, looks a lot like ublk.

FreeBSD does have CUSE, for what it’s worth.
FreeBSD has a /dev/cuse device, and a libcuse reimplemented on top of it, but it uses a different protocol from Linux's CUSE. You can see the FreeBSD implementation at https://github.com/freebsd/freebsd-src/blob/release/13.1.0/s... -- note how cuse_server_read() and cuse_server_write() are stubs.

I am somewhat familiar with this because I wrote a FUSE/CUSE server library in Rust, and tried porting it to FreeBSD. The FUSE bits worked with only minor issues[0][1], but the CUSE bits were completely different so I had to turn off that part of the library for FreeBSD targets.

[0] https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=253411

[1] https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=253500