2010-09-21 8 views
14

POSIX फ़ाइल सिस्टम में फ़ाइल का सही नाम बदलने का सही तरीका क्या है? निर्देशिका पर fsyncs के बारे में विशेष रूप से सोच रहा है। (यदि यह ओएस/एफएस पर निर्भर करता है, तो मैं लिनक्स और ext3/ext4 के बारे में पूछ रहा हूं)।POSIX में फ़ाइल का सही नाम बदलने के लिए कैसे करें?

नोट: वहाँ टिकाऊ renames के बारे में StackOverflow पर अन्य प्रश्न हैं, लेकिन वे fsync-इंग निर्देशिका का पता नहीं AFAICT (जो कि मुझे क्या मायने रखती है - मैं भी संशोधित नहीं कर रहा हूँ फ़ाइल डेटा)।

मैं वर्तमान में (अजगर में):

dstdirfd = open(dstdirpath, O_DIRECTORY|O_RDONLY) 
rename(srcdirpath + '/' + filename, dstdirpath + '/' + filename) 
fsync(dstdirfd) 

विशिष्ट सवालों:

  • भी इस करता परोक्ष स्रोत निर्देशिका fsync? या हो सकता है कि मैं पावर चक्र के बाद दोनों निर्देशिकाओं में दिखाए गए फ़ाइल के साथ समाप्त हो जाऊं (जिसका अर्थ है कि मुझे हार्ड लिंक गिनती की जांच करनी होगी और मैन्युअल रूप से वसूली करना होगा), यानी एक स्थायी परमाणु चालन संचालन की गारंटी देना असंभव है?
  • यदि मैं गंतव्य निर्देशिका को गंतव्य निर्देशिका के बजाय fsync करता हूं, तो यह भी गंतव्य निर्देशिका fsync को निश्चित रूप से fsync करेगा?
  • क्या कोई उपयोगी संबंधित परीक्षण/डिबगिंग/सीखने के उपकरण (गलती इंजेक्टर, आत्मनिरीक्षण उपकरण, नकली फाइल सिस्टम इत्यादि) हैं?

अग्रिम धन्यवाद।

उत्तर

14

POSIX परिभाषित करता है कि नाम बदलने समारोह परमाणु होना चाहिए:

http://pubs.opengroup.org/onlinepubs/009695399/functions/rename.html

तो अगर आप का नाम बदलने (

वैसे भी, इस लेख fsync के बारे में अपने प्रश्नों का उत्तर देने लगती है ए, बी), किसी भी परिस्थिति में आपको कभी भी निर्देशिकाओं या न तो निर्देशिका दोनों में फ़ाइल के साथ एक राज्य देखना चाहिए। एफएसआईएनसीसी() या सिस्टम क्रैश होने पर आप क्या करते हैं, इससे कोई फर्क नहीं पड़ता।

लेकिन यह सुनिश्चित करने की समस्या को हल नहीं करता है कि नाम() ऑपरेशन टिकाऊ है।

_POSIX_SYNCHRONIZED_IO परिभाषित किया गया है, तो fsync() फ़ंक्शन सिंक्रनाइज़ I/O पूर्णता राज्य के लिए फ़ाइल वर्णनकर्ता fildes ने संकेत दिया फ़ाइल से संबद्ध सभी वर्तमान पंक्तिबद्ध आई/ओ के संचालन के लिए मजबूर करेगा: POSIX इस सवाल का जवाब देता है। सभी I/O संचालन को सिंक्रनाइज़ I/O फ़ाइल अखंडता पूर्णता के लिए परिभाषित के रूप में पूरा किया जाएगा।

