devb-loopback

Pseudo block driver

Note: In order to start this driver, you must be logged in as root.

Syntax:

devb-loopback [loopback loopback_option[,option]]
              [blk option[,option]...] &

Runs on:

QNX Neutrino

Options:

Note: Use commas (,) to separate the options. You can put the blk and loopback groups of options in any order.
loopback options
The loopback options include global and order-dependent options:
  • Global options apply to all fd= instances. You can specify them anywhere in the loopback options.
  • Order-dependent options apply to all subsequent fd= files.
    Note: You can specify multiple occurrences of the order-dependent options with different values. For example, for read-only access for the first device, and read-write access for the second device, specify the following:

    loopback ro,fd=/dev/cd0,rw,fd=/fs/hd/iso.img

The global options include the following:

nio=num
The number of asynchronous I/O threads (which are responsible for executing an internal block device read/write as a normal read/write over the external file descriptor). This multithreading is useful if you've specified multiple fd= devices.

The default is 1. You can specify a value of 0 to force all I/O to be performed synchronously in the context of the filesystem caller; it can be higher to prevent this I/O from becoming a bottleneck to the filesystem layers above (appropriate only when multiple fd= paths have been specified). The pool of threads services requests to all fd= files in the order of client priority.

prefix=name
The name by which the loopback pseudo block devices are registered. The default is lo; thus each fd= entry named on the command line appears as /dev/lo0, /dev/lo1, and so on, in order.

The order-dependent options include the following:

fd=path
Specify a filename (a path registered by your resource manager) to be presented as a block device by devb-loopback. This pathname must support open(), close(), read(), write(), and fstat(); for more information, see "Driver support," below.

Each pathname results in the creation of a corresponding block-special device (see the global prefix= option), the content of which is mirrored over the file descriptor using standard read/write calls. You can then mount traditional block filesystems (such as fs-dos.so and fs-qnx4.so) on top of these pseudo devices and use them transparently.

You can specify multiple fd= pathnames; they're managed by a single devb-loopback process.

