mount_namespaces(7)

الاسم
mount_namespaces - نظرة عامة على مساحات أسماء الوصل في لينكس

الوصف
للحصول على نظرة عامة على مساحات الأسماء، انظر namespaces(7).

توفر مساحات أسماء الوصل عزلاً لقائمة عمليات الوصل التي تراها العمليات في كل نسخة من مساحة الأسماء. وبذلك، سترى العمليات في كل نسخة من مساحات أسماء الوصل هياكل أدلة منفردة ومتميزة.

تتوافق العروض التي توفرها ملفات /proc/pid/mounts و /proc/pid/mountinfo و /proc/pid/mountstats (وكلها مشروحة في proc(5)) مع مساحة أسماء الوصل التي تقع فيها العملية ذات معرف العملية pid. (سترى جميع العمليات التي تقع في مساحة أسماء الوصل نفسها العرض ذاته في هذه الملفات.)

تُنشأ مساحة أسماء وصل جديدة باستخدام إما clone(2) أو unshare(2) مع العلم CLONE_NEWNS. عند إنشاء مساحة أسماء وصل جديدة، تُهيأ قائمة الوصل الخاصة بها على النحو التالي:

•   إذا أُنشئت مساحة الأسماء باستخدام clone(2)، فإن قائمة وصل مساحة أسماء الابن هي نسخة من قائمة الوصل في مساحة أسماء وصل العملية الأب.

•   إذا أُنشئت مساحة الأسماء باستخدام unshare(2)، فإن قائمة وصل مساحة الأسماء الجديدة هي نسخة من قائمة الوصل في مساحة أسماء وصل المستدعِي السابقة.

التعديلات اللاحقة على قائمة الوصل (mount(2) و umount(2)) في أي من مساحتي أسماء الوصل لن تؤثر (مبدئياً) على قائمة الوصل المرئية في مساحة الأسماء الأخرى (لكن انظر المناقشة التالية حول الأشجار الفرعية المشتركة).

الأشجار الفرعية المشتركة
بعد اكتمال تنفيذ مساحات أسماء الوصل، أظهرت التجربة أن العزل الذي وفرته كان في بعض الحالات كبيراً جداً. على سبيل المثال، لجعل قرص بصري مُحمل حديثاً متاحاً في جميع مساحات أسماء الوصل، تطلبت العملية إجراء عملية وصل في كل مساحة أسماء. لهذه الحالة وغيرها، قُدمت ميزة الأشجار الفرعية المشتركة في لينكس 2.6.15. تتيح هذه الميزة انتشاراً آلياً ومحكوماً لأحداث mount(2) و umount(2) بين مساحات الأسماء (أو بدقة أكثر، بين عمليات الوصل التي هي أعضاء في مجموعة أقران تنشر الأحداث لبعضها البعض).

تُوسم كل عملية وصل (عبر mount(2)) بأن لها أحد أنواع الانتشار التالية:

MS_SHARED
    تتشارك عملية الوصل هذه الأحداث مع أعضاء مجموعة الأقران. أحداث mount(2) و umount(2) التي تقع مباشرة أسفل عملية الوصل هذه ستنتشر إلى عمليات الوصل الأخرى الأعضاء في مجموعة الأقران. الانتشار هنا يعني أن نفس mount(2) أو umount(2) سيحدث آلياً تحت جميع عمليات الوصل الأخرى في مجموعة الأقران. وبالعكس، فإن أحداث mount(2) و umount(2) التي تقع تحت عمليات وصل الأقران ستنتشر إلى عملية الوصل هذه.

MS_PRIVATE
    عملية الوصل هذه خاصة؛ ليس لها مجموعة أقران. أحداث mount(2) و umount(2) لا تنتشر إليها ولا تخرج منها.

MS_SLAVE
    أحداث mount(2) و umount(2) تنتشر إلى عملية الوصل هذه من مجموعة أقران مشتركة (رئيسة). أحداث mount(2) و umount(2) تحت عملية الوصل هذه لا تنتشر إلى أي قرين.

    لاحظ أن عملية الوصل يمكن أن تكون تابعاً لمجموعة أقران أخرى بينما تتشارك في الوقت نفسه أحداث mount(2) و umount(2) مع مجموعة أقران هي عضو فيها. (بدقة أكثر، يمكن لمجموعة أقران واحدة أن تكون تابعاً لمجموعة أقران أخرى.)

MS_UNBINDABLE
    هذه تشبه عملية الوصل الخاصة، وبالإضافة إلى ذلك لا يمكن وصل عملية الوصل هذه بوصل تقييدي (bind mount). ستفشل محاولات إجراء وصل تقييدي لعملية الوصل هذه (mount(2) مع العلم MS_BIND).

    عند إجراء وصل تقييدي تكراري (mount(2) مع العَلمين MS_BIND و MS_REC) على شجرة فرعية لدليل، فإن أي عمليات وصل تقييدي داخل الشجرة الفرعية تُقلم آلياً (أي لا تُنسخ) عند نسخ تلك الشجرة الفرعية لإنتاج الشجرة الفرعية المستهدفة.

لمناقشة نوع الانتشار المخصص لعملية وصل جديدة، انظر قسم الملاحظات (NOTES).

نوع الانتشار هو إعداد لكل نقطة وصل؛ قد تُوسم بعض عمليات الوصل بأنها مشتركة (حيث تكون كل عملية وصل مشتركة عضواً في مجموعة أقران متميزة)، بينما تكون عمليات أخرى خاصة (أو تابعة أو غير قابلة للتقييد).

