بقلم كريس سيبينمان ، مدير أنظمة يونكس بجامعة تورنتومن وقت لآخر ، يحدث شيء غريب في عملي يجعلني أفكر. حتى لو لم يكن واضحًا ما هي الاستنتاجات التالية. لقد ذكرت مؤخرًا أننا وجدنا خللًا في 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 ، لأنني اكتشفته يوم الجمعة فقط ، والجامعة في إجازة الشتاء الآن. لا تتردد في القيام بذلك أمامي.