(http://pubs.opengroup.org/onlinepubs/009695399/functions/fsync.html से)

तो अगर आप fsync() एक निर्देशिका, लंबित ऑपरेशन का नाम बदलने के समय इस रिटर्न द्वारा डिस्क में स्थानांतरित किया जाना चाहिए। किसी भी निर्देशिका का fsync() पर्याप्त होना चाहिए क्योंकि नाम() ऑपरेशन की परमाणुता की आवश्यकता होगी कि दोनों निर्देशिकाओं के परिवर्तन परमाणु रूप से समन्वयित किया जाए।

अंत में, ब्लॉग पोस्ट एक और जवाब में बताया गया में दावा के विपरीत, इस के लिए तर्क बताते हैं निम्नलिखित:

fsync() फ़ंक्शन से डेटा का एक भौतिक लिखने के लिए मजबूर करने का इरादा है बफर कैश, और यह सुनिश्चित करने के लिए कि सिस्टम क्रैश या अन्य विफलता के बाद fsync() कॉल के समय तक सभी डेटा डिस्क पर दर्ज किया गया है। चूंकि "बफर कैश", "सिस्टम क्रैश", "भौतिक लेखन" और "गैर-अस्थिर भंडारण" की अवधारणाओं को यहां परिभाषित नहीं किया गया है, इसलिए शब्द को और अधिक सार होना चाहिए।

एक प्रणाली है कि POSIX अनुरूप होने का दावा किया और कहा कि माना जाता है कि यह सही व्यवहार (यानी नहीं एक बग या हार्डवेयर विफलता) एक fsync() को पूरा करने और नहीं एक सिस्टम क्रैश भर में उन परिवर्तनों को जारी रहती है जानबूझ कर गलत ढंग से प्रस्तुत करना होगा करने के लिए खुद को कल्पना के संबंध में।

+1

यहां तर्क बहुत गलत है। - नाम के "परमाणु" (उदाहरण के लिए, "न्यूपैथ" को संदर्भित करता है, जिसके अंतर्गत पुरानी फ़ाइल (यदि कोई थी) या नामित फ़ाइल होनी चाहिए, जिसमें कोई भी स्थिति नहीं है (जैसा कि अन्य प्रक्रियाओं द्वारा देखा गया है) । –

+0

रॉबर्ट ने इसे इंगित किया, नाम बदलने के लिए नया इनोड असाइन करने के संबंध में नाम "परमाणु" है, चाहे नया इनोड पॉइंटिक्स द्वारा परिभाषित किया गया हो या नहीं। – ArekBulski

-1

आपके प्रश्न का उत्तर विशिष्ट ओएस पर इस्तेमाल होने पर निर्भर करता है, फाइल सिस्टम का उपयोग किया जा रहा है और क्या स्रोत और dest एक ही डिवाइस पर हैं या नहीं।

मैं आपके द्वारा उपयोग किए जा रहे प्लेटफ़ॉर्म पर नाम बदलें (2) मैन पेज पढ़कर शुरू करूंगा।

+0

पहले से ही उस पृष्ठ पृष्ठ से परामर्श लिया - कुछ भी प्रासंगिक नहीं है। आप कह रहे हैं कि निर्देशिकाओं का नाम बदलने का कोई पोर्टेबल तरीका नहीं है? मैं विश्वास करने के लिए तैयार हूं कि एक स्पष्ट बयान और आदर्श समर्थन साक्ष्य में रुचि रखते हैं। साथ ही, क्या आप ext3/4 के साथ हाल ही के लिनक्स 2.6 के जवाब का जवाब जानते हैं (जैसा कि यह प्रश्न टैग किया गया था - बस मुख्य पाठ को भी अपडेट किया गया है)? – Yang

+0

आह ठीक है, सरल है अगर यह सिर्फ लिनक्स और ext3/4 है जिसकी आप परवाह है। एक चेतावनी है कि लिनक्स नाम (2) मैन पेज का उल्लेख है: 'हालांकि, जब ओवरराइटिंग शायद एक खिड़की होगी जिसमें पुरानीपथ और न्यूपैथ दोनों नाम बदलकर फ़ाइल का संदर्भ लेंगे।' –

-3

ऐसा लगता है जैसे आप फाइल सिस्टम का काम करने की कोशिश कर रहे हैं। यदि आप फ़ाइल ले जाते हैं तो कर्नेल और फ़ाइल-सिस्टम परमाणु संचालन और गलती-वसूली के लिए ज़िम्मेदार हैं, न कि आपका कोड। http://blogs.gnome.org/alexl/2009/03/16/ext4-vs-fsync-my-take/

+0

पहले उस पोस्ट को पढ़ें, और यह कई में से एक है जो मुझे यहाँ लाया। यह विशेष रूप से कहता है: "लिखने के कुछ ही समय बाद सिस्टम क्रैश होने पर, इसकी संभावना अधिक है कि हमें पुरानी फ़ाइल की तुलना में नई फ़ाइल मिलती है (इसके अधिकतम मौके के लिए आपको अतिरिक्त निर्देशिका में फ़ाइल को fsync करने की आवश्यकता है)।" मेरा सवाल यह है कि जब आप निर्देशिकाओं में नाम बदल रहे होते हैं तो क्या होता है। – Yang

11

दुर्भाग्य डेव जवाब गलत है:

(लिनक्स विशिष्ट बनाम पोर्टेबल व्यवहार अतिरिक्त जानकारी पुनः के साथ अद्यतन)।

सभी POSIX सिस्टम में टिकाऊ संग्रहण भी नहीं हो सकता है। और यदि वे करते हैं, तो सिस्टम सिस्टम दुर्घटना के बाद भी इसे "अनुमति" होनी चाहिए। उन प्रणालियों के लिए एक नो-ऑप fsync() समझ में आता है, और ऐसे fsync() को POSIX के तहत स्पष्ट रूप से अनुमति दी जाती है। पुरानी निर्देशिका, नई निर्देशिका, दोनों, या किसी अन्य स्थान में फ़ाइल को पुनर्प्राप्त करने योग्य भी कानूनी है। POSIX सिस्टम क्रैश या फ़ाइल सिस्टम रिकवरी के लिए कोई गारंटी नहीं देता है।

असली सवाल किया जाना चाहिए:

सिस्टम जो POSIX एपीआई के माध्यम से समर्थन करने वाले पर एक टिकाऊ नाम बदलने कैसे करना है?

आप एक fsync() दोनों पर क्या करने की जरूरत है, स्रोत और गंतव्य निर्देशिका, क्योंकि कम से कम उन fsync() रों क्या करना चाहिए रहे हैं जारी रहती है स्रोत या गंतव्य निर्देशिका की तरह दिखना चाहिए कैसे है।

क्या एक fsync (destdirfd) भी स्रोत निर्देशिका fsync अंतर्निहित है? सामान्य रूप में

  • POSIX: नहीं, कुछ भी नहीं मतलब है कि
  • ext3/4: मुझे यकीन है कि अगर दोनों परिवर्तन स्रोत के लिए और गंतव्य निर्देशिका पत्रिका में एक ही लेन-देन में समाप्त नहीं कर रहा हूँ। यदि वे करते हैं, तो वे दोनों एक साथ प्रतिबद्ध हो जाते हैं।

या मैं दोनों निर्देशिका में एक शक्ति चक्र ("गिरावट") के बाद दिखा फ़ाइल है, यानी यह एक durably परमाणु कदम आपरेशन की गारंटी करने के असंभव है के साथ खत्म हो सकता है?

  • सामान्य में POSIX: कितना fsync() आप न्यूनतम जरूरत पर निर्भर करता है: कोई गारंटी है, लेकिन आप fsync करने के लिए() दोनों निर्देशिका है, जो परमाणु-टिकाऊ नहीं हो सकता है
  • ext3/4 चाहिए रहे हैं माउंट विकल्प। जैसे अगर "dirsync" के साथ घुड़सवार है तो आपको उन दो fsync() एस में से किसी की आवश्यकता नहीं है। सबसे अधिक आपको fsync() एस दोनों की आवश्यकता है, लेकिन मुझे यकीन है कि एक पर्याप्त है (परमाणु-टिकाऊ)।

यदि मैं गंतव्य निर्देशिका के बजाय स्रोत निर्देशिका fsync करता हूं, तो क्या यह गंतव्य निर्देशिका को पूरी तरह से fsync करेगा?

  • POSIX: कोई
  • ext3/4: मैं वास्तव में दोनों एक ही लेन-देन में समाप्त विश्वास करते हैं, तो यह कोई फर्क नहीं पड़ता उनमें से जो आप fsync()
  • पुराने कर्नेल ext3: (यदि वे एक ही लेनदेन में नहीं हैं) कुछ गैर-इष्टतम कार्यान्वयन ने fsync() पर बहुत अधिक समन्वय किया है, मुझे यकीन है कि यह पहले से आए प्रत्येक लेनदेन को प्रतिबद्ध करता है। और हां, एक सामान्य कार्यान्वयन पहले इसे गंतव्य से लिंक करेगा और फिर इसे स्रोत से हटा देगा। तो fsync (srcdirfd) गंतव्य के fsync() को भी ट्रिगर करेगा।
  • ext4/नवीनतम ext3: अगर वे एक ही लेन-देन में नहीं हैं, तो आप पूरी तरह से उन्हें स्वतंत्र रूप से सिंक करने के लिए (ताकि दोनों)

वहाँ किसी भी उपयोगी संबंधित परीक्षण/डिबगिंग/शिक्षा टूल हैं सक्षम हो सकता है (गलती इंजेक्टर, आत्मनिरीक्षण उपकरण, नकली फाइल सिस्टम, आदि)?

वास्तविक क्रैश के लिए, नहीं। वैसे, एक असली दुर्घटना कर्नेल के दृष्टिकोण से परे चला जाता है। हार्डवेयर फाइल सिस्टम को दूषित कर सकता है (और सबकुछ लिखने में असफल) लिख सकता है। Ext4 इसके खिलाफ बेहतर तैयार है, क्योंकि यह डिफ़ॉल्ट रूप से लेखन बैरी (माउंट विकल्प) सक्षम करता है (ext3 नहीं करता है) और जर्नल चेकसम (एक माउंट विकल्प भी) के साथ भ्रष्टाचार का पता लगा सकता है।

और सीखने के लिए: पता लगाएं कि दोनों परिवर्तन जर्नल में किसी तरह से जुड़े हुए हैं या नहीं! :- पी

+1

यह एक सूक्ष्म बिंदु है, लेकिन मैं बहस नहीं कर रहा था कि एक निर्देशिका का fsync() * दूसरे का * fsync() का तात्पर्य है। यह था कि नाम के परमाणुता के साथ संयुक्त, fsync(), की आवश्यकता है कि * उस विशिष्ट परिवर्तन * को अन्य निर्देशिका में भी डिस्क में सिंक किया जाए।मैं विश्वास कर सकता हूं कि यह मामला नहीं है, लेकिन यह मेरी कल्पना का पठन है। क्या आपके पास अपनी व्याख्या का बैक अप लेने का संदर्भ है कि परमाणुता को किसी दुर्घटना में गारंटी नहीं है, भले ही "परमाणु" परिवर्तन का हिस्सा fsync'd था? –

+0

हां, मैं करता हूं: opengroup.org पर [fsync() पर आपका लिंक] (http://pubs.opengroup.org/onlinepubs/009695399/functions/fsync.html)। "यह स्पष्ट रूप से इरादा है कि एक शून्य कार्यान्वयन की अनुमति है।" यह है: कोई गारंटी नहीं है। - और नाम() और fsync() की इच्छापूर्ण लिंकिंग आपका आविष्कार है। और नहीं, यह एक सूक्ष्म बिंदु नहीं है। –

+1

सहमत हैं कि POSIX सिस्टम को ऐसे किसी भी बदलाव को टिकाऊ बनाने की आवश्यकता नहीं है, और वास्तविक सवाल यह है कि एपीआई का उपयोग करने वाले सिस्टम पर टिकाऊ बदलाव करने के लिए एपीआई का उपयोग कैसे करें। (हालांकि, यह सवाल स्पष्ट रूप से लगता है कि चूंकि अंतर्निहित प्रणाली इसका समर्थन करती है।) एक संदर्भ मांगने में, मैं आपके दावे का जिक्र कर रहा था कि उन प्रणालियों पर भी जो डिस्क पर सिंकिंग का समर्थन करते हैं, सफल किसी भी निर्देशिका का fsync() अभी भी क्रैश के बाद दोनों स्थानों (या न तो) में दिखाई देने वाली फ़ाइल में परिणाम दे सकता है। –

संबंधित मुद्दे