لاحظ أن نوع انتشار عملية الوصل يحدد ما إذا كانت عمليات mount(2) و umount(2) لوصلات مباشرة تحت عملية الوصل ستنتشر أم لا. وبذلك، لا يؤثر نوع الانتشار على انتشار الأحداث للأحفاد والمنحدرين الأبعد. أما ما يحدث إذا فُصلت عملية الوصل نفسها فيحدده نوع الانتشار الساري على الأب لعملية الوصل تلك.

يُضاف الأعضاء إلى مجموعة أقران عندما تُوسم عملية وصل بأنها مشتركة وإما:

(أ) تُنسخ عملية الوصل أثناء إنشاء مساحة أسماء وصل جديدة؛ أو

(ب) يُنشأ وصل تقييدي جديد من عملية الوصل.

في كلتا الحالتين، تنضم عملية الوصل الجديدة إلى مجموعة الأقران التي تكون عملية الوصل الموجودة عضواً فيها.

تُنشأ أيضًا مجموعة أقران جديدة عندما يُنشأ وصل ابن تحت وصل موجود موسوم بأنه مشترك. في هذه الحالة، يُوسم الوصل الابن الجديد أيضًا بأنه مشترك وتتكون مجموعة الأقران الناتجة من جميع الوصلات المنسوخة تحت أقران الوصلات الآباء.

تكف عملية الوصل عن كونها عضواً في مجموعة أقران إما عندما تُفصل صراحة، أو عندما تُفصل ضمنياً بسبب إزالة مساحة أسماء وصل (لعدم وجود عمليات أعضاء فيها).

يمكن اكتشاف نوع انتشار الوصلات في مساحة أسماء وصل عبر "الحقول الاختيارية" المعروضة في /proc/pid/mountinfo. (انظر proc(5) لمزيد من التفاصيل حول هذا الملف). يمكن أن تظهر الأوسمة التالية في الحقول الاختيارية لسجل في ذلك الملف:

shared:X
    عملية الوصل هذه مشتركة في مجموعة الأقران X. كل مجموعة أقران لها معرف فريد تولده النواة آلياً، وجميع الوصلات في مجموعة الأقران نفسها ستظهر نفس المعرف. (تُخصص هذه المعرفات بدءاً من القيمة 1، وقد يُعاد استخدامها عندما تكف مجموعة الأقران عن امتلاك أي أعضاء).

master:X
    عملية الوصل هذه تابعة لمجموعة الأقران المشتركة X.

propagate_from:X (منذ لينكس 2.6.26)
    عملية الوصل هذه تابعة وتتلقى الانتشار من مجموعة الأقران المشتركة X. سيظهر هذا الوسم دائماً بالاقتران مع وسم master:X. هنا، X هي أقرب مجموعة أقران مهيمنة تحت دليل الجذر للعملية. إذا كانت X هي السيد المباشر للوصل، أو إذا لم تكن هناك مجموعة أقران مهيمنة تحت الجذر نفسه، فعندئذٍ يوجد حقل master:X فقط وليس حقل propagate_from:X. لمزيد من التفاصيل، انظر أدناه.

unbindable
    هذا وصل غير قابل للتقييد.

إذا لم يكن أي من الأوسمة المذكورة أعلاه موجوداً، فهذا وصل خاص.

  مثال على MS_SHARED و MS_PRIVATE
لنفترض أننا في طرفية في مساحة أسماء الوصل الأولية، وسمنا وصلاً واحداً بأنه مشترك ووصلاً آخر بأنه خاص، ثم استعرضنا الوصلات في /proc/self/mountinfo:

    sh1# mount --make-shared /mntS
    sh1# mount --make-private /mntP
    sh1# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//'
    77 61 8:17 / /mntS rw,relatime shared:1
    83 61 8:15 / /mntP rw,relatime

من مخرجات /proc/self/mountinfo، نرى أن /mntS وصل مشترك في مجموعة أقران 1، وأن /mntP ليس له أوسمة اختيارية، مما يشير إلى أنه وصل خاص. أول حقلين في كل سجل في هذا الملف هما المعرف الفريد لهذا الوصل، ومعرف الوصل للأب. يمكننا معاينة هذا الملف أكثر لنرى أن الوصل الأب لـ /mntS و /mntP هو دليل الجذر /، الموصول كوصل خاص:

    sh1# cat /proc/self/mountinfo | awk '$1 == 61' | sed 's/ - .*//'
    61 0 8:2 / / rw,relatime

في طرفية ثانية، نُنشئ مساحة أسماء وصل جديدة حيث نشغل صدفة ثانية ونعاين الوصلات:

    $ PS1='sh2# ' sudo unshare -m --propagation unchanged sh
    sh2# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//'
    222 145 8:17 / /mntS rw,relatime shared:1
    225 145 8:15 / /mntP rw,relatime

تلقت مساحة أسماء الوصل الجديدة نسخة من وصلات مساحة أسماء الوصل الأولية. تحافظ هذه الوصلات الجديدة على أنواع الانتشار نفسها، لكن لها معرفات وصل فريدة. (يمنع الخيار --propagation unchanged الأمر unshare(1) من وسم كل الوصلات بأنها خاصة عند إنشاء مساحة أسماء وصل جديدة، وهو ما يفعله مبدئياً).

في الطرفية الثانية، نُنشئ وصلات فرعية تحت كل من /mntS و /mntP ونعاين الإعداد:

    sh2# mkdir /mntS/a
    sh2# mount /dev/sdb6 /mntS/a
    sh2# mkdir /mntP/b
    sh2# mount /dev/sdb7 /mntP/b
    sh2# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//'
    222 145 8:17 / /mntS rw,relatime shared:1
    225 145 8:15 / /mntP rw,relatime
    178 222 8:22 / /mntS/a rw,relatime shared:2
    230 225 8:23 / /mntP/b rw,relatime