rw, ro
Set the access mode to use when opening the underlying file descriptor (corresponds to O_RDWR or O_RDONLY). If you specify read-only, then in turn you can mount only read-only filesystems onto the corresponding devb-loopback device (the pseudo-device is advertised up as DEV_RDONLY). The default is rw.
sync, async
Set the synchronous write mode to use when opening the underlying file descriptor (corresponds to O_SYNC). The effect of this depends on the resource manager responsible for each file (typically it's ignored).
Note: This option affects writes that are presented to the pseudo-device, and not the write behavior of any mounted filesystems above this (that can be controlled via mount options or blk delwri=... commit=...).

The default is sync.

denyno, denyrd, denywr, denyrw
The SH_DENY* mode to use when opening the underlying file descriptor. A deny mode stops other processes from opening the host file, thus preventing its content from being changed behind the back of the devb-loopback filesystems, which prevents coherence issues. The default is denyrw.
seek, xtype
Configure I/O onto the file descriptor using either an LSEEK+READ combined message or via a READ+XTYPE_OFFSET composite. By default, devb-loopback probes the host filesystem to determine whether it supports the pread() and pwrite() API. The default is xtype.
blksz=[size]
Override the device blocksize. This is typically probed from a stat() or DCMD_CAM_DEVINFO devctl() call onto the resource manager responsible for each file and the same value advertised up, but some resource managers don't advertise a useful blocksize (in particular, devf-* reports 1-byte blocks).

You might also need this option in some cases where a filesystem image was originally formatted on a device with a different sector size to that of the hosting filesystem; it may be necessary for correct operation or performance reasons to mimic the original sector size.

This option applies to all subsequent instances of fd=, but you can reset it to use the probed value with an empty option (e.g. blksz=2048,fd=/F1,blksz=,fd=/F2).

heads=num
Specify the number of heads (default 1).
tracks=num
Specify the number of sectors per track (default 1).
blk options
The blk options are as for io-blk.so. If specified, they must follow the blk keyword. For more information, see io-blk.so.

Since devb-loopback loads the standard block device DLLs, which creates a buffer cache using the same default rules as for the disk filesystems, the cache is likely to be too big for devb-loopback. You can reduce the cache size using blk cache=size. Depending on the actual size of the device, and the level of caching already implemented by its driver, a value of 128k may be sufficient.

Description:

The block filesystems in the QNX Neutrino RTOS are implemented as a series of DLL modules and a set of internal APIs. Thus it's possible to mount disk-based filesystems (such as Power-Safe or DOS) only onto released QNX devb-* drivers. The devb-loopback driver implements a mapping between an arbitrary file descriptor and the block API, allowing any resource manager to be used to host a disk filesystem.

Internal function calls, normally targeted at a SCSI/CAM driver, are translated into standard read() and write() calls onto the host file descriptor, and are used to populate the data content of a pseudo block device, which appears to the system as a disk.

Within this framework, any resource-manager or file-descriptor object can be viewed as a block-special device and be mounted as a disk filesystem. For example, you can't normally directly use an ISO9660 image stored on a devf-* device, because devf-* doesn't load fs-*.so modules; by using devb-loopback to present this image file as a block device, you can then mount it using fs-cd.so. For example:

devb-loopback fd=/devf/iso blk automount=lo0:/fs/iso:cd

This results in the following arrangement:

Other uses might be to mount images from /dev/shmem, an image filesystem (IFS), or over NFS.

The host file needs to be pregrown. For example, assuming that /fs/flash is a mounted devf filesystem, you'd have to do the following setup first:

touch /fs/flash/q4.img
dinit -hq -S32m /fs/flash/q4.img

You could then use that file on flash as a read-write fs-qnx4.so filesystem:

devb-loopback blk cache=128k,auto=none loopback fd=/fs/flash/q4.img
mount -tqnx4 /dev/lo0 /q4flash

Using devb-loopback in this case adds functionality that a disk filesystem format offers (access times, hard links, etc.) to the devf-* filesystem. In other cases, devb-loopback lets you use the caching (e.g., names and sectors) that io-blk.so supports, but that the resource manager underlying the host file might not.

Driver support

The resource manager(s) implementing the pathnames specified by fd= operands must support the following standard interfaces:

open(), close()
The device must be able to open and close a file descriptor to it. The O_RDONLY and O_RDWR modes should be supported, as should the SH_DENY* share flags and O_SYNC modifier (if those options are used from the devb-loopback command line); the default libc iofunc open handler is suitable.
fstat()
The device must support a stat method, which is used to determine the size and geometry of the underlying device. The default libc iofunc handler is suitable, provided there's an associated iofunc_mount_t which sets a suitable "blocksize" (the default is 1 byte, which isn't appropriate for use as a block device; it must be one of 512, 1024, 2048, or 4096). See also devctl() (below) and the loopback blksz= option.
read(), write()
The device must support read and write callouts, which are used to transfer "disk blocks" between the device and the filesystem buffer cache. I/O is in units of the advertised block size and within the bounds of the advertised device size. If the device supports the _IO_XTYPE_OFFSET modifier (corresponding to pread() and pwrite()), then that interface is used; otherwise a combined seek plus normal read/write is made.
lseek()
If _IO_XTYPE_OFFSET isn't supported, then the device must implement an lseek method. The default libc iofunc callout is suitable.
devctl()
The device may optionally implement the DCMD_CAM_DEVINFO devctl() command (refer to the <sys/dcmd_cam.h> and <sys/cam_device.h> header files). This allows the device to set certain low-level fields to fine-tune emulation behavior. The DCMD_ALL_GETFLAGS command is also used to probe the status of a (removable) file descriptor. However, suitable defaults for both these can be inferred from the fstat() query.

Mounting

You can mount the filesystem image via the loopback device (/dev/lo*) from the command line with the mount command:

devb-loopback blk cache=256k,vnode=128 \
              loopback ro,blksz=2048,fd=/mnt/EFS/tts.iso &
mount -r -tcd /dev/lo0 /mnt/tts

or via the blk automount= option:

devb-loopback blk cache=256k,vnode=128,automount=lo0:/mnt/tts:cd \
              loopback ro,blksz=2048,fd=/mnt/EFS/tts.iso &

You can use umount to unmount the filesystem. The file descriptors to the underlying host image files aren't closed, and /dev/lo* remain present, until devb-loopback is terminated.