Minimal runnable example
First we create a test filesystem as explained here:
mkdir sysroot
dd if=/dev/urandom of=sysroot/myfile bs=1024 count=1024
virt-make-fs --format=raw --type=ext2 sysroot sysroot.ext2
Now:
$ mkdir mnt
$ # mount can deduce "-o loop -t ext2" nowadays.
$ sudo mount sysroot.ext2 mnt
$ # Mount worked fine.
$ cmp mnt/myfile sysroot/myfile
$ losetup
NAME SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE DIO LOG-SEC
/dev/loop0 0 0 1 0 /home/ciro/sysroot.ext2 0 512
$ # I don't trust userland.
$ cat /sys/devices/virtual/block/loop0/loop/autoclear
1
$ sudo umount
$ losetp
$
Therefore we see that mount:
- creates a loop device
- sets AUTOCLEAR for it by default-o loop -t ext2
and then when umount sees AUTOCLEAR is set, it automatically destroys the file.
Minimal counter example
By creating the loop device manually with losetup, we can see what happens when AUTOCLEAR is not set:
$ sudo losetup /dev/loop0 sysroot.ext2
losetup: sysroot.ext2: Warning: file does not fit into a 512-byte sector; the end of the file will be ignored.
$ losetup
NAME SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE DIO LOG-SEC
/dev/loop0 0 0 0 0 /home/ciro/sysroot.ext2 0 512
$ cat /sys/devices/virtual/block/loop0/loop/autoclear
0
$ sudo mount /dev/loop0 mnt
$ cmp mnt/myfile sysroot/myfile
$ sudo umount mnt
$ losetup
NAME SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE DIO LOG-SEC
/dev/loop0 0 0 0 0 /home/ciro/sysroot.ext2 0 512
$ sudo mount /dev/loop0 mnt
$ sudo umount -d mnt
$ losetup
So we see that:
umount without options did not clear the loop device for us
umount -d did clear it
Alternatively, we can also detach the loop device with:
sudo mount /dev/loop0 mnt
sudo umount mnt
sudo losetup -d /dev/loop0
Automatic losetup on used filesystem
man losetup says:
-d Detach the file or device associated with the specified loop device(s). Note that since Linux v3.7 kernel uses "lazy device destruction". The detach operation does not return EBUSY error anymore if device is actively used by system, but it is marked by autoclear flag and destroyed later.
and we verify with:
$ sudo losetup /dev/loop0 sysroot.ext2
$ sudo mount /dev/loop0 mnt
$ cat /sys/devices/virtual/block/loop0/loop/autoclear
0
$ sudo losetup -d /dev/loop0
$ cat /sys/devices/virtual/block/loop0/loop/autoclear
1
$ # Still mounted.
$ cmp mnt/myfile sysroot/myfile
$ sudo umount mnt
$ losetup
$
So we see that if you do losetup -d befor umount, it sets autoclear automatically.
Low level view
A quick:
sudo strace mount sysroot.ext2 mnt
shows that the main system calls are:
openat(AT_FDCWD, "/dev/loop0", O_RDWR|O_CLOEXEC) = 4
ioctl(4, LOOP_SET_STATUS64, {lo_offset=0, lo_number=0, lo_flags=LO_FLAGS_AUTOCLEAR, lo_file_name="/home/ciro/sysroot.ext2", ...}) = 0
mount("/dev/loop0", "/home/ciro/test/libguestfs/mnt", "ext2", MS_MGC_VAL, NULL) = 0
so we see that losetup operations are basically done through ioctl.
The kernel source v4.17 of interest is:
Have a look at this minimal example If you are not familiar with ioctl: https://stackoverflow.com/questions/2264384/how-do-i-use-ioctl-to-manipulate-my-kernel-module/44613896#44613896
Tested on Ubuntu 18.04.