مما سبق، يمكن رؤية أن /mntS/a أُنشئ كوصل مشترك (وارثاً هذا الإعداد من الوصل الأب له) و /mntP/b أُنشئ كوصل خاص.

بالعودة إلى الطرفية الأولى ومعاينة الإعداد، نرى أن الوصل الجديد المنشأ تحت الوصل المشترك /mntS قد انتشر إلى وصل قرينه (في مساحة أسماء الوصل الأولية)، لكن الوصل الجديد المنشأ تحت الوصل الخاص /mntP لم ينتشر:

    sh1# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//'
    77 61 8:17 / /mntS rw,relatime shared:1
    83 61 8:15 / /mntP rw,relatime
    179 77 8:22 / /mntS/a rw,relatime shared:2

  مثال على MS_SLAVE
جعل الوصل تابعاً يتيح له استقبال أحداث mount(2) و umount(2) المنتشرة من مجموعة أقران مشتركة رئيسة، مع منعه من نشر الأحداث إلى ذلك السيد. هذا مفيد إذا أردنا (مثلاً) تلقي حدث وصل عند وصل قرص بصري في مجموعة الأقران المشتركة الرئيسة (في مساحة أسماء وصل أخرى)، مع منع أحداث mount(2) و umount(2) تحت الوصل التابع من إحداث آثار جانبية في مساحات أسماء أخرى.

يمكننا إثبات تأثير التبعية بوسم وصلين أولاً بأنهما مشتركان في مساحة أسماء الوصل الأولية:

    sh1# mount --make-shared /mntX
    sh1# mount --make-shared /mntY
    sh1# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//'
    132 83 8:23 / /mntX rw,relatime shared:1
    133 83 8:22 / /mntY rw,relatime shared:2

في طرفية ثانية، نُنشئ مساحة أسماء وصل جديدة ونعاين الوصلات:

    sh2# unshare -m --propagation unchanged sh
    sh2# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//'
    168 167 8:23 / /mntX rw,relatime shared:1
    169 167 8:22 / /mntY rw,relatime shared:2

في مساحة أسماء الوصل الجديدة، نسم أحد الوصلات بأنه تابع:

    sh2# mount --make-slave /mntY
    sh2# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//'
    168 167 8:23 / /mntX rw,relatime shared:1
    169 167 8:22 / /mntY rw,relatime master:2

من المخرجات أعلاه، نرى أن /mntY هو الآن وصل تابع يتلقى أحداث الانتشار من مجموعة الأقران المشتركة ذات المعرف 2.

بالمتابعة في مساحة الأسماء الجديدة، نُنشئ وصلات فرعية تحت كل من /mntX و /mntY:

    sh2# mkdir /mntX/a
    sh2# mount /dev/sda3 /mntX/a
    sh2# mkdir /mntY/b
    sh2# mount /dev/sda5 /mntY/b

عند معاينة حالة الوصلات في مساحة أسماء الوصل الجديدة، نرى أن /mntX/a أُنشئ كوصل مشترك جديد (وارثاً إعداد "shared" من الوصل الأب) و /mntY/b أُنشئ كوصل خاص:

    sh2# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//'
    168 167 8:23 / /mntX rw,relatime shared:1
    169 167 8:22 / /mntY rw,relatime master:2
    173 168 8:3 / /mntX/a rw,relatime shared:3
    175 169 8:5 / /mntY/b rw,relatime

بالعودة إلى الطرفية الأولى (في مساحة أسماء الوصل الأولية)، نرى أن الوصل /mntX/a قد انتشر إلى القرين (المشترك /mntX)، لكن الوصل /mntY/b لم ينتشر:

    sh1# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//'
    132 83 8:23 / /mntX rw,relatime shared:1
    133 83 8:22 / /mntY rw,relatime shared:2
    174 132 8:3 / /mntX/a rw,relatime shared:3

الآن نُنشئ وصلاً جديداً تحت /mntY في الصدفة الأولى:

    sh1# mkdir /mntY/c
    sh1# mount /dev/sda1 /mntY/c
    sh1# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//'
    132 83 8:23 / /mntX rw,relatime shared:1
    133 83 8:22 / /mntY rw,relatime shared:2
    174 132 8:3 / /mntX/a rw,relatime shared:3
    178 133 8:1 / /mntY/c rw,relatime shared:4

عند فحص الوصلات في مساحة أسماء الوصل الثانية، نرى أنه في هذه الحالة قد انتشر الوصل الجديد إلى الوصل التابع، وأن الوصل الجديد نفسه هو وصل تابع (لمجموعة أقران 4):

    sh2# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//'
    168 167 8:23 / /mntX rw,relatime shared:1
    169 167 8:22 / /mntY rw,relatime master:2
    173 168 8:3 / /mntX/a rw,relatime shared:3
    175 169 8:5 / /mntY/b rw,relatime
    179 169 8:1 / /mntY/c rw,relatime master:4

  مثال على MS_UNBINDABLE
أحد الأغراض الرئيسة للوصلات غير القابلة للتقييد هو تجنب مشكلة "انفجار الوصل" عند إجراء وصلات تقييدية متكررة لشجرة فرعية عالية المستوى عند وصل من مستوى أدنى. توضح جلسة الصدفة التالية المشكلة.

لنفترض أن لدينا نظاماً بالوصلات التالية:

    # mount | awk '{print $1, $2, $3}'
    /dev/sda1 on /
    /dev/sdb6 on /mntX
    /dev/sdb7 on /mntY

