73

Symlinks have limitations in how functions like ls, mv, and cp can operate on them because unlike shell initiated commands like cd, these functions do not have information about how the user accessed the directory with respect to the logical path (see related post). It seems like using the mount --bind option instead can get an around this, offering increased functionality and compatibility with samba and other file servers because the mounted directory will then have two independent physical paths, instead of a link.

I would like to replace all of my symbolic links with references using the mount --bind option but this would mean mounting over 150 points in fstab. Are there any performance issues that could potentially arise from this or any other drawbacks that I should consider?

Noam M
  • 451
mrtrujiyo
  • 885
  • 1
  • 8
  • 7

6 Answers6

75

With mount --bind, a directory tree exists in two (or more) places in the directory hierarchy. This can cause a number of problems. Backups and other file copies will pick all copies. It becomes difficult to specify that you want to copy a filesystem: you'll end up copying the bind-mounted files twice. Searches with find, grep -r, locate, etc., will traverse all the copies, and so on.

You will not gain any “increased functionality and compatibility” with bind mounts. They look like any other directory, which most of the time is not desirable behavior. For example, Samba exposes symbolic links as directories by default; there is nothing to gain with using a bind mount. On the other hand, bind mounts can be useful to expose directory hierarchies over NFS.

You won't have any performance issues with bind mounts. What you'll have is administration headaches. Bind mounts have their uses, such as making a directory tree accessible from a chroot, or exposing a directory hidden by a mount point (this is usually a transient use while a directory structure is being remodeled). Don't use them if you don't have a need.

Only root can manipulate bind mounts. They can't be moved by ordinary means; they lock their location and the ancestor directories.

Generally speaking, if you pass a symbolic link to a command, the command acts on the link itself if it operates on files, and on the target of the link if it operates on file contents. This goes for directories too. This is usually the right thing. Some commands have options to treat symbolic links differently, for example ls -L, cp -d, rsync -l. Whatever you're trying to do, it's far more likely that symlinks are the right tool, than bind mounts being the right tool.

  • Thanks. I guess I wasn't considering the impact on backups, copies and file searches. I was able to get Samba to follow the symlinks by adding 'follow symlinks = yes' in smb.conf but this does compromise the security in that any samba user can execute say, 'ln -s /etc' in a writeable folder and gain access to system files. I'm trying to find a way around this. Please let me know if you know of one. – mrtrujiyo Oct 02 '12 at 21:24
  • 2
    @mrtrujiyo For that requirement, I think it would make sense to run the samba server in a chroot, and bind-mount the directories you want to export inside that chroot. Make sure to exclude the root of the chroot from backups and so on (with this organization, you only need to exclude the one toplevel directory, so it isn't much of a maintenance headache). – Gilles 'SO- stop being evil' Oct 02 '12 at 21:31
  • 3
    With the ever growing usage of containers, mount --bind is becoming more and more "the right tool" as symlinks might point outside of the boundaries of the container. – niry Dec 07 '19 at 16:13
  • There can be a measurable performance benefit of using bind over symlinks in cases when the mounted/linked directory hierarchy is deep and the process needs to handle a lot of (small) files. – oᴉɹǝɥɔ Jun 15 '20 at 23:03
15

In addition to what @Gilles wrote earlier, it's worth noting that some utilities might consider a bind-mounted directory to be a separate file system. This may have performance or functionality implications if the program can no longer assume that the same inode number refers to the same file (which it doesn't, if they are on different file systems), a move cannot be optimized as link-at-target-then-unlink-source, etc.

