प्रतिनिधि इंटरव्यू विषय

सिस्टम डिज़ाइन इंटरव्यू: आप एक रिकवरेबल यूज़रस्पेस ब्लॉक-डिवाइस ड्राइवर कैसे डिज़ाइन करेंगे?

सिस्टम डिज़ाइनकठिन
Offer.cc संपादकीय टीमप्रकाशित अपडेट किया गया

प्रश्न

एक ऐसा सिस्टम डिज़ाइन करें जो वर्चुअल ब्लॉक-डिवाइस लॉजिक को यूज़रस्पेस में रखता हो। इसे उच्च-समवर्ती (high-concurrency) I/O, यूज़रस्पेस-प्रोसेस क्रैश रिकवरी, परमिशन आइसोलेशन और ऑब्जर्वेबिलिटी का समर्थन करना चाहिए। कंट्रोल/डेटा-प्लेन प्रोटोकॉल बाउंड्री को समझाएं।

प्रांप्ट और संदर्भ

एक ऐसा सिस्टम डिज़ाइन करें जो वर्चुअल ब्लॉक-डिवाइस लॉजिक को यूज़रस्पेस में रखता हो: कर्नेल एक ब्लॉक डिवाइस को एक्सपोज़ करता है जबकि एक यूज़रस्पेस सर्विस लूप, रिमोट ब्लॉक स्टोरेज या qcow2 मैपिंग को संभालती है। इसे हाई-कंकरेंसी I/O, यूज़रस्पेस-प्रोसेस क्रैश रिकवरी, परमिशन आइसोलेशन और ऑब्जर्वेबिलिटी का समर्थन करना चाहिए।

Linux ublk इस फ्रेमवर्क को एक कंट्रोल प्लेन और एक डेटा प्लेन में अलग करता है: /dev/ublk-control डिवाइसेस को मैनेज करता है, /dev/ublkb* ब्लॉक I/O को ले जाता है, और यूज़रस्पेस सर्विस io_uring पासथ्रू के माध्यम से अनुरोध प्राप्त करती है और परिणाम कमिट करती है। यह इंटरव्यू केवल फ़ाइल I/O को एक प्रोसेस में ले जाने के बजाय रिक्वेस्ट लाइफसाइकिल, विफलता सेमांटिक्स (failure semantics) और सुरक्षा सीमाओं का परीक्षण करता है।

इंटरव्यूअर क्या जांच रहा है

कंट्रोल, कर्नेल ब्लॉक लेयर, io_uring और यूज़रस्पेस बैकएंड के बीच की सीमाओं को प्रदर्शित करें। कतारों (queues), टैग्स, बफ़र्स और कंप्लीशन्स के बीच एक-से-एक (one-to-one) संबंध की व्याख्या करें; प्रति-I/O और बैच मोड के बीच चयन करें; सर्वर के बाहर निकलने (exit) पर रीकतार (requeue), फ़ेल और रीप्ले सेमांटिक्स को परिभाषित करें; और ज़ीरो-कॉपी, विशेषाधिकारों (privileges), कंटेनर आइसोलेशन और मेट्रिक्स को संभालें।

पहले स्पष्ट करने योग्य प्रश्न

वर्कलोड और बैकएंड

रीड/राइट अनुपात, I/O आकार, कतारों की संख्या, लेटेंसी लक्ष्य, क्या बैकएंड एक स्थानीय फ़ाइल, रिमोट NBD, या कॉपी-ऑन-राइट प्रारूप है, और क्या ऑर्डरिंग गारंटी की आवश्यकता है, इसकी पुष्टि करें।

विफलता और डेटा सुरक्षा

यूज़रस्पेस क्रैश, नेटवर्क विभाजन (partition), बैकएंड पर शॉर्ट राइट, डुप्लिकेट राइट और डिवाइस हटाने के लिए सेमांटिक्स की पुष्टि करें। स्थापित करें कि क्या रीप्ले डबल राइट्स को सहन कर सकता है।

अनुमतियाँ और परिनियोजन (Deployment)

