6

How do I discover, for a given top-level directory, which “real” filesystems are mounted there, and from which devices (may include UUID or LABEL, but must use /dev/something for LVM)?

Background is automated fstab(5) generation from a script that would run after debootstrap; the host OS is GNU/Linux (I think not everything I use in subroutines is GNU/kFreeBSD‑ or GNU/Hurd-safe).

The closest thing I’ve found so far is findmnt -l --real but this still shows bind mounts, which aren’t “real enough” for my use case, I need block device-backed mountpoints. (This may include loop mounts.)

mirabilos
  • 1,733
  • a bind mount is indistinguishable from the original even if it accesses only part of that file system. this is done as a way to indicate the path in a way that keeps kernel code simple and secure, as well as sharing as much memory data, like cache, as possible. you can unmount the original and the bind mount is still as real. both are always equally real. – Skaperen May 18 '22 at 00:45
  • @Skaperen this is wrong (see the first answer and my first comment on it). – mirabilos May 18 '22 at 18:33

2 Answers2

8

From the perspective of the Linux kernel, there is no difference between bind mounts and "regular" mounts. They are conceptually closer to hard links than symbolic links.

Nevertheless you can narrow it down somewhat with e.g.

findmnt -lv --real --output "FSROOT,SOURCE,TARGET,FSTYPE,OPTIONS" | grep "^/\s"

This filters out all mounts which have a FSROOT (path in the mounted filesystem that is linked to the mountpoint) other than /.

Bind mounts that remount the whole filesystem like

mount /dev/sda /a
mount --bind /a /b

are harder to detect. You need to further filter the list by comparing the SOURCE or MAJ:MIN columns and remove duplicates that way.

There are still some edge cases (e.g. bind mounts to subdirectories/files starting with a space character are falsely accepted by the regex and Btrfs subvolume mounts look like bind mounts so they are removed from the list) but this should give you a starting point.

cg909
  • 7,082
  • perhaps a better name for bind mounts is shared mounts. – Skaperen May 18 '22 at 00:47
  • Hmm, but the SOURCE column already has [sourcepath] for bindmounts (other than the whole-filesystem ones), so detecting them is probably possible (see if the path exists, filter out if not). I guess I’ll have to write that part myself, then. And hope that this method doesn’t filter out too much… – mirabilos May 18 '22 at 18:32
  • 1
    @mirabilos findmnt by default doesn't display the FSROOT column I used in my answer and instead puts the path in brackets (if not /) into the SOURCE column. It often signifies a bind mount but may also be a Btrfs subvolume mount, so you always need to handle some edge cases. – cg909 May 19 '22 at 14:16
  • Yeah, I figure so now, too. Parsing findmnt(8) output is a PITA (it encodes things in hex but fstab(5) only supports octal; it doesn’t list things in a way you can read with shell; etc.) but I guess I’ll list sufficient columns (notably FSROOT but also {,PART}{UUID,LABEL} to use for nōn-LVM sources) and deal with bind mounts somehow. No idea about btrfs. It’s only meant to pre-fill fstab anyway, so the user would possibly still need to edit it (e.g. to add the swap device). – mirabilos May 19 '22 at 20:37
0

This is what I would do (if I understand what all you are asking)

  1. alias lsblk2='lsblk -o size,fstype,model,name,serial,uuid'
  2. lsblk2
  3. first observe all the block devices that linux sees, and with seeing FSTYPE you'll be able to judge what is where and what you want
  4. I would recommend not mounting by device-name such as /dev/sda because as disks come and go then sda can become a different disk, so it is better to mount by uuid.
  5. view /etc/mtab to see what is currently mounted, and view /etc/fstab for what would be mounted after booting.
  6. based on the display from lsblk2 add or adjust /etc/fstab accordingly

three sample /etc/fstab entries:

UUID=800e924a-a869-4152-9503-9d9cfecbd16e              /                       xfs     defaults        0 0
UUID=4f3da85a-71a9-4f6e-bc5f-dfd23a880b08              /boot                   xfs     defaults        0 0
/dev/disk/by-uuid/e0791b9e-b620-4274-9857-78389b10f5a5 /data auto nosuid,nodev,nofail,x-gvfs-show 0 0

simply type mount to see all currently mounted filesystems

type just findmnt, on rhel 7.9 this is what I get:

