How to find which device corresponds to your root filesystem
I recently found something I was looking for for quite a long time. If you use the mount
command in Linux, you can see that the root device is not listed like the other mounted filesystems:
/dev/root on / type ext3 (rw) /dev/mmcblk0p1 on /mmcboot type vfat (rw) proc on /proc type proc (rw) none on /sys type sysfs (rw,noexec,nosuid,nodev) none on /dev type tmpfs (rw,mode=0755) ...
For the /
mount point, you are just told that it corresponds to /dev/root
, which is not the real device you are looking for.
Of course, you can look at the kernel command line and see on which initial root filesystem Linux was instructed to boot (root
parameter):
$ cat /proc/cmdline mem=512M console=ttyS2,115200n8 root=/dev/mmcblk0p2 rw rootwait
However, this doesn’t mean that what you see is the current root device. Many Linux systems boot on intermediate root filesystems (like initramdisks and initramfs), which are just used to access the final one.
I explored the contents of /proc
, but didn’t find any file revealing what the root device is.
Fortunately, I eventually found a command to find the root device:
$ rdev /dev/mmcblk0p2 /
But how does this work? How could we find such information by ourselves? Use the Source, Luke!
When you ask yourself questions like this one, the best is to look at the BusyBox sources which implement this command. These sources are usually simpler than the ones for the same GNU command.
Here is what BusyBox rdev
does… It first runs the stat
system call on the /
directory. Let’s run the stat
command that corresponds to it:
$ stat / File: `/' Size: 4096 Blocks: 8 IO Block: 4096 directory Device: b302h/45826d Inode: 2 Links: 23 Access: (0755/drwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2010-07-21 22:00:01.000000000 +0200 Modify: 2010-06-13 15:04:37.000000000 +0200 Change: 2010-06-13 15:04:37.000000000 +0200
What’s interesting is the Device
field. It means that the device corresponding to /
has the major number b3
in hexadecimal (179
in decimal), and minor number 02
. Bingo, this corresponds to /dev/mmcblk0p2
:
$ ls -l /dev/mmcblk0p2 brw-rw---- 1 root disk 179, 2 Jan 1 1970 /dev/mmcblk0p2
Therefore, what BusyBox rdev
does is walk through /dev
and its subdirectories to find a device file matching the major and minor numbers.
This is not a completely generic solution though. On some very simple embedded systems, you don’t even need to create device files for all existing devices. In particular, the device file for the root filesystem doesn’t have to exist. In such a case, rdev
wouldn’t be able to find the root device.
A more generic solution could be to walk through /sys/block
which enumerates all the block devices present on a system (even if not all of them have an entry in /dev/
. This would allow to find the device with the matching major and minor numbers:
$ cat /sys/block/mmcblk0/mmcblk0p1/dev 179:1
Through this example, you can see how useful it can be to study the sources of system commands to understand how the system works. BusyBox sources, implementing simplified versions of GNU utilities, make this even easier.
Useful info there, thanks – though n.b. it doesn’t work with root mounted over NFS because there’s no entry in sys/block in this case (which is maybe why BusyBox walks /dev).
On some embedded systems the rdev command will fail simply because busybox has been compiled without it. As long as you have a writable device this is not a problem. Simply load a later busybox for your processor from the busybox.net website to that device with a different name and call the command with, for example, /dev/sda/busybox-mipsel rdev.
Hi,
following your hints I came out with this, maybe simplistic, approach:
find_linux_root_device() {
RDEV=$(mountpoint -d /)
for file in $(find /dev);
do
if [ $(stat --printf="%t:%T" "$file") = $RDEV ];
then
ROOTDEVICE="$file"
break;
fi
done
echo "$ROOTDEVICE"
}
What do you think about it?
Thanks,
Antonio
In the code above I forgot to consider that ‘stat’ prints the major and minor number in hex, while ‘mountpoint’ outputs them in decimal.
Something like this should be used:
...
CURRENT_DEVICE=$(printf "%d:%d" $(stat --printf="0x%t 0x%T" "$devnode"))
if [ $CURRENT_DEVICE = $RDEV ];
...
Regards,
Antonio
#/bin/bash
find_linux_root_device() {
RDEV=$(mountpoint -d /)
for file in /dev/* ; do
CURRENT_DEVICE=$(stat -c “%t:%T” $file)
if [ $CURRENT_DEVICE = $RDEV ]; then
ROOTDEVICE=”$file”
break;
fi
done
echo “$ROOTDEVICE”
}
This seems to work for a lot of systems:
#/bin/bash
find_linux_root_device() {
local PDEVICE=`stat -c %04D /`
for file in $(find /dev -type b 2>/dev/null) ; do
local CURRENT_DEVICE=$(stat -c “%02t%02T” $file)
if [ $CURRENT_DEVICE = $PDEVICE ]; then
ROOTDEVICE=”$file”
break;
fi
done
echo “$ROOTDEVICE”
}
Hello Team,
cat /proc/cmdline
console=ttyS0,115200 root=/dev/nfs rw nfsroot=192.168.1.100:/home/nfs/IntelCE,nolock ip=dhcp mem=exactmap memmap=1M@0 memmap=639M@1M
# rdev
0x000c /
How can i increase the size of my root partiotion , it is shown as /dev/root.
Thanks,
Rashmi
Assuming you have no duplicate partitions mounted nor any single partition mounted twice:
df -a | grep "`df -a | grep rootfs | cut -d -f2- | sed 's/^ *//g'`" | cut -d -f1 | tail -1
Basically, run
df -a
to get stats on what it lists asrootfs
and then use that info to scan for what other listing has those stats.on my system, /dev/root is a symlink to /dev/sda1, which is where the system was booted from.
Interesting. What kind of system is this? What distribution is it, or what was used to generate the root filesystem?
As least, this doesn’t seem to be a standard feature. Ubuntu 13.04 with Linux 3.8 doesn’t have such a link.
Thanks!
Michael.
#! /bin/bash
MAJOR_ROOTFS=$(mountpoint -d / | cut -f 1 -d “:”)
MINOR_ROOTFS=$(mountpoint -d / | cut -f 2 -d “:”)
DEV_ROOTFS=$(cat /proc/partitions | awk {‘if ($1 == “‘${MAJOR_ROOTFS}'” && $2 == “‘${MINOR_ROOTFS}'”) print $4 ‘})
echo /dev/$DEV_ROOTFS
However, this script doesn’t work when rootfs is an UBI file system. It fails because “mountpoint” returns wrong major/minor numbers. How can this be solved in a more generic way?
I was just investigating a solution to this and found this command that seems useful:
findmnt
user@someplace:~# findmnt
TARGET SOURCE FSTYPE OPTIONS
/ /dev/mmcblk0p2 ext3 rw,relatime,errors=continue,user_x
|-/dev devtmpfs devtmpfs rw,relatime,size=383868k,nr_inodes
| `-/dev/pts devpts devpts rw,relatime,gid=5,mode=620
|-/proc proc proc rw,relatime
|-/sys sysfs sysfs rw,relatime
| `-/sys/kernel/debug debugfs debugfs rw,relatime
|-/run tmpfs tmpfs rw,nosuid,nodev,mode=755
|-/var/volatile tmpfs tmpfs rw,relatime
Single command:
user@someplace:~# findmnt -n -o SOURCE /
/dev/mmcblk0p2
Great, that’s exactly what I’ve been looking for. It solved the problem for me on a Raspberry Pi with Raspian Jessie.
Author, can you kindly let me know how to properly read the file system type?
For instance, I’d like to know my internal and external sdcard file system, but some of the Market apps show types different from what I expect…
That’s a slightly out of topic for Android, but I’m glad to help.
You can get the excellent “Terminal Emulator for Android” app and then run the
mount
command. It will tell you what filesystems are in use on your system.Cheers,
Michael.
Couldn’t you just look at /etc/fstab?
Sure, that’s the easiest way. However, I was in the perspective of a small embedded Linux system that may not even have a /etc/fstab file and would be mounting its mount points through a simple script…
what is my rootfs device?
root@ibm#findmnt
TARGET SOURCE FSTYPE OPTIONS
/ unionfs rw,relatime,dirs=/host/root_rw/image-a=rw:/host/root_ro=ro
|-/sys sysfs sysfs rw,nosuid,nodev,noexec,relatime
| |-/sys/fs/cgroup tmpfs rw,relatime,size=4k,mode=755
| |-/sys/fs/fuse/connections fusectl rw,relatime
| |-/sys/kernel/debug debugfs rw,relatime
| `-/sys/kernel/security securityfs rw,relatime
|-/proc proc proc rw,nosuid,nodev,noexec,relatime
|-/dev udev devtmpfs rw,relatime,size=122448k,nr_inodes=30612,mode=755
| `-/dev/pts devpts devpts rw,nosuid,noexec,relatime,gid=5,mode=620
|-/run tmpfs tmpfs rw,nosuid,relatime,size=101952k,mode=755
| |-/run/lock tmpfs rw,nosuid,nodev,noexec,relatime,size=5120k
| |-/run/shm tmpfs rw,nosuid,nodev,relatime
| `-/run/user tmpfs rw,nosuid,nodev,noexec,relatime,size=102400k,mode=755
|-/mnt/ro /dev/mmcblk0p3 ext4 ro,relatime,data=ordered
`-/mnt/rw /dev/mmcblk0p4 ext4 rw,relatime,data=ordered
Very nice utility indeed. Thanks!