ولنفترض أيضًا أننا نرغب في إجراء وصل تقييدي تكراري لدليل الجذر تحت أدلة المنزل لعدة مستخدمين. نفعل هذا للمستخدم الأول، ونعاين الوصلات:

    # mount --rbind / /home/cecilia/
    # mount | awk '{print $1, $2, $3}'
    /dev/sda1 on /
    /dev/sdb6 on /mntX
    /dev/sdb7 on /mntY
    /dev/sda1 on /home/cecilia
    /dev/sdb6 on /home/cecilia/mntX
    /dev/sdb7 on /home/cecilia/mntY

عندما نكرر هذه العملية للمستخدم الثاني، نبدأ في رؤية مشكلة الانفجار:

    # mount --rbind / /home/henry
    # mount | awk '{print $1, $2, $3}'
    /dev/sda1 on /
    /dev/sdb6 on /mntX
    /dev/sdb7 on /mntY
    /dev/sda1 on /home/cecilia
    /dev/sdb6 on /home/cecilia/mntX
    /dev/sdb7 on /home/cecilia/mntY
    /dev/sda1 on /home/henry
    /dev/sdb6 on /home/henry/mntX
    /dev/sdb7 on /home/henry/mntY
    /dev/sda1 on /home/henry/home/cecilia
    /dev/sdb6 on /home/henry/home/cecilia/mntX
    /dev/sdb7 on /home/henry/home/cecilia/mntY

تحت /home/henry، لم نضف وصلات /mntX و /mntY تكرارياً فحسب، بل أضفنا أيضًا الوصلات التكرارية لتلك الأدلة تحت /home/cecilia التي أُنشئت في الخطوة السابقة. عند تكرار الخطوة لمستخدم ثالث، يصبح من الواضح أن الانفجار أسي بطبيعته:

    # mount --rbind / /home/otto
    # mount | awk '{print $1, $2, $3}'
    /dev/sda1 on /
    /dev/sdb6 on /mntX
    /dev/sdb7 on /mntY
    /dev/sda1 on /home/cecilia
    /dev/sdb6 on /home/cecilia/mntX
    /dev/sdb7 on /home/cecilia/mntY
    /dev/sda1 on /home/henry
    /dev/sdb6 on /home/henry/mntX
    /dev/sdb7 on /home/henry/mntY
    /dev/sda1 on /home/henry/home/cecilia
    /dev/sdb6 on /home/henry/home/cecilia/mntX
    /dev/sdb7 on /home/henry/home/cecilia/mntY
    /dev/sda1 on /home/otto
    /dev/sdb6 on /home/otto/mntX
    /dev/sdb7 on /home/otto/mntY
    /dev/sda1 on /home/otto/home/cecilia
    /dev/sdb6 on /home/otto/home/cecilia/mntX
    /dev/sdb7 on /home/otto/home/cecilia/mntY
    /dev/sda1 on /home/otto/home/henry
    /dev/sdb6 on /home/otto/home/henry/mntX
    /dev/sdb7 on /home/otto/home/henry/mntY
    /dev/sda1 on /home/otto/home/henry/home/cecilia
    /dev/sdb6 on /home/otto/home/henry/home/cecilia/mntX
    /dev/sdb7 on /home/otto/home/henry/home/cecilia/mntY

يمكن تجنب مشكلة انفجار الوصل في السيناريو أعلاه بجعل كل من الوصلات الجديدة غير قابلة للتقييد. تأثير فعل ذلك هو أن الوصلات التكرارية لدليل الجذر لن تنسخ الوصلات غير القابلة للتقييد. نُجري مثل هذا الوصل للمستخدم الأول:

    # mount --rbind --make-unbindable / /home/cecilia

قبل المضي قدماً، نُبين أن الوصلات غير القابلة للتقييد هي بالفعل كذلك:

    # mkdir /mntZ
    # mount --bind /home/cecilia /mntZ
    mount: wrong fs type, bad option, bad superblock on /home/cecilia,
           missing codepage or helper program, or other error

           In some cases useful info is found in syslog - try
           dmesg | tail or so.

الآن نُنشئ وصلات تقييدية تكرارية غير قابلة للتقييد للمستخدمين الآخرين:

    # mount --rbind --make-unbindable / /home/henry
    # mount --rbind --make-unbindable / /home/otto

عند فحص قائمة الوصلات، نرى أنه لم يحدث انفجار للوصلات، لأن الوصلات غير القابلة للتقييد لم تُنسخ تحت دليل كل مستخدم:

    # mount | awk '{print $1, $2, $3}'
    /dev/sda1 on /
    /dev/sdb6 on /mntX
    /dev/sdb7 on /mntY
    /dev/sda1 on /home/cecilia
    /dev/sdb6 on /home/cecilia/mntX
    /dev/sdb7 on /home/cecilia/mntY
    /dev/sda1 on /home/henry
    /dev/sdb6 on /home/henry/mntX
    /dev/sdb7 on /home/henry/mntY
    /dev/sda1 on /home/otto
    /dev/sdb6 on /home/otto/mntX
    /dev/sdb7 on /home/otto/mntY

  انتقالات نوع الانتشار
يوضح الجدول التالي التأثير الذي يحدثه تطبيق نوع انتشار جديد (أي، mount --make-xxxx) على نوع الانتشار الحالي لعملية الوصل. تقابل الصفوف أنواع الانتشار الموجودة، والأعمدة هي إعدادات الانتشار الجديدة. لدواعي المساحة، اختُصرت "private" إلى "priv" و "unbindable" إلى "unbind".
 | make-shared | make-slave | make-priv | make-unbind
