How to create loop devices on Linux

A loop device is a pseudo-device which doesn’t correspond to a real, physical block device, but can be used to make a file appear and be treated like one. To manage loop devices on Linux, we can use the losetup command: the utility let us create new loop devices, detach them and retrieve information about existing ones.

In this article we learn how to use losetup to perform the aforementioned actions.

In this tutorial you will learn:

  • What is a loop device
  • How to retrieve information about existing loop devices
  • How to create loop device
  • How to detach a loop device
How to create loop devices on Linux

Software requirements and conventions used

Software Requirements and Linux Command Line Conventions
Category Requirements, Conventions or Software Version Used
System Distribution-independent
Software losetup
Other Root permissions to perform administrative tasks
Conventions # – requires given linux-commands to be executed with root privileges either directly as a root user or by use of sudo command
$ – requires given linux-commands to be executed as a regular non-privileged user

Introducing losetup

On Linux, the losetup command is what we use to interact with loop devices: we can use it to create, list and remove them. The command is part of the core packages of the majority of Linux distribution, so there is no need to install it explicitly. As the first thing, let’s start to see how we can retrieve information about the status of existing loop devices.

Retrieving information about existing loop devices

To list the loop devices existing in the system and get their status, all we have to do is to invoke losetup without specifying any option or argument, or to be more explicit, use the --list option. For the sake of this tutorial I already created a loop device: /dev/loop0:

$ losetup
/dev/loop0         0      0         0  0 /home/egdoc/Downloads/block0   0     512

When we invoke losetup as we did above, information about all existing loop devices are reported. If we want to investigate the status of a specific loop device, instead, we must pass it as argument to the command. To get information about the /dev/loop0 device only, for example, we would run:

$ losetup /dev/loop0

As we can see above, the output of the command includes 7 columns by default:

NAME The name of the loop device
SIZELIMIT The size limit of the file in bytes
OFFSET The offset from the beginning
AUTOCLEAR The status of the “autoclear” flag (we will talk about this later)
RO Whether the device is read-only or not
BACK-FILE The file associated with the loop device
DIO Whether access to the backing file with direct-io is active or not
LOG-SEC The size of the logical sector expressed in bytes

There are also other available columns, not displayed by default:

BACK-INO The inode of the backing file
BACK-MAJ:MIN The backing file major:minor device number
MAJ:MIN The loop device major:minor number

The columns that must be included in the output can be specified by using the -o option (short for --output). To include only the NAME and BACK-FILE columns, for example, we would run:

$ losetup --output=NAME,BACK-FILE /dev/loop0

We would obtain the following output:

/dev/loop0 /home/egdoc/Downloads/block0

To include all the available columns, instead, we can simply use the --output-all option.  The output produced by losetup, as we saw above, is formatted as a list. We have, however, the option to format it as JSON: this can be especially useful if we intend to later parse the retrieved information with other programming languages. All we have to do is to use the --json option. Here is how the output changes:

$ losetup --json --list /dev/loop0
   "loopdevices": [
         "name": "/dev/loop0",
         "sizelimit": 0,
         "offset": 0,
         "autoclear": false,
         "ro": false,
         "back-file": "/home/egdoc/Downloads/block0",
         "dio": false,
         "log-sec": 512

Creating a loop device

Let’s see how to create a new loop device. As a first thing we need to create the file which will be treated as a block device. To create a file just composed by 0s, we can use ddand /dev/zero as input. We will create a file named blockfile with a size of 5GiB by specifying a block size of 1M and writing 5120 blocks:

$ dd if=/dev/zero of=blockfile bs=1M count=5120

Once the task is over, dd will respond with the following output:

5120+0 records in
5120+0 records out
5368709120 bytes (5.4 GB, 5.0 GiB) copied, 28.8846 s, 186 MB/s

The next step is to actually create the loopdevice. As we already said we use losetup to perform the task. The syntax to be used is really simple: we provide the name of the loop device as first argument, and the path to the file we want to map to it as second:

$ sudo losetup /dev/loop0 blockfile

In certain situations a specific loop device could be already in use. In this case, for example, we know that /dev/loop0 was already in use by the block device I created as an example. How can we know what to use? To find the first unused block device, we can invoke losetup with the -f option (short for --find):

$ sudo losetup -f blockfile

If losetup is invoked with the -f option, without any other argument, it will just return name of the first available block device instead of actually mapping the file:

$ sudo losetup -f

Another useful option we want to use when creating a loop device is -P or --partscan: this will force the kernel to re-scan for existing partition tables. Once the loop device is created, it is listed as any other block device. It is included in the output of lsblk, for example (in the TYPE column you can see that the device is reported as “loop”):

NAME                                      MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS
loop1                                       7:1    0     5G  0 loop  

We can use the loop device just like any other block device: we can create a partition table, partitions and filesystems on it, for example:

$ sudo parted -s /dev/loop1 mklabel msdos
$ sudo parted -s /dev/loop1 mkpart primary 1MiB 100%
$ sudo mkfs.ext4 /dev/loop1p1

Notice how, once it is created, the first partition of the loop device is reported with the p1 notation. In the example we created an ext4 filesystem on it, which now can be mounted as usual:

$ sudo mount /dev/loop1p1 /mnt

A typical case in which a loop device is automatically created on Linux, is when we mount an ISO file, like for example a distribution installer image (the iso file is mounted in read-only mode, of course):

$ sudo mount Fedora-Server-netinst-x86_64-35-1.2.iso /mnt
mount: /mnt: WARNING: source write-protected, mounted read-only.

Once the iso is mounted, files inside of it are easy accessible:

ls -l /mnt
total 11
drwxrwxr-x. 1 root root 2048 Oct 26 04:14 EFI
-rw-r--r--. 1 root root 2574 Oct 11 19:31 Fedora-Legal-README.txt
drwxrwxr-x. 1 root root 2048 Oct 26 04:14 images
drwxrwxr-x. 1 root root 2048 Oct 26 04:14 isolinux
-rw-r--r--. 1 root root 1063 Oct 11 19:29 LICENSE

Detaching a loop device

To detach a loop device, all we have to do is to invoke losetup together with the -d option, which is the short for --detach and pass the path of the loop device we want to detach. To detach the /dev/loop0 device, we would run:

$ sudo losetup -d /dev/loop0

In case we want to detach all existing loop devices, instead, we can use the -D option (capital “d”), or the long --detach-all version. On recent Linux kernel versions (>=3.7), if we detach a loop device which is in use by the system, for example when one or more partitions existing on it are mounted, no errors will be returned; the AUTOCLEAR flag of the device will be set to 1 instead, and the device will be destroyed later (this feature is called “lazy destruction”):

/dev/loop0         0      0         1  0 /home/egdoc/blockfile   0     512

Closing thoughts

In this tutorial we learned what is a loop device, and we saw how to retrieve information about existing loop devices on Linux, and how to create and detach loop devices on Linux using the losetup utility.

Comments and Discussions
Linux Forum