Linux:階層化バインドマウントの読み取り専用モードを維持する方法

Linux:階層化バインドマウントの読み取り専用モードを維持する方法

この問題に関するいくつかの背景情報を提供します。

  1. /foo/barディレクトリが読み取り/書き込みモードになっています。
  2. /bar以下を指すバインドマウントポイントがあります。/foo/bar
  3. 読み取り専用モードでなければならないディレクトリが/foo/barあります(および)。bar/foo/bar/baz/bar/baz

/foo/bar/baz読み取り専用にするために別のバインディングを作成しました。

$ sudo mount -o bind,ro /foo/bar/baz /foo/bar/baz
$ sudo touch /foo/bar/baz/test
touch: cannot touch '/foo/bar/baz/test': Read-only file system
$ mount | grep bar
/dev/vda1 on /bar type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/vda1 on /foo/bar/baz type xfs (ro,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/vda1 on /bar/baz type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)

/foo/bar/bazPSがありますが、/bar/baz後者は読み取り専用ではありません。

ただし、/bar/baz次のように書くことができます。

$ sudo touch /bar/baz/test
$ echo $?
0

別のバインディングを試してみてください。

$ sudo mount -o bind,ro /bar/baz /bar/baz
$ mount | grep bar
/dev/vda1 on /bar type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/vda1 on /foo/bar/baz type xfs (ro,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/vda1 on /bar/baz type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/vda1 on /bar/baz type xfs (ro,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/vda1 on /foo/bar/baz type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/vda1 on /foo/bar/baz type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/vda1 on /bar/baz type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)

私を本当に混乱させるには:

  1. なぜ今同じマウントが3つありますか/bar/baz?いいえ、1回のバインディング後に3つのことを得ました。

    /dev/vda1 on /bar/baz type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
    /dev/vda1 on /bar/baz type xfs (ro,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
    /dev/vda1 on /bar/baz type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
    

    2つは読み書き可能で、1つは読み取り専用です。どちらが優先ですか?読み取り専用のようです。

    $ sudo touch /bar/baz/test
    touch: cannot touch '/bar/baz/test': Read-only file system
    

    しかし、最後ではなく、読み取り専用が真ん中にあります。

  2. /foo/bar/baz読み取り専用のマウントポイントしかない前に、3つのマウントポイントがあるのはなぜですか?

    /dev/vda1 on /foo/bar/baz type xfs (ro,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
    /dev/vda1 on /foo/bar/baz type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
    /dev/vda1 on /foo/bar/baz type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
    

    1つは読み取り専用で、2つは読み取り/書き込みです。何が優先ですか?結果は書き込み可能なので、読み取り専用ではありません。

    $ sudo touch /foo/bar/baz/test
    $ echo $?
    0
    

なぜこれが起こるのですか?そしてそれを避ける方法は何ですか?同時に読み取り専用にする正しい方法は何ですか/foo/bar/baz/bar/baz

答え1

長い話を短く

基本的に/bar/foo/bar共有山。つまり、何かを のフォルダにバインドした後は に伝播される/foo/bar/bar返品のフォルダに何かをインストールすると、/bar再び伝播されます/foo/bar

マニュアルページからmount(8)

...共有インストールはそのインストールのミラーを作成する機能を提供するため、ミラーのインストールと削除は別のミラーに伝播されます。 ...

/bar/bazマウントを にバインドすると/bar/baz再度伝播されます/foo/bar/baz( rw)。

2つのオプションがあります。

オプション1

実行する代わりに:

mount -o bind,ro /bar/baz /bar/baz

ランニング:

mount -o bind,ro /foo/bar/baz /bar/baz

これで元の場所からインストールしているので、元の場所/foo/barに再度伝播されません。

オプション#2

/bar一つ作らなければならない奴隷/foo/bar

また、次のマニュアルページからmount(8)

...スレーブマウントはマスターマウントから電波を受信しますが、その逆ではありません。 ...

だから実行しないでください:

mount -o bind /foo/bar /bar

ランニング:

mount --make-rslave -o bind /foo/bar /bar

これが唯一の違いです。その後、マウントを/foo/bar/baz読み取り専用(/bar/bazこの時点ではまだ読み取り/書き込み)にバインドし、以前に作成した読み取り専用/bar/bazバインドマウントを中断することなくマウントを読み取り専用にバインドできます/foo/bar/baz

問題を説明してください

ステップを再生成すると、次のようになります。

(1)mount -o bind /foo/bar /bar

で結果を見ることができます/proc/self/mountinfo

さまざまなフィールドを理解するには、次のマニュアルページをお読みくださいproc(5)

/proc/[pid]/mountinfo (since Linux 2.6.26)
       This file contains information about mount points.  It contains lines of the form:

       36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue
       (1)(2)(3)   (4)   (5)      (6)      (7)   (8) (9)   (10)         (11)

       The numbers in parentheses are labels for the descriptions below:

       (1)  mount ID: unique identifier of the mount (may be reused after umount(2)).

       (2)  parent ID: ID of parent mount (or of self for the top of the mount tree).

それでは確認してみましょう/proc/self/mountinfo

# grep bar /proc/self/mountinfo
146 65 8:1 /foo/bar /bar rw,relatime shared:1 - xfs /dev/sda1 rw,attr2,inode64,logbsize=256k,sunit=512,swidth=512,noquota

# grep ^65 /proc/self/mountinfo
65 0 8:1 / / rw,relatime shared:1 - xfs /dev/sda1 rw,attr2,inode64,logbsize=256k,sunit=512,swidth=512,noquota

  1. インストールID146/foo/barはに設置されています/bar
  2. 親IDは次のとおりです。65、これはルートパーティション(/)です。

また、次のように/foo/bar設置時にご注意ください。/bar共有

(2)mount -o bind,ro /foo/bar/baz /foo/bar/baz

  1. これにより、/foo/bar/bazから/foo/bar/bazへの読み取り専用バインドマウントが作成されます。
  2. また広がるというのは、にも設置されるという/bar意味です。/foo/bar/baz/bar/baz
  3. しかし、私が言ったように、roオプションは伝播されないので、/bar/bazまだrw

以下から見ることができます/proc/self/mountinfo

# grep bar /proc/self/mountinfo
146 65 8:1 /foo/bar /bar rw,relatime shared:1 - xfs /dev/sda1 rw,attr2,inode64,logbsize=256k,sunit=512,swidth=512,noquota
182 65 8:1 /foo/bar/baz /foo/bar/baz ro,relatime shared:1 - xfs /dev/sda1 rw,attr2,inode64,logbsize=256k,sunit=512,swidth=512,noquota
183 146 8:1 /foo/bar/baz /bar/baz rw,relatime shared:1 - xfs /dev/sda1 rw,attr2,inode64,logbsize=256k,sunit=512,swidth=512,noquota

1. 182 /foo/bar/baz/foo/bar/baz上部上部roに設置(2)

2. 146 /foo/bar/barその結果、インストール済み(1)

  • 183 /foo/bar/baz/bar/baz次にasの上に再インストールしてくださいrw(2)

マウントオプション(例ro:)はマウントと共に伝播されません。/foo/bar/bazに伝播されますが、オプションは/bar/bazありませんro

そのため、一度(読み取り専用)と一度(電波の結果として読み取り/書き込みとして)/foo/bar/bazマウントされます。/foo/bar/baz/bar/baz/foo/bar

(サム)mount -o bind,ro /bar/baz /bar/baz

  1. これにより、/bar/bazから/bar/bazへの読み取り専用バインドマウントが作成されます。
  2. また広がるというのは、にも設置されるという/foo/bar意味です。/bar/baz/foo/bar/baz
  3. ただし、roオプションは伝播されないため、/foo/bar/baz読み取り/書き込みが可能です。
# grep bar /proc/self/mountinfo
146 65 8:1 /foo/bar /bar rw,relatime shared:1 - xfs /dev/sda1 rw,attr2,inode64,logbsize=256k,sunit=512,swidth=512,noquota
182 202 8:1 /foo/bar/baz /foo/bar/baz ro,relatime shared:1 - xfs /dev/sda1 rw,attr2,inode64,logbsize=256k,sunit=512,swidth=512,noquota
183 201 8:1 /foo/bar/baz /bar/baz rw,relatime shared:1 - xfs /dev/sda1 rw,attr2,inode64,logbsize=256k,sunit=512,swidth=512,noquota
200 183 8:1 /foo/bar/baz /bar/baz ro,relatime shared:1 - xfs /dev/sda1 rw,attr2,inode64,logbsize=256k,sunit=512,swidth=512,noquota
203 182 8:1 /foo/bar/baz /foo/bar/baz rw,relatime shared:1 - xfs /dev/sda1 rw,attr2,inode64,logbsize=256k,sunit=512,swidth=512,noquota
202 65 8:1 /foo/bar/baz /foo/bar/baz rw,relatime shared:1 - xfs /dev/sda1 rw,attr2,inode64,logbsize=256k,sunit=512,swidth=512,noquota
201 146 8:1 /foo/bar/baz /bar/baz rw,relatime shared:1 - xfs /dev/sda1 rw,attr2,inode64,logbsize=256k,sunit=512,swidth=512,noquota

1. 146 /foo/bar/barその結果、インストール済み(1)

  • 201 /foo/bar/bazにインストールされました/bar/baz
    • 183 /foo/bar/baz/bar/baz次にasの上に再インストールしてくださいrw(2)
      • 200 /foo/bar/bazインストール済み再び上記の理由/bar/bazro(サム)

2. 第202話 /foo/bar/bazの元のフォルダはです/

  • 182 /foo/bar/baz/foo/bar/baz上部上部roに設置(2)
    • 203 /foo/bar/bazインストール済み再び〜のように/foo/bar/bazrw(サム)

これで一度(読み取り専用)と一度(読み取り/書き込み)を/foo/bar/bazマウントします。/bar/baz/foo/bar/baz

解決策

(1)mount --make-rslave -o bind /foo/bar /bar

# grep bar /proc/self/mountinfo
146 65 8:1 /foo/bar /bar rw,relatime master:1 - xfs /dev/sda1 rw,attr2,inode64,logbsize=256k,sunit=512,swidth=512,noquota

/foo/barそれは所有者of /bar:マウントをからに伝播できますが、/foo/baron/barのマウントは/bar後方に伝播されません/foo/bar

(2)mount -o bind,ro /foo/bar/baz /foo/bar/baz

# grep bar /proc/self/mountinfo
146 65 8:1 /foo/bar /bar rw,relatime master:1 - xfs /dev/sda1 rw,attr2,inode64,logbsize=256k,sunit=512,swidth=512,noquota
182 65 8:1 /foo/bar/baz /foo/bar/baz ro,relatime shared:1 - xfs /dev/sda1 rw,attr2,inode64,logbsize=256k,sunit=512,swidth=512,noquota
183 146 8:1 /foo/bar/baz /bar/baz rw,relatime master:1 - xfs /dev/sda1 rw,attr2,inode64,logbsize=256k,sunit=512,swidth=512,noquota

以前見たものと似ていますが、今は/foo/barの所有者/barであり、/foo/bar/baz所有者です/bar/baz

(サム)mount -o bind,ro /bar/baz /bar/baz

# grep bar /proc/self/mountinfo
146 65 8:1 /foo/bar /bar rw,relatime master:1 - xfs /dev/sda1 rw,attr2,inode64,logbsize=256k,sunit=512,swidth=512,noquota
182 65 8:1 /foo/bar/baz /foo/bar/baz ro,relatime shared:1 - xfs /dev/sda1 rw,attr2,inode64,logbsize=256k,sunit=512,swidth=512,noquota
183 146 8:1 /foo/bar/baz /bar/baz rw,relatime master:1 - xfs /dev/sda1 rw,attr2,inode64,logbsize=256k,sunit=512,swidth=512,noquota
200 183 8:1 /foo/bar/baz /bar/baz ro,relatime master:1 - xfs /dev/sda1 rw,attr2,inode64,logbsize=256k,sunit=512,swidth=512,noquota

これが主な違いです。これで新しいマウントのみが作成されます。200

残りは変更されません。このインストールは再び伝播されなかった/foo/barため、まだ次のように/foo/bar/bazインストールされます。/foo/bar/bazro(2)

これで/foo/bar/baz、すべてに読み取り専用でインストールされます。/foo/bar/baz/bar/baz

答え2

説明部分は完全に説明されています。アベイロ答え:https://unix.stackexchange.com/a/689950/513617

追加の読み書きインストールを追加する必要がない良いソリューションが見つかりました。これはremount選択です。

  1. mount -o bind /foo/bar /bar
  2. mount -o bind,ro /foo/bar/baz /foo/bar/baz
  3. その後、既存の読み取り/書き込み伝播/bar/bazバインディングを使用しますremount
    mount -o bind,ro,remount /foo/bar/baz /bar/baz

その後、次の結果のみが得られます。

$ mount | grep bar
/dev/vda1 on /bar type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/vda1 on /foo/bar/baz type xfs (ro,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/vda1 on /bar/baz type xfs (ro,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)

関連情報