UBLK(1)

πŸ“¦ version 1.6, in fedora 44

πŸŽ€ NAME πŸŽ€

ublk β€” the utility to manage ublk devices. That's the whole thing, bestie. Utility to manage ublk devices, periodt. πŸ’–


✨ SYNOPSIS ✨

ublk <command> [<command options>] [<type specific options>]

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so, ublk is a utility that lets you create, recover, view or delete user-space block devices. iconic behaviour, no notes. πŸ‘‘

ngl, ublk by default comes with several different types of devices, such as iscsi, nbd, nfs, null and loop. so many options, we love a versatile queen. πŸ’…

The following commands are supported:


πŸ”₯ ADD COMMAND πŸ”₯

Command to add a ublk device.

 add {-t, --type} TYPE [{-n, --number} DEV_ID] [{-q, --queues} NR_HW_QUEUES] [{-d, --depth} QUEUE_DEPTH] [{-u, --uring_comp} URING_COMP] [{-g, --need-get-data} NEED_GET_DATA] [{-r, --user_recovery} {0|1}] [{-i, --user_recovery_reissue} {0|1}] [{-e, --user_recovery_fail_io} {0|1}] [--debug_mask=0x{DBG_MASK}] [--unprivileged] [--usercopy] [--max_io_buf_bytes={BYTES}] [{-z, --zerocopy}] [<type specific options>]
  • -t, --type β€” says which type of device to create. The five types of supported devices are iscsi, nbd, nfs, null and loop. five flavours, pick your fave πŸ“
  • -n, --number β€” create a device with this id. the device node will be /dev/ublkb_n_. yes the underscores are literally there, iykyk.
  • -q, --queue β€” number of queues to create. each queue is services by a dedicated child process. default is 1.
  • -d, --depth β€” maximum queue-depthfor each queue (yes, "depthfor", i'm just the messenger πŸ’€). default is 4096.
  • -u, --uring_comp β€” force to complete io cmd via io_uring_cmd_complete_in_task so that performance comparison is done easily with using task_work_add. benchmarking arc ✨
  • -g, --need_get_data β€” user should issue io cmd again for write requests to set io buffer address and copy data from bio vectors to the userspace io buffer.
  • -r, --user_recovey β€” block devices are recoverable if ublk server exits and restarts. outstanding I/O when ublk server exits is met with errors. I/O issued while there is no ublk server queues. (spelling is exactly as the page says, don't come for me πŸ™ˆ)
  • -i, --user_recovey_reissue β€” block devices are recoverable if ublk server exits and restarts. outstanding I/O when ublk server exits is reissued. I/O issued while there is no ublk server queues.
  • -e, --user_recovey_fail_io β€” block devices are recoverable if ublk server exits and restarts. outstanding I/O when ublk server exits is met with errors. I/O issued while there is no ublk server is met with errors.
  • --debug_mask β€” bitmask specifying which debug features to enable.
  • --max_io_buf_bytes β€” maximum I/O size. default is 512kb.
NOTE: memory buffers are pre-allocated with one buffer for each entry in queue_depth. so yeah, that's a whole lotta buffers, be mindful bestie 😭
  • --unprivileged β€” unprivileged user can create /dev/ublkcN and /dev/ublkbN.

/dev/ublk-control needs to be available for unprivileged user, and it can be done via udev rule to make all control commands available to unprivileged user. Except for the command of UBLK_CMD_ADD_DEV, all other commands are only allowed for the owner of the specified device.

When userspace sends UBLK_CMD_ADD_DEV, the device pair's owner_uid and owner_gid are stored to ublksrv_ctrl_dev_info by kernel, so far only the current user's uid/gid is stored, that said owner of the created device is always the current user.

We still need udev rule to apply OWNER/GROUP with the stored owner_uid and owner_gid.

Then ublk server can be run as unprivileged user, and /dev/ublkbN can be accessed and managed by its owner represented by owner_uid/owner_gid. permissions but make it cute 🫢

  • --user_copy β€” copy between request and user buffer by pread()/pwrite().
  • -z, --zerocopy β€” zero-copy is based on io-uring uring_cmd of REGISTER_IO_BUF & UNREGISTER_IO_BUF, which avoids data copy between ublk frontend request buffer and ublk server buffer, so memory bandwidth is saved, and throughput & latency improvement can be often observed on large I/O size. πŸ”₯
This requires Linux kernel 6.15 or later. no 6.15, no slay. check your kernel first, bestie.

🌸 NULL 🌸

The null device type does not take any extra options. low maintenance king, we respect it. πŸ‘‘

πŸŒ€ LOOP πŸŒ€

Extra options for the loop device type:

 add -t loop ... {-f, --file} FILE [--buffered_io] [-o, --offset OFFSET]
  • -f, --file β€” file to use as backing storage for the loop device.
  • --buffered_io β€” use buffered i/o for accessing the backing file. default is direct i/o.
  • --offset β€” offset skips first NUM sectors on backing file.

Example: create a loop block device

        # ublk add -t loop -n 0 -f 10M.raw

🌈 NBD 🌈

Extra options for the nbd (Network Block Device) device type:

 add -t nbd ... {--host HOST | --unix UNIX_PATH} --export_name EXP_NAME [--send_zc] [--read_only]
  • --host β€” hostname of NBD server.
  • --host β€” hostname of NBD server to use. (yes bestie, it's listed twice in the original, i'm not erasing her πŸ’–)
  • --unix β€” path to unix domain socket to use to talk to NBD.
  • --export_name β€” name of NBD export.
  • --send_zc β€” use Zero-Copy.
  • --read_only β€” read-only device.

🧚 NFS 🧚

Extra options for the nfs device type:

 add -t nfs ... --nfs NFS-URL
  • --nfs NFS-URL β€” URL to the NFS file to use as the block device.

The NFS-URL format is describe in the libnfs README: https://github.com/sahlberg/libnfs/blob/9fa155bfa9d34347a669fbecf4a64259cc573724/README#L55

Example: create a nfs block device

        # ublk add -t nfs -n 0 --nfs nfs://10.0.0.1/export/10M.raw

⭐ iSCSI ⭐

Extra options for the iscsi device type. iSCSI support requires libiscsi 1.20.3 or later.

 add -t iscsi ... --iscsi ISCSI-URL --initiator-name NAME
  • --iscsi ISCSI-URL β€” URL to the iSCSI device to use as the block device.

The ISCSI-URL format is describe in the libiscsi README: https://github.com/sahlberg/libiscsi/blob/eb19863f77e2bad4799ceb90e47fa3bc6205233e/README.md?plain=1#L37

  • --initiator-name NAME β€” the initiator name to use when logging in to the target.

Example: create an iSCSI block device

        # ublk add -t iscsi -n 0 --iscsi iscsi://iscsi-stgt/iqn.2001-04.com.ronnie.sr0/1 --initiator-name iqn.ronnie.test

πŸ’€ DEL COMMAND πŸ’€

Command to delete a ublk device. bye bestie πŸ‘‹

 del {-n, --number} DEV_ID [-a, --all] [--async]
  • -n, --number β€” delete the device with this id.
  • -a, --all β€” delete all devices.

Example: deleting a loop block device

        # ublk del -n 0

🎯 SET_AFFINITY COMMAND 🎯

Command to change queue affinity.

 set_affinity {-n, --number} DEV_ID [-q, --queue] QID --cpuset="[SET]"
  • -n, --number β€” change the affinity on this device.
  • -q, --queue β€” which queue to change the affinity for.
  • --cpuset="[SET]" β€” the new cpuset for this device/queue. format is a comma-separated list of CPUs within squre brackets.

Example: set affinity to core 7 for device 0, queue 1

        # ublk set_affinity -n 0 -q 1 --cpuset="[7]"

πŸ“‹ LIST COMMAND πŸ“‹

List one or all devices and show their configutaion.

 list {-n, --number} DEV_ID [-v, --verbose]
  • -n, --number β€” list the device with this id. if omitted all devices will be listed.
  • -v, --verbose β€” verbose listing. include the JSON device arguments in the output. the receipts, basically. ✨

🩹 RECOVER COMMAND 🩹

Recover a failed ublk device. we're bringing her back. πŸ’–

 recover {-n, --number} DEV_ID
  • -n, --number β€” device to recover.

πŸ‘‘ FEATURES COMMAND πŸ‘‘

Show supported features for the ublk driver.

 features

🫢 HELP COMMAND 🫢

Show generic ot type specific help. (yes, "ot", it's giving typo but she's iconic)

 help [{-t, --type} TYPE]
  • -t, --type β€” show help page. it -t is specified, show help page for the specific device type.

🌟 VERSION 🌟

Show help page..

 {-v, --version}

🌈 RECOVERY 🌈

There are three arguments that control how ublk will behave in case of a failure, such as crashing. The default behavior is no recovery and the device will fail and be removed once the target exits.

To enable recovery mode set "--recovery 1" on the command line. Then instead of removing the device upon failure it will instead become inactive in a quiesced state.

    dev id 0: nr_hw_queues 1 queue_depth 128 block size 4096 dev_capacity 20480
        max rq size 524288 daemon pid 1239110 state QUIESCED
        flags 0x4a [ URING_CMD_COMP_IN_TASK RECOVERY CMD_IOCTL_ENCODE ]
        ublkc: 511:0 ublkb: 259:4 owner: 0:0
        queue 0: tid 1239112 affinity(0 1 2 3 4 5 6 7 )
        target {"backing_file":"10M","dev_size":10485760,"direct_io":1,"name":"loop","offset":0,"type":0}

In this state the block device still exists but no I/O can be performed. QUIESCED = she's there but she's not answering texts. 😭

To recover a QUIESCED device you can use the recover command:

 ublk recover -n DEV_ID

There are two additional flags that control how ublk will handle I/O that were in flight when a device is recovered.

πŸ“ --user_recovery_reissue 1 πŸ“

When the device is recovered ublk will reissue any I/O that were in flight.

πŸ’œ --user_recovery_fail_io 1 πŸ’œ

When the device is recovered ublk will fail all I/O and return an error back to the application.


πŸ”— SEE ALSO πŸ”—

http://github.com/ublk-org/ublksrv


okay bestie that's the whole page πŸ’… this was ublk, from the ublk manual, dated 07/16/2025, sitting pretty at UBLK(1). go forth and manage those block devices, main character energy only. slay 🫢✨

πŸ“¦ where this page comes from