shared | shared | slave/priv [1] | priv | unbind
slave | slave+shared | slave [2] | priv | unbind
slave+shared | slave+shared | slave | priv | unbind
private | shared | priv [2] | priv | unbind
unbindable | shared | unbind [2] | priv | unbind

لاحظ التفاصيل التالية المتعلقة بالجدول:

[1] إذا كانت عملية الوصل المشتركة هي الوحيدة في مجموعة الأقران الخاصة بها، فإن جعلها تابعة يجعلها خاصة آليًا.

[2] لا يؤثر جعل عملية الوصل غير المشتركة تابعة على عملية الوصل.

  دلالات الربط (MS_BIND)
افترض أنه نُفّذ الأمر التالي:

    mount --bind A/a B/b

هنا، A هي وصلة المصدر، و B هي وصلة الوجهة، و a هو مسار دليل فرعي تحت نقطة الوصل A، و b هو مسار دليل فرعي تحت نقطة الوصل B. يعتمد نوع انتشار الوصلة الناتجة، B/b، على أنواع انتشار الوصلات A و B، وهو ملخص في الجدول التالي.

 |  |  | المصدر(A)
 |  | shared | private | slave | unbind
الوجهة(B) | shared | shared | shared | slave+shared | غير صالح
 | غير مشترك | shared | private | slave | غير صالح

لاحظ أن الربط المتكرر لشجرة فرعية يتبع نفس الدلالات الخاصة بعملية الربط لكل وصلة في الشجرة الفرعية. (تُقلّم الوصلات غير القابلة للارتباط آليًا عند نقطة الوصل الهدف).

لمزيد من التفاصيل، راجع Documentation/filesystems/sharedsubtree.rst في شجرة مصادر النواة.

  دلالات النقل (MS_MOVE)
افترض أنه نُفّذ الأمر التالي:

    mount --move A B/b

هنا، A هي وصلة المصدر، و B هي وصلة الوجهة، و b هو مسار دليل فرعي تحت نقطة الوصل B. يعتمد نوع انتشار الوصلة الناتجة، B/b، على أنواع انتشار الوصلات A و B، وهو ملخص في الجدول التالي.

 |  |  | المصدر(A)
 |  | shared | private | slave | unbind
الوجهة(B) | shared | shared | shared | slave+shared | غير صالح
 | غير مشترك | shared | private | slave | unbindable

ملاحظة: نقل وصلة تقع تحت وصلة مشتركة أمر غير صالح.

لمزيد من التفاصيل، راجع Documentation/filesystems/sharedsubtree.rst في شجرة مصادر النواة.

  دلالات الوصل
افترض أننا نستخدم الأمر التالي لإنشاء وصلة:

    mount device B/b

هنا، B هي وصلة الوجهة، و b هو مسار دليل فرعي تحت نقطة الوصل B. يتبع نوع انتشار الوصلة الناتجة، B/b، نفس القواعد المتبعة في وصلة الربط، حيث يُعتبر نوع انتشار وصلة المصدر دائمًا خاصًا.

  دلالات الفصل
افترض أننا نستخدم الأمر التالي لتفكيك وصلة:

    umount A

هنا، A هي وصلة على B/b، حيث B هي الوصلة الأب و b هو مسار دليل فرعي تحت نقطة الوصل B. إذا كانت B مشتركة، فستُفصل جميع الوصلات الموصولة حديثًا عند b على الوصلات التي تتلقى انتشارًا من الوصلة B وليس لديها وصلات فرعية تحتها.

  وسم propagate_from في /proc/ pid /mountinfo
يظهر الوسم propagate_from:X في الحقول الاختيارية لسجل /proc/pid/mountinfo في الحالات التي لا تستطيع فيها العملية رؤية السيد المباشر للتابع (أي أن مسار السيد لا يمكن الوصول إليه من دليل جذر نظام الملفات) وبالتالي لا يمكنها تحديد سلسلة الانتشار بين الوصلات التي يمكنها رؤيتها.

في المثال التالي، ننشئ أولاً سلسلة سيد-تابع من وصلتين بين الوصلات /mnt و /tmp/etc و /mnt/tmp/etc. ثم يُستخدم الأمر chroot(1) لجعل نقطة الوصل /tmp/etc غير قابلة للوصول من دليل الجذر، مما يخلق وضعًا لا يمكن فيه الوصول إلى سيد /mnt/tmp/etc من دليل الجذر (الجديد) للعملية.

أولاً، نقوم بوصل الربط لدليل الجذر على /mnt ثم وصل الربط لـ /proc عند /mnt/proc بحيث يظل نظام ملفات proc(5) مرئيًا في الموقع الصحيح في بيئة الـ chroot بعد تنفيذ chroot(1) لاحقًا.

    # mkdir -p /mnt/proc
    # mount --bind / /mnt
    # mount --bind /proc /mnt/proc

بعد ذلك، نتأكد من أن الوصلة /mnt هي وصلة مشتركة في مجموعة أقران جديدة (بدون أقران):

    # mount --make-private /mnt  # اعزله عن أي مجموعة أقران سابقة
    # mount --make-shared /mnt
    # cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//'
    239 61 8:2 / /mnt ... shared:102
    248 239 0:4 / /mnt/proc ... shared:5

بعد ذلك، نقوم بوصل الربط لـ /mnt/etc على /tmp/etc:

    # mkdir -p /tmp/etc
    # mount --bind /mnt/etc /tmp/etc
    # cat /proc/self/mountinfo | egrep '/mnt|/tmp/' | sed 's/ - .*//'
    239 61 8:2 / /mnt ... shared:102
    248 239 0:4 / /mnt/proc ... shared:5
    267 40 8:2 /etc /tmp/etc ... shared:102

