كيف وجدت خطأ في جنو تار

بقلم كريس سيبينمان ، مدير أنظمة يونكس بجامعة تورنتو

من وقت لآخر ، يحدث شيء غريب في عملي يجعلني أفكر. حتى لو لم يكن واضحًا ما هي الاستنتاجات التالية. لقد ذكرت مؤخرًا أننا وجدنا خللًا في GNU Tar ، وقصة كيف حدث هذا هي إحدى هذه الحالات.

بالنسبة لخوادم الملفات الاحتياطية ، نستخدم أماندا وجنو تار. بمرور الوقت ، واجهنا أحيانًا مشكلة نادرة إلى حد ما حيث أصبح القطران مجنونًا عند النسخ الاحتياطي لنظام الملفات باستخدام دليل /var/mail ، مما ينتج عنه قدر كبير من المخرجات. عادة ما ذهبت هذه العملية إلى ما لا نهاية واضطررت إلى قتل التفريغ. في حالات أخرى ، لا يزال ينتهي بإصدار تيرابايت من البيانات التي يبدو أنها مضغوطة تمامًا. عندما صادفت مرةً أخرى ملف القطران العملاق هذا ، راجعتُه - ​​واكتشفت أنه يتكون جزئيًا من صفر بايت ، وهو ما يكره فريق اختبار tar -t حقًا ، وبعد ذلك يعود كل شيء إلى طبيعته.

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

لقد قمنا مؤخرًا بنقل نظام الملفات من /var/mail إلى خوادم ملفات Linux الجديدة تحت Ubuntu 18.04 وبالتالي انتقلنا إلى إصدار أحدث وأكثر معيارًا من GNU Tar مقارنةً بأجهزة OmniOS. كنا نأمل أن يحل هذا مشاكلنا ، ولكن نفس الحادث وقع على الفور تقريبًا. هذه المرة ، عمل GNU Tar على جهاز Ubuntu ، حيث تعرفت جيدًا على جميع أدوات تصحيح الأخطاء المتاحة ، لذلك راجعت عملية tar الجارية. أظهر الاختبار أن tar ينتج دفقًا لا ينتهي من read() إرجاع 0 بايت:

 read(6, "", 512) = 0 read(6, "", 512) = 0 [...] read(6, "", 512) = 0 write(1, "\0\0\0\0\0"..., 10240) = 10240 read(6, "", 512) = 0 [...] 

وقال أن ملف واصف 6 هو صندوق بريد شخص آخر.

باستخدام apt-get source tar قمت بتنزيل الكود المصدري وبدأت أبحث عن مكالمات نظام read() التي لم تتحقق من اكتمال الملف. بعد فحص عدة مستويات للعنونة غير المباشرة ، وجدت مكانًا واضحًا حيث يبدو أن هذا الفحص تم حذفه ، أي في وظيفة sparse_dump_region من ملف sparse.cs . ثم تذكرت شيئًا ما.

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

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

لقد عابثت قليلاً في GDB مع رموز تصحيح Ubuntu ورمز مصدر حزمة tar الذي تلقيته ، وكنت قادرًا على إعادة إنتاج الخطأ ، على الرغم من أنه كان مختلفًا إلى حد ما عن نظريتي الأصلية. اتضح أن sparse_dump_region لا يعيد تعيين المناطق المتفرقة في الملف ، لكنه يعيد تعيين المناطق غير المتفرقة (بالطبع) ، ويستخدم لجميع الملفات (متفرقة أم لا) إذا قمت بتشغيل tar باستخدام الوسيطة - --sparse . وبالتالي ، فإن الخطأ الفعلي هو أنه إذا قمت بتشغيل GNU Tar باستخدام وسيطة - --sparse وكان الملف مضغوطًا أثناء قراءته ، فلن يتمكن tar من معالجة نهاية الملف الذي تم استلامه قبل الموعد المتوقع بشكل صحيح . إذا كان الملف ينمو مرة أخرى ، يستعيد القطران.

(ما عدا عندما يكون الملف متناثرًا فقط في النهاية ويتم ضغطه في هذا المكان فقط. في هذه الحالة ، يكون كل شيء جيدًا).

اعتقدت أنه على الرغم من ذلك ، فقد تمكنت من التحقق قبل سنوات عديدة على خوادم ملفات OmniOS الخاصة بنا. هناك طرق لتتبع مكالمات نظام البرنامج ونظائرها ، ويمكنني العثور على الكود المصدري وإصداره لإصداري من جنو تار وتشغيله باستخدام مصحح أخطاء OmniOS (على الرغم من أننا لا يبدو أننا قد قمنا بتثبيت GDB) ، وهكذا. لكنني لم أفعل. بدلاً من ذلك ، تجاهلنا وانتقلنا. لقد تطلب الأمر نقل نظام الملفات تحت Ubuntu حتى أقوم بتحريك إصبعي واكتشاف المشكلة.

(لا يقتصر الأمر على الأدوات والبيئة فحسب ، بل افترضنا تلقائيًا أن OmniOS كان لديه نوع قديم من النسخ غير المدعومة من GNU Tar ، وهو أمر لا معنى له ، نظرًا بالطبع تم حل المشكلة في الإصدار الأحدث).

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

PPS: لم أحاول الإبلاغ عن الخطأ إلى مطوري GNU Tar ، لأنني اكتشفته يوم الجمعة فقط ، والجامعة في إجازة الشتاء الآن. لا تتردد في القيام بذلك أمامي.

Source: https://habr.com/ru/post/ar434624/


All Articles