user
  • 28,901
  • Thanks. I was wondering how simple utilities like df and du would handle directory size calculations on filesystems with bind mounts. – mrtrujiyo Oct 02 '12 at 21:33
  • 1
    At least GNU df on my system doesn't even consider bind-mounted directories by default, but if asked specifically, it's treated as another mount of the same file system. (Which, if you ask me, is expected behavior for a tool with df's purpose.) – user Oct 03 '12 at 09:11
7

You should also want to use bind mounts instead of symlinks when you are relying on a support that might not always be in place (for example an external disk) and you want to be sure that the original directory structure is in place even if the support fails or is removed.

For example if I want to keep /var/tmp in an sd card I will use the bind mount, since some programs will expect /var/tmp to be a valid directory even if the card is removed.

TopperH
  • 171
2

I have tried bind mount to workaround a problem installing some packages with pacman (archlinux, more about that here) on a system where /var (as well as /home and /usr/local) were symlinks (across filesystems: SSD to SATA).

It looked great at first, but, as Gilles pointed out, locate always gave multiple results for a single file, despite the PRUNE_BIND_MOUNTS = "yes" line in /etc/updatedb.conf.

$ locate \*/findutils-4.4.2 | xargs ls -ldiog
33816600 drwxr-xr-x 12 4096 Dec  3 00:05 /SHARED/LOCALS/Manjaro/src/findutils-4.4.2
33816600 drwxr-xr-x 12 4096 Dec  3 00:05 /usr/local/src/findutils-4.4.2

Digging a little further, I found that more complex bind mounts may be pruned correctly:

$ sudo mount --bind /SHARED/LOCALS/common/ /usr/local/common
$ findmnt | fgrep -n sdb
34:├─/SHARED/LOCALS                  /dev/sdb5           ext4           rw,relatime,data=ordered
35:│ └─/SHARED/LOCALS/Manjaro/common /dev/sdb5[/common]  ext4            rw,relatime,data=ordered
36:├─/usr/local                      /dev/sdb5[/Manjaro] ext4            rw,relatime,data=ordered
37:│ └─/usr/local/common             /dev/sdb5[/common]  ext4            rw,relatime,data=ordered
38:├─/SHARED/HOMES                   /dev/sdb4           ext4            rw,relatime,data=ordered
39:├─/home                           /dev/sdb4[/Manjaro] ext4            rw,relatime,data=ordered
40:├─/SHARED/VARS                    /dev/sdb3           ext4            rw,relatime,data=ordered
41:├─/var                            /dev/sdb3[/Manjaro] ext4            rw,relatime,data=ordered
42:└─/opt                            /dev/sdb5[/opt]     ext4            rw,relatime,data=ordered

$ sudo updatedb --debug-pruning 2>&1 >/dev/null | grep bind
prune_bind_mounts\000
Rebuilding bind_mount_paths:
Matching bind_mount_paths:
Skipping `/SHARED/LOCALS/Manjaro/common': bind mount
Skipping `/usr/local/common': bind mount

$ locate \*/mmedia
/SHARED/LOCALS/common/mmedia

Without the PRUNE_BIND_MOUNT option, I would have got 3 results:

$ sudo sed -i '1 s/yes/no/' /etc/updatedb.conf 
$ sudo updatedb --debug-pruning 2>&1 >/dev/null | grep bind
prune_bind_mounts\000
$ locate \*/mmedia
/SHARED/LOCALS/Manjaro/common/mmedia
/SHARED/LOCALS/common/mmedia
/usr/local/common/mmedia
$ sudo sed -i '1 s/no/yes/' /etc/updatedb.conf 

Another issue with bind mounts:

Of course, one can manually add bind mounts (mounpoint or target) to PRUNEPATHS in /etc/updatedb.conf.

Also, mountpoint and various stat commands or functions can be used in tools to improve filesystem traversal as proposed here

RockyRoad
  • 161
1

When it comes to file bind mounts, they behave closer to hard links than symlinks. This can have somewhat subtle consequences, for example:

# echo 1 > 1.txt
# touch 2.txt
# mount --bind 1.txt 2.txt
# cat 2.txt
1
# echo 1a > 1.txt
# cat 2.txt
1a

So far so good, but now consider how many programs (editors, properly written scripts, etc.) actually modify files:

# echo 1new > 1new.txt
# mv 1new.txt 1.txt
# cat 1.txt
1new
# cat 2.txt
1a

If 2.txt had been a symlink to 1.txt then the last command would have output 1new, which is what one would probably expect.

This can cause some subtle problems: in systemd I was using BindReadOnlyPaths= to make a particular service use a different resolv.conf file than the rest of the system, but that turned out to be flaky in weird and hard to diagnose ways because resolvconf would replace the source file behind the service's back.

0

I use it like this:

/mnt/sdb1/.user_cache/User1_cache /home/User1/.cache none bind 0 0
/mnt/sdb1/.user_cache/User2_cache /home/User2/.cache none bind 0 0

I do it to reduce writes to an ssd that is being mounted with defaults,relatime,data=ordered,commit=600 0 1 also symlinked folders to my ~ that are not IO critical.

RobotJohnny
  • 1,039
  • 8
  • 18
rochr4
  • 1