في البداية، تكون هاتان الوصلتان في نفس مجموعة الأقران، ولكننا نجعل /tmp/etc تابعًا لـ /mnt/etc، ثم نجعل /tmp/etc مشتركًا أيضًا، حتى يتمكن من نشر الأحداث إلى التابع التالي في السلسلة:

    # mount --make-slave /tmp/etc
    # mount --make-shared /tmp/etc
    # cat /proc/self/mountinfo | egrep '/mnt|/tmp/' | sed 's/ - .*//'
    239 61 8:2 / /mnt ... shared:102
    248 239 0:4 / /mnt/proc ... shared:5
    267 40 8:2 /etc /tmp/etc ... shared:105 master:102

ثم نقوم بوصل الربط لـ /tmp/etc على /mnt/tmp/etc. مرة أخرى، تكون الوصلتان في البداية في نفس مجموعة الأقران، ولكننا نجعل /mnt/tmp/etc تابعًا لـ /tmp/etc:

    # mkdir -p /mnt/tmp/etc
    # mount --bind /tmp/etc /mnt/tmp/etc
    # mount --make-slave /mnt/tmp/etc
    # cat /proc/self/mountinfo | egrep '/mnt|/tmp/' | sed 's/ - .*//'
    239 61 8:2 / /mnt ... shared:102
    248 239 0:4 / /mnt/proc ... shared:5
    267 40 8:2 /etc /tmp/etc ... shared:105 master:102
    273 239 8:2 /etc /mnt/tmp/etc ... master:105

مما سبق، نرى أن /mnt هي السيد للتابع /tmp/etc، والذي بدوره هو السيد للتابع /mnt/tmp/etc.

ثم ننفذ chroot(1) إلى دليل /mnt، مما يجعل الوصلة ذات المعرف 267 غير قابلة للوصول من دليل الجذر (الجديد):

    # chroot /mnt

عند فحص حالة الوصلات داخل بيئة الـ chroot، نرى ما يلي:

    # cat /proc/self/mountinfo | sed 's/ - .*//'
    239 61 8:2 / / ... shared:102
    248 239 0:4 / /proc ... shared:5
    273 239 8:2 /etc /tmp/etc ... master:105 propagate_from:102

نرى أعلاه أن الوصلة ذات المعرف 273 هي تابع سيدها هو مجموعة الأقران 105. نقطة الوصل لهذا السيد غير قابلة للوصول، ولذلك يُعرض وسم propagate_from، مما يشير إلى أن أقرب مجموعة أقران مهيمنة (أي أقرب وصلة يمكن الوصول إليها في سلسلة التوابع) هي مجموعة الأقران ذات المعرف 102 (المقابلة لنقطة الوصل /mnt قبل تنفيذ chroot(1)).

المعايير
لينكس.

التاريخ
لينكس 2.4.19.

ملاحظات
يعتمد نوع الانتشار المعين لوصلة جديدة على نوع انتشار الوصلة الأب. إذا كان للوصلة أب (أي أنها ليست وصلة جذر) وكان نوع انتشار الأب هو MS_SHARED، فإن نوع انتشار الوصلة الجديدة يكون أيضًا MS_SHARED. خلاف ذلك، يكون نوع انتشار الوصلة الجديدة هو MS_PRIVATE.

على الرغم من أن نوع الانتشار المبدئي للوصلات الجديدة هو MS_PRIVATE في كثير من الحالات، إلا أن MS_SHARED عادة ما يكون أكثر فائدة. لهذا السبب، يقوم systemd(1) آليًا بإعادة وصل جميع الوصلات كـ MS_SHARED عند بدء تشغيل النظام. وبالتالي، في معظم الأنظمة الحديثة، يكون نوع الانتشار المبدئي عمليًا هو MS_SHARED.

بما أنه عند استخدام unshare(1) لإنشاء مساحة اسم وصل، يكون الهدف عادةً هو توفير عزل كامل للوصلات في مساحة الاسم الجديدة، فإن unshare(1) (منذ util-linux 2.27) يعكس بدوره الخطوة التي قام بها systemd(1)، بجعل جميع الوصلات خاصة في مساحة الاسم الجديدة. أي أن unshare(1) ينفذ ما يعادل التالي في مساحة اسم الوصل الجديدة:

    mount --make-rprivate /

لمنع ذلك، يمكن للمرء استخدام الخيار --propagation unchanged مع unshare(1).

قد يرغب التطبيق الذي ينشئ مساحة اسم وصل جديدة مباشرة باستخدام clone(2) أو unshare(2) في منع انتشار أحداث الوصل إلى مساحات أسماء الوصل الأخرى (كما يفعل unshare(1)). يمكن القيام بذلك عن طريق تغيير نوع انتشار الوصلات في مساحة الاسم الجديدة إلى MS_SLAVE أو MS_PRIVATE، باستخدام استدعاء مثل التالي:

    mount(NULL, "/", MS_SLAVE | MS_REC, NULL);

لمناقشة أنواع الانتشار عند نقل الوصلات (MS_MOVE) وإنشاء وصلات الربط (MS_BIND)، راجع Documentation/filesystems/sharedsubtree.rst.

  قيود على مساحات أسماء الوصل
لاحظ النقاط التالية فيما يتعلق بمساحات أسماء الوصل:

[1] لكل مساحة اسم وصل مساحة اسم مستخدم مالكة. كما هو موضح أعلاه، عندما تُنشأ مساحة اسم وصل جديدة، تُهيأ قائمة الوصل الخاصة بها كنسخة من قائمة وصل مساحة اسم وصل أخرى. إذا كانت مساحة الاسم الجديدة ومساحة الاسم التي نُسخت منها قائمة الوصل مملوكتين لمساحات أسماء مستخدمين مختلفة، فإن مساحة اسم الوصل الجديدة تُعتبر أقل امتيازًا.