पुष्टि करें कि कौन डिवाइस बना सकता है, कौन /dev/ublkc* को पढ़ सकता है, क्या सर्विस एक कंटेनर में चलती है, किन ज़ीरो-कॉपी विशेषाधिकारों की अनुमति है, और किरायेदारों (tenants) को कैसे अलग किया जाता है।

एक 30-सेकंड का उत्तर

“मैं कंट्रोल और डेटा प्लेन को अलग करता हूँ। कंट्रोल डिवाइस शुरू करने से पहले कतारों, गहराई और फीचर्स पर बातचीत (negotiate) करता है; डेटा कतार और टैग द्वारा io_uring से अनुरोध प्राप्त करता है और परिणाम कमिट करता है। प्रत्येक अनुरोध का एक स्वामी, स्थिति और टाइमआउट होता है। जब यूज़रस्पेस सर्वर बाहर निकलता है, तो मैं डिवाइस को शांत (quiesce) करता हूँ और बैकएंड गारंटी के अनुसार रीकतार (requeue), फ़ेल या रीप्ले चुनता हूँ। कॉपी करना डिफ़ॉल्ट है; ज़ीरो-कॉपी केवल विश्वसनीय, अधिकृत बैकएंड तक सीमित है। मेट्रिक्स कतार की गहराई, कंप्लीशन लेटेंसी, पुनः प्रयास (retries), ड्रॉप्स और रिकवरी समय को कवर करते हैं, जिसमें हटाने और रिकवरी के लिए निरंतरता (consistency) परीक्षण शामिल हैं।”

चरण-दर-चरण विस्तृत उत्तर

चरण 1: कंट्रोल प्लेन को विभाजित करें

डिवाइस को जोड़ने, पैरामीटर सेट/गेट करने, शुरू करने, रोकने और हटाने के लिए कमांड्स एक्सपोज़ करें। एक जोड़ने पर nr_hw_queues, queue_depth और अधिकतम I/O-बफ़र आकार पर बातचीत होती है; पैरामीटर शुरू होने से पहले फ्रीज हो जाते हैं, जिसके बाद /dev/ublkb* एक्सपोज़ होता है। यूज़रस्पेस सर्विस डिवाइस आईडी और बैकएंड-विशिष्ट जानकारी संग्रहीत करती है।

चरण 2: डेटा-प्लेन अनुरोधों को डिज़ाइन करें

ब्लॉक लेयर प्रति कतार एक अद्वितीय टैग प्रदान करती है, और यूज़रस्पेस सर्विस अनुरोधों को (queue, tag) द्वारा संबद्ध करती है। एक निश्चित मैप किया गया क्षेत्र ऑफ़सेट, लंबाई, ऑपरेशन और फ़्लैग का वर्णन करता है। सर्विस io_uring पासथ्रू के माध्यम से सूचनाएं प्राप्त करती है और स्थिति और पूर्ण किए गए बाइट्स को कर्नेल में वापस कमिट करती है।

चरण 3: प्रति-I/O या बैच मोड चुनें

पारंपरिक प्रति-I/O कमांड्स को समझना आसान है, जिसमें प्रत्येक टैग का स्वामित्व एक डेमॉन के पास होता है। बैच मोड प्रति कतार कई अनुरोधों को तैयार और कमिट करता है, सिस्टम कॉल ओवरहेड को कम करता है, और कार्यों को गतिशील रूप से काम साझा करने की अनुमति देता है। माइग्रेशन के दौरान कमांड सेट को मिश्रित न करें; दबाव में टेल लेटेंसी, CPU और लोड बैलेंसिंग की तुलना करें।

चरण 4: रिकवरी स्टेट मशीन को परिभाषित करें

रनिंग, क्विएसिंग, रिकवरिंग और फेल्ड जैसी स्थितियों का उपयोग करें। सर्वर के बाहर निकलने पर, नया I/O भेजना बंद करें, इन-फ़्लाइट अनुरोधों की प्रतीक्षा करें या उन्हें चिह्नित करें, और START_USER_RECOVERY जारी करें। REISSUE उन बैकएंड के अनुकूल है जो डुप्लिकेट राइट्स को सहन करते हैं; FAIL_IO सफलता की झूठी रिपोर्ट देने के बजाय इन-फ़्लाइट और भविष्य के अनुरोधों को स्पष्ट रूप से विफल बनाता है।

