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? 아니요, 한 번의 바인딩 후에 세 가지를 얻었습니다.

    /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)
    

    두 개는 읽기-쓰기이고 하나는 읽기 전용입니다. 어느 것이 우선인가? 읽기 전용인 것 같습니다.

    $ 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)
    

    하나는 읽기 전용이고 두 개는 읽기-쓰기입니다. 무엇이 우선인가? 결과는 쓰기 가능하므로 읽기 전용이 아닙니다.

    $ 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).

두 가지 옵션이 있습니다:

옵션 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)

관련 정보