[2] عند إنشاء مساحة اسم وصل أقل امتيازًا، تُختزل الوصلات المشتركة إلى وصلات تابعة. يضمن ذلك أن التعيينات التي تُجرى في مساحات أسماء الوصل الأقل امتيازًا لن تنتشر إلى مساحات أسماء الوصل الأكثر امتيازًا.

[3] تُقفل الوصلات التي تأتي كوحدة واحدة من مساحة اسم وصل أكثر امتيازًا معًا ولا يجوز فصلها في مساحة اسم وصل أقل امتيازًا. (تجلب عملية CLONE_NEWNS في unshare(2) جميع الوصلات من مساحة اسم الوصل الأصلية كوحدة واحدة، وتنتشر الوصلات المتكررة التي تنتشر بين مساحات أسماء الوصل كوحدة واحدة).

    في هذا السياق، تعني عبارة "لا يجوز فصلها" أن الوصلات مقفلة بحيث لا يمكن فصلها بشكل فردي. تأمل المثال التالي:

        $ sudo sh
        # mount --bind /dev/null /etc/shadow
        # cat /etc/shadow       # لا ينتج أي مخرج

    أدت الخطوات المذكورة أعلاه، والتي نُفذت في مساحة اسم وصل أكثر امتيازًا، إلى إنشاء وصلة ربط تحجب محتويات ملف كلمة السر الخفي، /etc/shadow. لأسباب أمنية، لا ينبغي أن يكون من الممكن فصل (umount(2)) تلك الوصلة في مساحة اسم وصل أقل امتيازًا، لأن ذلك سيكشف عن محتويات /etc/shadow.

    افترض أننا ننشئ الآن مساحة اسم وصل جديدة مملوكة لمساحة اسم مستخدم جديدة. ستَرث مساحة اسم الوصل الجديدة نسخًا من جميع الوصلات من مساحة اسم الوصل السابقة. ومع ذلك، ستُقفل تلك الوصلات لأن مساحة اسم الوصل الجديدة أقل امتيازًا. وبناءً على ذلك، ستفشل محاولة فصل (umount(2)) الوصلة كما هو موضح في الخطوة التالية:

        # unshare --user --map-root-user --mount \
        strace -o /tmp/log \
        umount /etc/shadow
        umount: /etc/shadow: not mounted.
        # grep '^umount' /tmp/log
        umount2("/etc/shadow", 0)     = -1 EINVAL (Invalid argument)

    رسالة الخطأ من mount(8) مربكة قليلاً، لكن مخرجات strace(1) تكشف أن استدعاء النظام umount2(2) الأساسي فشل مع الخطأ EINVAL، وهو الخطأ الذي ترجعه النواة للإشارة إلى أن الوصلة مقفلة.

    لاحظ، مع ذلك، أنه من الممكن تكديس (وفك تكديس) وصلة فوق إحدى الوصلات المقفلة الموروثة في مساحة اسم وصل أقل امتيازًا:

        # echo 'aaaaa' > /tmp/a    # ملف لوصله على /etc/shadow
        # unshare --user --map-root-user --mount \
        sh -c 'mount --bind /tmp/a /etc/shadow; cat /etc/shadow'
        aaaaa
        # umount /etc/shadow

    أمر umount(8) الأخير أعلاه، والذي نُفذ في مساحة اسم الوصل الأولية، يجعل ملف /etc/shadow الأصلي مرئيًا مرة أخرى في مساحة الاسم تلك.

