Bind mount is just... well... a bind mount. I.e. it's not a new mount. It just "links"/"exposes"/"considers" a subdirectory as a new mount point. As such it cannot alter the mount parameters. That's why you're getting complaints:
# mount /mnt/1/lala /mnt/2 -o bind,ro
mount: warning: /mnt/2 seems to be mounted read-write.
But as you said a normal bind mount works:
# mount /mnt/1/lala /mnt/2 -o bind
And then a ro remount also works:
# mount /mnt/1/lala /mnt/2 -o bind,remount,ro
However what happens is that you're changing the whole mount and not just this bind mount. If you take a look at /proc/mounts you'll see that both bind mount and the original mount change to read-only:
/dev/loop0 /mnt/1 ext2 ro,relatime,errors=continue,user_xattr,acl 0 0
/dev/loop0 /mnt/2 ext2 ro,relatime,errors=continue,user_xattr,acl 0 0
So what you're doing is like changing the initial mount to a read-only mount and then doing a bind mount which will of course be read-only.
UPDATE 2016-07-20:
The following are true for 4.5 kernels, but not true for 4.3 kernels (This is wrong. See update #2 below):
The kernel has two flags that control read-only:
- The
MS_READONLY
: Indicating whether the mount is read-only
- The
MNT_READONLY
: Indicating whether the "user" wants it read-only
On a 4.5 kernel, doing a mount -o bind,ro
will actually do the trick. For example, this:
# mkdir /tmp/test
# mkdir /tmp/test/a /tmp/test/b
# mount -t tmpfs none /tmp/test/a
# mkdir /tmp/test/a/d
# mount -o bind,ro /tmp/test/a/d /tmp/test/b
will create a read-only bind mount of /tmp/test/a/d
to /tmp/test/b
, which will be visible in /proc/mounts
as:
none /tmp/test/a tmpfs rw,relatime 0 0
none /tmp/test/b tmpfs ro,relatime 0 0
A more detailed view is visible in /proc/self/mountinfo
, which takes into consideration the user view (namespace). The relevant lines will be these:
363 74 0:49 / /tmp/test/a rw,relatime shared:273 - tmpfs none rw
368 74 0:49 /d /tmp/test/b ro,relatime shared:273 - tmpfs none rw
Where on the second line, you can see that it says both ro
(MNT_READONLY
) and rw
(!MS_READONLY
).
The end result is this:
# echo a > /tmp/test/a/d/f
# echo a > /tmp/test/b/f
-su: /tmp/test/b/f: Read-only file system
UPDATE 2016-07-20 #2:
A bit more digging into this shows that the behavior in fact depends on the version of libmount which is part of util-linux. Support for this was added with this commit and was released with version 2.27:
commit 9ac77b8a78452eab0612523d27fee52159f5016a
Author: Karel Zak
Date: Mon Aug 17 11:54:26 2015 +0200
libmount: add support for "bind,ro"
Now it's necessary t use two mount(8) calls to create a read-only
mount:
mount /foo /bar -o bind
mount /bar -o remount,ro,bind
This patch allows to specify "bind,ro" and the remount is done
automatically by libmount by additional mount(2) syscall. It's not
atomic of course.
Signed-off-by: Karel Zak
which also provides the workaround. The behavior can be seen using strace on an older and a newer mount:
Old:
mount("/tmp/test/a/d", "/tmp/test/b", 0x222e240, MS_MGC_VAL|MS_RDONLY|MS_BIND, NULL) = 0 <0.000681>
New:
mount("/tmp/test/a/d", "/tmp/test/b", 0x1a8ee90, MS_MGC_VAL|MS_RDONLY|MS_BIND, NULL) = 0 <0.011492>
mount("none", "/tmp/test/b", NULL, MS_RDONLY|MS_REMOUNT|MS_BIND, NULL) = 0 <0.006281>
Conclusion:
To achieve the desired result one needs to run two commands (as @Thomas already said):
mount SRC DST -o bind
mount DST -o remount,ro,bind
Newer versions of mount (util-linux >=2.27) do this automatically when one runs
mount SRC DST -o bind,ro
Most modern file systems are journaling file systems, which means that they keep track of changes that have not yet been written to disk in an internal data structure called a journal. In the event of a crash, this journal will be replayed, to make sure that all writes performed successfully, preventing file corruption.
When actually writing out the data to disk, the write cache will re-order the writes to try to maximize the throughput, but it must make sure that the actual file data is written to disk before the metadata, to make sure that if a crash occurs the metadata won't be out-of-date with the data.
The problem is that many disks have caches of their own that might re-order the writes as well. Some file systems will assume that that will happen and will force the disk to flush the cache at certain points to prevent this, and is called write barriers
in e.g. ext4, and Linux in general.
For modern disks the performance sacrifice for doing this is negligible though, and you shouldn't disable write barriers unless absolutely necessary.
Best Answer