The following details loopback file system (FS) mounts. These allow
one to effectively mount a portion of an FS elsewhere, providing access
to the underlying sub-tree(s) via alternate pathnames wherein a symlink
may not be appropriate. Our host details are:
HOSTS: europa (Linux)
berkeley (FreeBSD)
sunspot (Solaris)
OSes: CentOS 6.2 (Red Hat Enterprise Linux Clone)
FreeBSD 8.2
Solaris 10
MOUNTED FS: /usr/local/prodapp
LOOPBACK MOUNT: /var/log/prodapp
NOTE: Unless details differ between OSes, "europa"
will be used in the examples.
The short answer to how to setup a loopback mount is to simply use the
appropriate mount options:
europa [0] /bin/mount --bind /usr/local/prodapp/logs /var/log/prodapp
berkeley [0] /sbin/mount -t nullfs /usr/local/prodapp/logs /var/log/prodapp
sunspot [0] /usr/sbin/mount -F lofs /usr/local/prodapp/logs /var/log/prodapp
For further details on why, how, and expectations, I've setup a scenario
wherein "/var" is undersized for the amount of data logged by application
"prodapp". For our currently mounted file systems, we have:
europa [0] /bin/df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 6.0G 1.6G 4.1G 27% /
tmpfs 467M 0 467M 0% /dev/shm
/dev/sda3 1008M 598M 360M 63% /var
/dev/sdb1 2.0G 36M 1.9G 2% /usr/local/prodapp
A quick check under "/var" identifies the contents of "/var/log/prodapp"
as our consumer:
berkeley [0] /usr/bin/du -sk /var/* | /usr/bin/sort -n | /usr/bin/tail -5
europa [0] /usr/bin/du -sk /var/* | /bin/sort -n | /usr/bin/tail -5
112 /var/run
116 /var/spool
21948 /var/cache
42060 /var/lib
513144 /var/log
europa [0] /usr/bin/du -sk /var/log/* | /bin/sort -n | /usr/bin/tail -5
88 /var/log/audit
104 /var/log/dracut.log
108 /var/log/messages
144 /var/log/anaconda.storage.log
512224 /var/log/prodapp
europa [0] /bin/ls -l /var/log/prodapp
total 512220
-rw-r--r--. 1 root root 218678 Aug 16 13:07 prodapp.log
-rw-r--r--. 1 root root 524288000 Aug 16 13:19 prodapp.log.0.gz
Our application directory, "/usr/local/prodapp", is a separate FS with
available space. Our application, however, expects to write its logs to
a directory at "/var/log/prodapp". To keep our logs with our application
and to setup for our loopback mount, we'll create a "logs" directory
under "/usr/local/prodapp". After that, we'll move the contents of
"/var/log/prodapp" to "/usr/local/prodapp/logs":
europa [0] /bin/ls -Fb /usr/local/prodapp
bin/ conf/ lost+found/ readme.html
europa [0] /bin/mkdir /usr/local/prodapp/logs && /bin/ls /usr/local/prodapp
bin/ conf/ logs/ lost+found/ readme.html
europa [0] /bin/mv /var/log/prodapp/* /usr/local/prodapp/logs/.
europa [0] /bin/ls -l /var/log/prodapp /usr/local/prodapp/logs
/usr/local/prodapp/logs:
total 512220
-rw-r--r--. 1 root root 218678 Aug 16 13:07 prodapp.log
-rw-r--r--. 1 root root 524288000 Aug 16 13:19 prodapp.log.0.gz
/var/log/prodapp:
total 0
europa [0]
At this point, we can remount "/usr/local/prodapp/logs" to the
"/var/log/prodapp" directory via a loopback mount. This will make the
underlying directory sub-tree of "/usr/local/prodapp/logs" accessible
also under "/var/log/prodapp":
europa [0] /bin/mount --bind /usr/local/prodapp/logs /var/log/prodapp
berkeley [0] /sbin/mount -t nullfs /usr/local/prodapp/logs /var/log/prodapp
sunspot [0] /usr/sbin/mount -F lofs /usr/local/prodapp/logs /var/log/prodapp
berkeley [0] /bin/df -h
Filesystem Size Used Avail Capacity Mounted on
/dev/da0s1a 5.8G 1.9G 3.5G 35% /
devfs 1.0K 1.0K 0B 100% /dev
/dev/da0s1d 990M 834K 910M 0% /var
/dev/da1s1a 1.9G 501M 1.3G 28% /usr/local/prodapp
/usr/local/prodapp/logs 1.9G 501M 1.3G 28% /var/log/prodapp
berkeley [0]
Of note, I've used the 'df -h' output from "berkeley" in the above
since it reflects the expected output from both FreeBSD and Solaris.
Unfortunately, as seen below, to get the same output under Linux, we
need to use 'df -ah' to allow "dummy" or "virtual" FS to be displayed:
europa [0] /bin/df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 6.0G 1.6G 4.1G 27% /
tmpfs 467M 0 467M 0% /dev/shm
/dev/sda3 1008M 97M 860M 11% /var
/dev/sdb1 2.0G 537M 1.4G 29% /usr/local/prodapp
europa [0] /bin/df -ah
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 6.0G 1.6G 4.1G 27% /
proc 0 0 0 - /proc
sysfs 0 0 0 - /sys
devpts 0 0 0 - /dev/pts
tmpfs 467M 0 467M 0% /dev/shm
/dev/sda3 1008M 97M 860M 11% /var
none 0 0 0 - /proc/sys/fs/binfmt_misc
/dev/sdb1 2.0G 537M 1.4G 29% /usr/local/prodapp
/usr/local/prodapp/logs
2.0G 537M 1.4G 29% /var/log/prodapp
A quick check via 'mount' for all three OSes supports the output from 'df':
europa [0] /bin/mount | /bin/grep prodapp
/dev/sdb1 on /usr/local/prodapp type ext4 (rw)
/usr/local/prodapp/logs on /var/log/prodapp type none (rw,bind)
sunspot [0] /usr/sbin/mount | /bin/grep prodapp
/usr/local/prodapp on /dev/dsk/c1t1d0s0 read/write/setuid/devices/intr/largefiles/logging/xattr/onerror=panic/dev=800080 on Thu Aug 16 12:56:49 2012
/var/log/prodapp on /usr/local/prodapp/logs read/write/setuid/devices/dev=800080 on Thu Aug 16 13:22:06 2012
berkeley [0] /sbin/mount | /usr/bin/grep prodapp
/dev/da1s1a on /usr/local/prodapp (ufs, local)
/usr/local/prodapp/logs on /var/log/prodapp (nullfs, local)
Since our loopback mount simply provides access to a portion of our
original FS via an additional, new directory structure, we can see the
same files are presented under each, thus also having the same inode
numbers, etc:
europa [0] /bin/ls -li /var/log/prodapp /usr/local/prodapp/logs
/usr/local/prodapp/logs:
total 512220
33 -rw-r--r--. 1 root root 218678 Aug 16 13:07 prodapp.log
34 -rw-r--r--. 1 root root 524288000 Aug 16 13:19 prodapp.log.0.gz
/var/log/prodapp:
total 512220
33 -rw-r--r--. 1 root root 218678 Aug 16 13:07 prodapp.log
34 -rw-r--r--. 1 root root 524288000 Aug 16 13:19 prodapp.log.0.gz
The only thing left is to add the loopback mount to the "fstab" so that
it will be mounted at boot time. (Remember to add it so it will be
mounted after the original FS is mounted):
europa [0] /usr/bin/tail -2 /etc/fstab
/dev/sdb1 /usr/local/prodapp ext4 defaults 0 2
/usr/local/prodapp/logs /var/log/prodapp none bind 0 0
berkeley [0] /usr/bin/tail -2 /etc/fstab
/dev/da1s1a /usr/local/prodapp ufs rw 0 2
/usr/local/prodapp/logs /var/log/prodapp nullfs rw 0 0
sunspot [0] /usr/bin/tail -2 /etc/vfstab
/dev/dsk/c1t1d0s0 /dev/rdsk/c1t1d0s0 /usr/local/prodapp ufs 0 yes -
/usr/local/prodapp/logs - /var/log/prodapp lofs - yes -
Alright, now some caveats. If the underlying FS structure
(/usr/local/prodapp/logs) does not exist prior to attempting to mount
the loopback FS (/var/log/prodapp), the mount of the loopback mount
will fail. The following is after unmounting both "/var/log/prodapp"
and "/usr/local/prodapp", thus "/usr/local/prodapp/logs" is not available:
europa [0] /bin/mount --bind /usr/local/prodapp/logs /var/log/prodapp
mount: special device /usr/local/prodapp/logs does not exist
europa [32]
berkeley [0] /sbin/mount -t nullfs /usr/local/prodapp/logs /var/log/prodapp
mount_nullfs: /usr/local/prodapp/logs: No such file or directory
berkeley [64]
sunspot [0] /usr/sbin/mount -F lofs /usr/local/prodapp/logs /var/log/prodapp
mount: /usr/local/prodapp/logs: No such file or directory
sunspot [33]
Also, it should not, and is not possible to unmount the mounted FS while
the loopback FS is mounted, as seen under FreeBSD and Solaris:
berkeley [0] /sbin/umount /usr/local/prodapp
umount: unmount of /usr/local/prodapp failed: Device busy
berkeley [1]
Linux, curiously however, will allow you to do just that leaving the
loopback FS still accessible just as it was previously:
europa [0] /bin/umount /usr/local/prodapp
europa [0] /bin/df -ah
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 6.0G 1.6G 4.2G 27% /
proc 0 0 0 - /proc
sysfs 0 0 0 - /sys
devpts 0 0 0 - /dev/pts
tmpfs 467M 0 467M 0% /dev/shm
/dev/sda3 1008M 98M 860M 11% /var
/usr/local/prodapp/logs
2.0G 537M 1.4G 29% /var/log/prodapp
none 0 0 0 - /proc/sys/fs/binfmt_misc
europa [0] /bin/touch /var/log/prodapp/trash
europa [0] /bin/ls -li /var/log/prodapp/trash
35 -rw-r--r--. 1 root root 0 Aug 16 13:43 /var/log/prodapp/trash
europa [0] /bin/mount /usr/local/prodapp
europa [0] /bin/df -h /usr/local/prodapp
Filesystem Size Used Avail Use% Mounted on
/dev/sdb1 2.0G 537M 1.4G 29% /usr/local/prodapp
europa [0] /bin/ls -li /usr/local/prodapp/logs/trash
35 -rw-r--r--. 1 root root 0 Aug 16 13:43 /usr/local/prodapp/logs/trash
Finally, since the loopback FS is simply representing a portion of the
original mounted FS, the loopback FS by default will be restricted to
the mount options used for the mounted FS. While you can further limit
the options on the loopback FS, the mount options will not be allowed
to exceed those of the mounted FS. As an example, if the mounted FS is
mounted read-write, the loopback FS can be subsequently mounted read-only.
If, however, the mounted FS is mounted read-only, the loopback FS will
also be read-only:
berkeley [0] /sbin/mount -o ro /dev/da1s1a /usr/local/prodapp
berkeley [0] /sbin/mount -t nullfs -o rw /usr/local/prodapp/logs /var/log/prodapp
sunspot [0] /usr/sbin/mount -o ro /dev/dsk/c1t1d0s0 /usr/local/prodapp
sunspot [0] /usr/sbin/mount -F lofs -o rw /usr/local/prodapp/logs /var/log/prodapp
mount: /usr/local/prodapp/logs on /var/log/prodapp - WARNING ignoring option "rw"
europa [0] /bin/mount -t ext4 -o ro /dev/sdb1 /usr/local/prodapp
europa [0] /bin/mount -o bind,rw /usr/local/prodapp/logs /var/log/prodapp
europa [0] /bin/touch /usr/local/prodapp/logs/trash.0
berkeley [0] /usr/bin/touch /usr/local/prodapp/logs/trash.0
touch: cannot touch `/usr/local/prodapp/logs/trash.0': Read-only file system
europa [1] /bin/touch /var/log/prodapp/trash.0
touch: cannot touch `/var/log/prodapp/trash.0': Read-only file system
europa [1]
Reviewing our mounted FS options, we have:
europa [1] /bin/mount | /bin/grep prodapp
/dev/sdb1 on /usr/local/prodapp type ext4 (ro)
/usr/local/prodapp/logs on /var/log/prodapp type none (rw,bind)
europa [0] /bin/grep prodapp /proc/mounts
/dev/sdb1 /usr/local/prodapp ext4 ro,seclabel,relatime,barrier=1,data=ordered 0 0
/dev/sdb1 /var/log/prodapp ext4 ro,seclabel,relatime,barrier=1,data=ordered 0 0
europa [0]
berkeley [1] /sbin/mount -p | /usr/bin/grep prodapp
/dev/da1s1a /usr/local/prodapp ufs ro 0 2
/usr/local/prodapp/logs /var/log/prodapp nullfs rw 0 0
berkeley [0]
sunspot [1] /usr/sbin/mount -p | /bin/grep prodapp
/dev/dsk/c1t1d0s0 - /usr/local/prodapp ufs - no ro,intr,largefiles,logging,xattr,onerror=panic
/usr/local/prodapp/logs - /var/log/prodapp lofs - no
sunspot [0]