text
on_server_exit:
  quiesce_device()
  if policy == REISSUE:
    requeue_inflight()
  else:
    fail_inflight_and_future_io()
  wait_new_server_ready()
  end_user_recovery()

चरण 5: बफ़र्स और ज़ीरो-कॉपी को संभालें

सामान्य पथ प्री-एलोकेटेड यूज़रस्पेस बफ़र्स और कर्नेल कॉपियों का उपयोग करता है, जो सरल सीमाएं प्रदान करता है। ज़ीरो-कॉपी के लिए पंजीकृत फिक्स्ड बफ़र्स, बैकएंड सेगमेंट संरेखण (alignment), और एक विश्वसनीय सर्विस की आवश्यकता होती है जो READ डेटा भरती है और बाइट काउंट की सही रिपोर्ट करती है। एक गलती अप्रारंभीकृत कर्नेल बफ़र्स को उजागर कर सकती है, इसलिए विशेषाधिकारों को प्रतिबंधित करें और लाइफटाइम का ऑडिट करें।

चरण 6: अनुमति और कंटेनर आइसोलेशन का निर्माण करें

विशेषाधिकार प्राप्त कंट्रोल कमांड्स को डिवाइस एक्सेस से अलग करें। गैर-विशेषाधिकार प्राप्त डिवाइसेस के साथ, कर्नेल अभी भी प्रासंगिक कैरेक्टर डिवाइस के स्वामित्व की जांच करता है; एक कंटेनर को केवल अपने डिवाइस नोड्स देखने चाहिए। यूज़रस्पेस बैकएंड को उसके लक्षित डिवाइस से परे फ़ाइल, नेटवर्क या KMS अनुमतियाँ प्राप्त नहीं होनी चाहिए।

चरण 7: प्रदर्शन और शुद्धता सत्यापित करें

fio या प्रोडक्शन जैसे वर्कलोड के साथ IOPS, p50/p99 लेटेंसी, कतार की गहराई, CPU, कॉपी किए गए बाइट्स और रिकवरी समय को मापें। सर्वर क्रैश, बैकएंड टाइमआउट, शॉर्ट राइट्स, डिवाइस विलोपन और डुप्लिकेट सबमिशन इंजेक्ट करें। सत्यापित करें कि प्रत्येक अनुरोध नीति के अनुसार एक बार पूरा हो या स्पष्ट रूप से विफल हो; कॉपी और ज़ीरो-कॉपी दोनों मोड में सीमाओं और चेकसम का परीक्षण करें।

मॉडल उत्तर

मैं ublk जैसे सिस्टम को कंट्रोल प्लेन, कर्नेल ब्लॉक लेयर, io_uring डेटा प्लेन और यूज़रस्पेस बैकएंड में विभाजित करूँगा। कंट्रोल शुरू होने से पहले कतारों और बफ़र्स पर बातचीत करता है; डेटा (queue, tag) द्वारा अनुरोधों को ट्रैक करता है और पूरा होने पर स्थिति और बाइट काउंट को मान्य करता है। सर्वर क्रैश क्विएसिंग और रिकवरी को ट्रिगर करता है: केवल उसी बैकएंड के लिए रीप्ले करें जो इसे सहन कर सके, अन्यथा फ़ेल करें। कॉपी करना डिफ़ॉल्ट है; ज़ीरो-कॉपी केवल विश्वसनीय, संरेखित, अधिकृत सेवाओं तक सीमित है। रिलीज़ के लिए टेल-लेटेंसी, फॉल्ट-इंजेक्शन, परमिशन-आइसोलेशन और रिमूवल-कंसिस्टेंसी परीक्षणों की आवश्यकता होती है।