TARGET                                SOURCE      FSTYPE       OPTIONS
/                                     /dev/sda3   xfs          rw,relatime,seclabel,attr2,inode64,logbsize=64k,sunit=128,swidth=
├─/sys                                sysfs       sysfs        rw,nosuid,nodev,noexec,relatime,seclabel
│ ├─/sys/kernel/security              securityfs  securityfs   rw,nosuid,nodev,noexec,relatime
│ ├─/sys/fs/cgroup                    tmpfs       tmpfs        ro,nosuid,nodev,noexec,seclabel,mode=755
│ │ ├─/sys/fs/cgroup/systemd          cgroup      cgroup       rw,nosuid,nodev,noexec,relatime,seclabel,xattr,release_agent=/usr
│ │ ├─/sys/fs/cgroup/net_cls,net_prio cgroup      cgroup       rw,nosuid,nodev,noexec,relatime,seclabel,net_prio,net_cls
│ │ ├─/sys/fs/cgroup/cpu,cpuacct      cgroup      cgroup       rw,nosuid,nodev,noexec,relatime,seclabel,cpuacct,cpu
│ │ ├─/sys/fs/cgroup/freezer          cgroup      cgroup       rw,nosuid,nodev,noexec,relatime,seclabel,freezer
│ │ ├─/sys/fs/cgroup/pids             cgroup      cgroup       rw,nosuid,nodev,noexec,relatime,seclabel,pids
│ │ ├─/sys/fs/cgroup/devices          cgroup      cgroup       rw,nosuid,nodev,noexec,relatime,seclabel,devices
│ │ ├─/sys/fs/cgroup/blkio            cgroup      cgroup       rw,nosuid,nodev,noexec,relatime,seclabel,blkio
│ │ ├─/sys/fs/cgroup/perf_event       cgroup      cgroup       rw,nosuid,nodev,noexec,relatime,seclabel,perf_event
│ │ ├─/sys/fs/cgroup/hugetlb          cgroup      cgroup       rw,nosuid,nodev,noexec,relatime,seclabel,hugetlb
│ │ ├─/sys/fs/cgroup/memory           cgroup      cgroup       rw,nosuid,nodev,noexec,relatime,seclabel,memory
│ │ └─/sys/fs/cgroup/cpuset           cgroup      cgroup       rw,nosuid,nodev,noexec,relatime,seclabel,cpuset
│ ├─/sys/fs/pstore                    pstore      pstore       rw,nosuid,nodev,noexec,relatime
│ ├─/sys/firmware/efi/efivars         efivarfs    efivarfs     rw,nosuid,nodev,noexec,relatime
│ ├─/sys/kernel/config                configfs    configfs     rw,relatime
│ ├─/sys/fs/selinux                   selinuxfs   selinuxfs    rw,relatime
│ ├─/sys/kernel/debug                 debugfs     debugfs      rw,relatime
│ └─/sys/fs/fuse/connections          fusectl     fusectl      rw,relatime
├─/proc                               proc        proc         rw,nosuid,nodev,noexec,relatime
│ └─/proc/sys/fs/binfmt_misc          systemd-1   autofs       rw,relatime,fd=35,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,p
│   └─/proc/sys/fs/binfmt_misc        binfmt_misc binfmt_misc  rw,relatime
├─/dev                                devtmpfs    devtmpfs     rw,nosuid,seclabel,size=395484100k,nr_inodes=98871025,mode=755
│ ├─/dev/shm                          tmpfs       tmpfs        rw,nosuid,nodev,seclabel
│ ├─/dev/pts                          devpts      devpts       rw,nosuid,noexec,relatime,seclabel,gid=5,mode=620,ptmxmode=000
│ ├─/dev/hugepages                    hugetlbfs   hugetlbfs    rw,relatime,seclabel
│ └─/dev/mqueue                       mqueue      mqueue       rw,relatime,seclabel
├─/run                                tmpfs       tmpfs        rw,nosuid,nodev,seclabel,mode=755
│ ├─/run/user/3584810                 tmpfs       tmpfs        rw,nosuid,nodev,relatime,seclabel,size=79100268k,mode=700,uid=358
│ │ └─/run/user/3584810/gvfs          gvfsd-fuse  fuse.gvfsd-f rw,nosuid,nodev,relatime,user_id=3584810,group_id=100
│ ├─/run/user/2001                    tmpfs       tmpfs        rw,nosuid,nodev,relatime,seclabel,size=79100268k,mode=700,uid=200
│ └─/run/user/329918                  tmpfs       tmpfs        rw,nosuid,nodev,relatime,seclabel,size=79100268k,mode=700,uid=329
├─/tmp                                tmpfs       tmpfs        rw,seclabel
├─/boot                               /dev/sda2   xfs          rw,relatime,seclabel,attr2,inode64,logbsize=64k,sunit=128,swidth=
│ └─/boot/efi                         /dev/sda1   vfat         rw,relatime,fmask=0077,dmask=0077,codepage=437,iocharset=ascii,sh
├─/data                               /dev/sdb1   xfs          rw,nosuid,nodev,relatime,seclabel,attr2,inode64,logbsize=64k,suni
├─/var/lib/nfs/rpc_pipefs             sunrpc      rpc_pipefs   rw,relatime
├─/bkup                               bkup:/bkup
                                                  nfs4         rw,nosuid,noexec,relatime,vers=4.1,rsize=1048576,wsize=1048576,na
└─/ramdisk                            tmpfs       tmpfs        rw,relatime,seclabel,size=775946240k

with all this in hand not sure what else could be needed to solve any kind of mount issue.

ron
  • 6,575