[4] إلحاقًا بالنقطة [3]، لاحظ أنه من الممكن فصل (umount(2)) شجرة فرعية كاملة من الوصلات التي انتشرت كوحدة واحدة إلى مساحة اسم وصل أقل امتيازًا، كما هو موضح في المثال التالي.

    أولاً، ننشئ مساحات أسماء مستخدم ووصل جديدة باستخدام unshare(1). في مساحة اسم الوصل الجديدة، ضُبط نوع انتشار جميع الوصلات ليكون خاصًا. ثم ننشئ وصلة ربط مشتركة عند /mnt، وهرمية صغيرة من الوصلات تحت تلك الوصلة.

        $ PS1='ns1# ' sudo unshare --user --map-root-user \
        --mount --propagation private bash
        ns1# echo $$        # سنحتاج إلى PID هذه الصدفة لاحقًا
        778501
        ns1# mount --make-shared --bind /mnt /mnt
        ns1# mkdir /mnt/x
        ns1# mount --make-private -t tmpfs none /mnt/x
        ns1# mkdir /mnt/x/y
        ns1# mount --make-private -t tmpfs none /mnt/x/y
        ns1# grep /mnt /proc/self/mountinfo | sed 's/ - .*//'
        986 83 8:5 /mnt /mnt rw,relatime shared:344
        989 986 0:56 / /mnt/x rw,relatime
        990 989 0:57 / /mnt/x/y rw,relatime

    استمرارًا في نفس جلسة الصدفة، ننشئ صدفة ثانية في مساحة اسم مستخدم جديدة ومساحة اسم وصل جديدة (أقل امتيازًا) ونتحقق من حالة الوصلات المنتشرة المتجذرة عند /mnt.

        ns1# PS1='ns2# ' unshare --user --map-root-user \
        --mount --propagation unchanged bash
        ns2# grep /mnt /proc/self/mountinfo | sed 's/ - .*//'
        1239 1204 8:5 /mnt /mnt rw,relatime master:344
        1240 1239 0:56 / /mnt/x rw,relatime
        1241 1240 0:57 / /mnt/x/y rw,relatime

    مما يلاحظ في المخرج أعلاه هو أن نوع انتشار الوصلة /mnt قد اختُزل إلى تابع، كما هو موضح في النقطة [2]. وهذا يعني أن أحداث الوصل الفرعي ستنتشر من السيد /mnt في "ns1"، ولكن الانتشار لن يحدث في الاتجاه المعاكس.

    من نافذة طرفية منفصلة، نستخدم nsenter(1) للدخول إلى مساحات أسماء الوصل والمستخدم المقابلة لـ "ns1". في تلك النافذة الطرفية، نقوم بعد ذلك بوصل ربط متكرر لـ /mnt/x عند الموقع /mnt/ppp.

        $ PS1='ns3# ' sudo nsenter -t 778501 --user --mount
        ns3# mount --rbind --make-private /mnt/x /mnt/ppp
        ns3# grep /mnt /proc/self/mountinfo | sed 's/ - .*//'
        986 83 8:5 /mnt /mnt rw,relatime shared:344
        989 986 0:56 / /mnt/x rw,relatime
        990 989 0:57 / /mnt/x/y rw,relatime
        1242 986 0:56 / /mnt/ppp rw,relatime
        1243 1242 0:57 / /mnt/ppp/y rw,relatime shared:518

    نظرًا لأن نوع انتشار الوصل الأب، /mnt، كان مشتركًا، فقد نشر الوصل المربوط العودي (recursive bind mount) شجيرة وصلات صغيرة تحت الوصل التابع /mnt إلى "ns2"، كما يمكن التحقق من ذلك بتنفيذ الأمر التالي في جلسة الصدفة تلك:

        ns2# grep /mnt /proc/self/mountinfo | sed 's/ - .*//'
        1239 1204 8:5 /mnt /mnt rw,relatime master:344
        1240 1239 0:56 / /mnt/x rw,relatime
        1241 1240 0:57 / /mnt/x/y rw,relatime
        1244 1239 0:56 / /mnt/ppp rw,relatime
        1245 1244 0:57 / /mnt/ppp/y rw,relatime master:518

    في حين أنه لا يمكن فصل (umount(2)) جزء من الشجيرة المنشورة (/mnt/ppp/y) في "ns2"، إلا أنه يمكن فصل الشجيرة بأكملها، كما هو موضح في الأوامر التالية:

        ns2# umount /mnt/ppp/y
        umount: /mnt/ppp/y: not mounted.
        ns2# umount -l /mnt/ppp | sed 's/ - .*//'      # ينجح...
        ns2# grep /mnt /proc/self/mountinfo
        1239 1204 8:5 /mnt /mnt rw,relatime master:344
        1240 1239 0:56 / /mnt/x rw,relatime
        1241 1240 0:57 / /mnt/x/y rw,relatime

[5] تصبح إعدادات أعلام mount(2) المسماة MS_RDONLY و MS_NOSUID و MS_NOEXEC، وأعلام "atime" (مثل MS_NOATIME و MS_NODIRATIME و MS_RELATIME) مقفلة عند انتشارها من مساحة اسم وصل أكثر امتيازًا إلى مساحة اسم وصل أقل امتيازًا، ولا يجوز تغييرها في مساحة اسم الوصل الأقل امتيازًا.

    تتضح هذه النقطة في المثال التالي حيث نقوم، في مساحة اسم وصل أكثر امتيازًا، بإنشاء وصل مربط وُسم بكونه للقراءة فقط. ولأسباب أمنية، يجب ألا يكون من الممكن جعل الوصل قابلًا للكتابة في مساحة اسم وصل أقل امتيازًا، وبالفعل تمنع النواة ذلك:

        $ sudo mkdir /mnt/dir
        $ sudo mount --bind -o ro /some/path /mnt/dir
        $ sudo unshare --user --map-root-user --mount \
        mount -o remount,rw /mnt/dir
        mount: /mnt/dir: permission denied.

[6] إن الملف أو الدليل الذي يعد نقطة وصل في مساحة اسم واحدة ولكنه ليس نقطة وصل في مساحة اسم أخرى، يجوز إعادة تسميته أو فك ربطه أو إزالته (rmdir(2)) في مساحة اسم الوصل التي لا يكون فيها نقطة وصل (يخضع ذلك لفحوصات الأذونات المعتادة). ونتيجة لذلك، تُزال نقطة الوصل في مساحة اسم الوصل التي كانت فيها نقطة وصل.

    سابقًا (قبل لينكس 3.18)، كانت محاولة فك ربط أو إعادة تسمية أو إزالة ملف أو دليل كان يمثل نقطة وصل في مساحة اسم وصل أخرى تؤدي إلى الخطأ EBUSY. كان لهذا السلوك مشكلات تقنية في الإنفاذ (على سبيل المثال، لـ NFS) وسمح بشن هجمات حجب الخدمة ضد المستخدمين الأكثر امتيازًا (أي منع تحديث ملفات فردية عن طريق عمل وصل مربط فوقها).

أمثلة
انظر pivot_root(2).

انظر أيضًا
unshare(1), clone(2), mount(2), mount_setattr(2), pivot_root(2), setns(2), umount(2), unshare(2), proc(5), namespaces(7), user_namespaces(7), findmnt(8), mount(8), pam_namespace(8), pivot_root(8), umount(8)

Documentation/filesystems/sharedsubtree.rst في شجرة مصدر النواة.

ترجمة
تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي <zayed.alsaidi@gmail.com>

هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 (https://www.gnu.org/licenses/gpl-3.0.html) أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.

إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: kde-l10n-ar@kde.org.