सामान्य गलतियाँ

  • गलती: यूज़रस्पेस सर्वर को डिवाइस को सीधे बंद करने की अनुमति देना। → यह क्यों विफल होता है: इन-फ़्लाइट अनुरोध और कर्नेल-कतार की स्थिति अपरिभाषित रहती है। → सुधार: डिस्पैच रोकें, क्विएस करें, फिर एक रिकवरी नीति लागू करें।
  • गलती: प्रत्येक बैकएंड के लिए ज़ीरो-कॉपी सक्षम करना। → यह क्यों विफल होता है: बफ़र लाइफटाइम, विशेषाधिकार और अप्रारंभीकृत-डेटा के जोखिम बढ़ते हैं। → सुधार: डिफ़ॉल्ट रूप से कॉपी करें और क्षमता और ऑडिट के आधार पर ज़ीरो-कॉपी को नियंत्रित करें।
  • गलती: एक ही ग्लोबल लॉक से सभी कतारों की सुरक्षा करना। → यह क्यों विफल होता है: मल्टी-कतार समवर्ती (concurrency) क्रमबद्ध (serialized) हो जाती है। → सुधार: कतार/टैग द्वारा स्थिति को शार्ड करें और विवाद (contention) को मापें।
  • गलती: केवल स्वस्थ I/O थ्रूपुट को मापना। → यह क्यों विफल होता है: क्रैश, शॉर्ट राइट्स और डुप्लिकेट राइट्स निरंतरता निर्धारित करते हैं। → सुधार: स्वीकृति परीक्षणों में रिकवरी स्टेट मशीन और फॉल्ट इंजेक्शन को शामिल करें।

फॉलो-अप प्रश्न और उत्तर

आपको बैच I/O कब चुनना चाहिए?

बैच तब चुनें जब सिस्टम कॉल और नोटिफिकेशन ओवरहेड प्रभावी हों, कतारों में पर्याप्त समवर्ती हो, और कार्य गतिशील रूप से काम साझा कर सकें। जब प्रति-I/O स्वामित्व मायने रखता है या समवर्ती कम होती है, तो पारंपरिक मोड को डिबग करना आसान होता है।

REISSUE डेटा करप्शन से कैसे बचाता है?

अनुरोध आईडी, राइट वर्ज़न या लॉग डिडुप्लीकेशन का उपयोग करके इसे केवल इडेम्पोटेंट या डुप्लिकेट-डिटेक्टिंग बैकएंड के लिए सक्षम करें। यदि इडेम्पोटेंस सिद्ध नहीं किया जा सकता है, तो फ़ेल करें और ऊपरी परत को रिकवर करने दें।

आप ज़ीरो-कॉपी के सुरक्षा प्रभाव को कैसे सीमित करते हैं?

बफ़र पंजीकरण, अपंजीकरण और डिवाइस अनुमतियों को एक विश्वसनीय सर्विस से बाँधें; पता, लंबाई, संरेखण और पूर्ण बाइट्स को मान्य करें; और किरायेदारों के बीच साझा की गई लिखने योग्य मैपिंग को प्रतिबंधित करें।

आप डिवाइस हटाने के दौरान निरंतरता कैसे बनाए रखते हैं?

नए अनुरोधों को रोकें, सबमिट किए गए अनुरोधों के पूर्ण होने या विफल होने की प्रतीक्षा करें, पुष्टि करें कि यूज़रस्पेस कतार खाली है, फिर डिवाइस नोड्स और मैपिंग को रिलीज़ करें। टाइमआउट को चुपचाप छोड़ने के बजाय ट्रेस करने योग्य विफलताओं के रूप में रिकॉर्ड करें।

सार्वजनिक स्रोत

संबंधित प्रश्न

संबंधित इंटरव्यू टूल

सिस्टम डिज़ाइन उत्तर के लिए हल करें का उपयोग करें

पहले आवश्यकताओं को स्पष्ट करें, फिर स्केल, आर्किटेक्चर, कंपोनेंट चयन और ट्रेड-ऑफ की ओर बढ़ें।

टूल देखें