andreasw
andreasw

Reputation: 521

How to write a userspace linux block device driver?

I would like to write a linux block device driver. The driver would not need to access the hardware so it can be in userspace.

To start, I have tried to build an example block device driver with this Makefile:

obj-m = sbd.o
KVERSION = $(shell pwd)
PWD = $(shell pwd)

all:
    make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules

I however get these errors which I do not know how to fix. Here is the stdout and stderr:

make -C /lib/modules/2.6.31-19-generic/build M=/home/andreas/sp/nivoa/src/driver/sbd modules
make[1]: Entering directory `/usr/src/linux-headers-2.6.31-19-generic'
  CC [M]  /home/andreas/sp/nivoa/src/driver/sbd/sbd.o
/home/andreas/sp/nivoa/src/driver/sbd/sbd.c:72: error: expected ‘)’ before ‘*’ token
/home/andreas/sp/nivoa/src/driver/sbd/sbd.c:128: warning: initialization from incompatible pointer type
/home/andreas/sp/nivoa/src/driver/sbd/sbd.c: In function ‘sbd_init’:
/home/andreas/sp/nivoa/src/driver/sbd/sbd.c:143: error: ‘sbd_request’ undeclared (first use in this function)
/home/andreas/sp/nivoa/src/driver/sbd/sbd.c:143: error: (Each undeclared identifier is reported only once
/home/andreas/sp/nivoa/src/driver/sbd/sbd.c:143: error: for each function it appears in.)
/home/andreas/sp/nivoa/src/driver/sbd/sbd.c:146: error: implicit declaration of function ‘blk_queue_hardsect_size’
make[2]: *** [/home/andreas/sp/nivoa/src/driver/sbd/sbd.o] Error 1
make[1]: *** [_module_/home/andreas/sp/nivoa/src/driver/sbd] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-2.6.31-19-generic'
make: *** [all] Error 2

Any help on this would be greatly appreciated.

Thanks, Andreas

Upvotes: 10

Views: 8831

Answers (6)

BZKN
BZKN

Reputation: 1729

In addition to the above useful answers I would like to add that apart from NBD, there are also other ways where Linux Block I/O Layer can be used at userspace. Following are the additional options:

Upvotes: 1

Rich
Rich

Reputation: 976

You can use NBD. Using nbdkit you can even write virtual block devices in shell script or other scripting languages (although stick to C if you want the best performance). I gave a talk about this topic at FOSDEM 2019 where I did a live demo writing a Linux kernel block device in shell script.

Upvotes: 1

schoppenhauer
schoppenhauer

Reputation: 421

While using NBD, as suggested before, is nice, maybe a better way (used by, for example, virtualbox-fuse) is to make a FUSE filesystem that exports one file, which you can then use via losetup.

Upvotes: 5

hillu
hillu

Reputation: 9631

Following MarkR's suggestion, it is even possible to talk the NBD protocol over an AF_UNIX socket pair, so no extra local daemon is needed. The program implementing this protocol will need to set up the socket pair and fork off a child. Both parent and child close one end of the socket pair. One of them starts taking requests on its end of the socket while the other one connects the NBD driver to its end of the socket.

Upvotes: 7

MarkR
MarkR

Reputation: 63616

There isn't an "official" way of doing block drivers in userspace, however people often do it by (ab)using the NBD driver to talk over a loopback network to a daemon which listens on a normal socket and speaks the NBD protocol. See the NBD docs for more info.

Your example is for a kernel-mode block device, which will need to be built as a kernel module. And as the kernel internals are always changing, it's presumably now incompatible.

Upvotes: 16

Ofir
Ofir

Reputation: 8372

Always looks at the first error:

In your case it looks like a problem with include files, e.g. request_queue_t is not defined.

Since this is a deprecated type, you are probably using a version of linux/blkdev.h that is newer than the code example.

Try adding typedef struct request_queue request_queue_t;

Upvotes: 5

Related Questions