Difference between --rbind and --bind in mounting

I am confused. Linux filesystem is a tree structure, with the root node(starting node) as the root directory. Now let's suppose I have a folder abc at location /home/abc and another folder xyz at location /home/xyz

Folder xyz consists of some other folders and files inside it. (ex def and mno are folders inside it)

/
├── home/
│   ├── abc
│   └── xyz
│       ├── def
│       └── mno

When I run the command

mount --rbind /home/xyz /home/abc

(rbind is recursively bind) I see all the contents of the folder xyz in abc. Now, when I just run the command

mount --bind /home/xyz /home/abc

I still see all the contents of xyz in abc.

Why is that?

--bind to work just as similarly to --rbind.


Solution 1:

You've rightly observed that, with both --bind and --rbind, you see directories under the bind mount.

The difference is that, with --rbind but not with --bind, you see the contents of other bind mounts under the bind mount.


As applied to your example, suppose for simplicity that /home/xyz/def and /home/xyz/mno are empty directories. Suppose further that you then use them as bind mounts, i.e., you use them as mount points in mount --bind or mount --rbind. This causes them to appear nonempty. Then, suppose you run:

mount --bind /home/xyz /home/abc

Then, /home/abc/def and /home/abc/mno both exist, but they appear empty, because you used mount --bind, which is nonrecursive.

In contrast, suppose you instead made /home/abc a bind mount by running this command:

mount --rbind /home/xyz /home/abc

Then, /home/abc/def and /home/abc/mno both exist and they appear nonempty--they have the contents of the /home/xyz/def and /home/xyz/mno bind mounts--because you used mount --rbind, which is recursive.


Here's a fully worked-out example:

ek@Gnar:~$ mkdir original
ek@Gnar:~$ touch original/a-regular-file
ek@Gnar:~$ mkdir original/a-directory
ek@Gnar:~$ mkdir parent-of-mountpoint
ek@Gnar:~$ mkdir parent-of-mountpoint/mountpoint
ek@Gnar:~$ sudo mount --bind ~/original ~/parent-of-mountpoint/mountpoint
ek@Gnar:~$ mkdir nonrecursive-other-mountpoint recursive-other-mountpoint
ek@Gnar:~$ sudo mount --bind ~/parent-of-mountpoint ~/nonrecursive-other-mountpoint
ek@Gnar:~$ sudo mount --rbind ~/parent-of-mountpoint ~/recursive-other-mountpoint
ek@Gnar:~$ tree -F original/
original/
├── a-directory/
└── a-regular-file

1 directory, 1 file
ek@Gnar:~$ tree -F parent-of-mountpoint/
parent-of-mountpoint/
└── mountpoint/
    ├── a-directory/
    └── a-regular-file

2 directories, 1 file
ek@Gnar:~$ tree -F nonrecursive-other-mountpoint/
nonrecursive-other-mountpoint/
└── mountpoint/

1 directory, 0 files
ek@Gnar:~$ tree -F recursive-other-mountpoint/
recursive-other-mountpoint/
└── mountpoint/
    ├── a-directory/
    └── a-regular-file

2 directories, 1 file
ek@Gnar:~$ mount | grep ~
/dev/sda2 on /home/ek/parent-of-mountpoint/mountpoint type ext4 (rw,relatime)
/dev/sda2 on /home/ek/nonrecursive-other-mountpoint type ext4 (rw,relatime)
/dev/sda2 on /home/ek/recursive-other-mountpoint type ext4 (rw,relatime)
/dev/sda2 on /home/ek/recursive-other-mountpoint/mountpoint type ext4 (rw,relatime)

Solution 2:

Read man 8 mount. It says (emphasis added):

Bind mounts

Remount part of the file hierarchy somewhere else. The call is:

mount --bind olddir newdir

or by using this fstab entry:

/olddir /newdir none bind

After this call the same contents are accessible in two places. One can also remount a single file (on a single file). It's also possible to use the bind mount to create a mountpoint from a regular directory, for example:

mount --bind foo foo

The bind mount call attaches only (part of) a single filesystem, not possible submounts. The entire file hierarchy including submounts is attached a second place by using:

mount --rbind olddir newdir

Note that the filesystem mount options will remain the same as those on the original mount point.