लिनक्स पृष्ठभूमि फ्लश (गंदे पृष्ठ) सीमित करें


26

लिनक्स पर पृष्ठभूमि का फ्लशिंग तब होता है जब या तो बहुत अधिक लिखित डेटा लंबित होता है (समायोज्य / proc / sys / vm / dirty_background_ratio के माध्यम से) या लंबित लेखन के लिए एक समय सीमा समाप्त हो जाती है (/ proc / sys / vm / dirty_backire_centisecs)। जब तक एक और सीमा हिट नहीं हो रही है (/ proc / sys / vm / dirty_ratio), अधिक लिखित डेटा कैश किया जा सकता है। आगे लिखेंगे ब्लॉक।

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

क्या फ्लशिंग प्रक्रिया का प्रदर्शन प्रति सेकंड अनुरोधों की मात्रा को सीमित करने का एक तरीका है, या अन्यथा प्रभावी रूप से अन्य डिवाइस I / O को प्राथमिकता देता है?


हो सकता है कि यह linux kernel mailing list vger.kernel.org/vger-lists.html#linux-kernel

आप किस IO अनुसूचक का उपयोग कर रहे हैं?
3dinfluence

विभिन्न (cfq, समय सीमा) की कोशिश की, लेकिन मुझे लगता है कि ये केवल मज़बूती से काम करते हैं जब कोई बैटरी समर्थित राइट-कैश शामिल नहीं है। एक डिस्क सरणी की तरह मैं PCIe बस की गति (RAM) में 1 GiB डेटा खाता है और फिर वास्तविकता-दीवार को हिट करता है। कई सेकंड शून्य I / O सभी LUN के लिए। वास्तविक डिवाइस की गति के मोटे अनुमान के लिए थ्रॉटलिंग फ्लश (कम से कम पृष्ठभूमि वाले) उस भीड़ की समस्या को हल करेंगे।
कॉर्कमैन

1
मुझे हाल ही में / sys / block / sdX / queue / nr_requests के बारे में पता चला है जो एक प्रमुख ट्यूनेबल है। इसे न्यूनतम (= 4 मेरे मामले में) करने से समवर्ती भार विलंबता बहुत बेहतर हो जाती है: Sysbench fsync यादृच्छिक प्रति सेकंड 4 (j!) से 80-90 तक dd के साथ बस की गति से लिखते समय लिखता है। गैर-लोडेड प्रदर्शन अप्रभावित लगता है। शेड्यूलर सभी समान हैं, नोप या समय सीमा इष्टतम लगती है। यह अधिकांश BBWC कॉन्फ़िगरेशन के लिए सही हो सकता है।
कॉर्कमैन

जवाबों:


20

Sysbench के साथ बहुत सारे बेंचमार्किंग के बाद, मैं इस नतीजे पर आता हूं:

जीवित रहने के लिए (प्रदर्शन वार) ऐसी स्थिति जहां

  • एक दुष्ट प्रतिलिपि प्रक्रिया गंदे पृष्ठों को बाढ़ देती है
  • और हार्डवेयर राइट-कैश मौजूद है (संभवतः इसके बिना भी)
  • और तुल्यकालिक पढ़ता है या प्रति सेकंड (IOPS) लिखता है महत्वपूर्ण हैं

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

जितना संभव हो उतना गंदे_रोटो (या नए गंदे_बाइट्स) को समायोजित करें, लेकिन क्रमिक थ्रूपुट पर नज़र रखें। मेरे विशेष मामले में, 15 एमबी इष्टतम थे ( echo 15000000 > dirty_bytes)।

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


तुलना के लिए विनिर्देशों और बेंचमार्क:

परीक्षण किया गया जबकि dd'डिस्क के लिए शून्य, sysbench ने भारी सफलता दिखाई , 10 थ्रेड्स fsync को बढ़ाकर 16 kB पर 33 से 700 IOPS (निष्क्रिय सीमा: 1500 IOPS) और 8 से 400 OOPS तक एकल थ्रेड लिखते हैं।

लोड के बिना, IOPS अप्रभावित थे (~ 1500) और थ्रूपुट थोड़ा कम (251 एमबी / एस से 216 एमबी / एस तक)।

dd फोन:

dd if=/dev/zero of=dumpfile bs=1024 count=20485672

sysbench के लिए, test_file.0 के साथ असुरक्षित होने के लिए तैयार किया गया था:

dd if=/dev/zero of=test_file.0 bs=1024 count=10485672

10 धागे के लिए sysbench कॉल:

sysbench --test=fileio --file-num=1 --num-threads=10 --file-total-size=10G --file-fsync-all=on --file-test-mode=rndwr --max-time=30 --file-block-size=16384 --max-requests=0 run

एक धागे के लिए sysbench कॉल:

sysbench --test=fileio --file-num=1 --num-threads=1 --file-total-size=10G --file-fsync-all=on --file-test-mode=rndwr --max-time=30 --file-block-size=16384 --max-requests=0 run

छोटे ब्लॉक आकार ने और भी अधिक कठोर संख्याएँ दिखाईं।

-फाइल-ब्लॉक-आकार = 1 जीबी गंदे_बीट्स के साथ 4096:

sysbench 0.4.12:  multi-threaded system evaluation benchmark

Running the test with following options:
Number of threads: 1

Extra file open flags: 0
1 files, 10Gb each
10Gb total file size
Block size 4Kb
Number of random requests for random IO: 0
Read/Write ratio for combined random IO test: 1.50
Calling fsync() after each write operation.
Using synchronous I/O mode
Doing random write test
Threads started!
Time limit exceeded, exiting...
Done.

Operations performed:  0 Read, 30 Write, 30 Other = 60 Total
Read 0b  Written 120Kb  Total transferred 120Kb  (3.939Kb/sec)
      0.98 Requests/sec executed

Test execution summary:
      total time:                          30.4642s
      total number of events:              30
      total time taken by event execution: 30.4639
      per-request statistics:
           min:                                 94.36ms
           avg:                               1015.46ms
           max:                               1591.95ms
           approx.  95 percentile:            1591.30ms

Threads fairness:
      events (avg/stddev):           30.0000/0.00
      execution time (avg/stddev):   30.4639/0.00

-फाइल-ब्लॉक-साइज = 4096 15 एमबी गंदे_बाइट्स के साथ:

sysbench 0.4.12:  multi-threaded system evaluation benchmark

Running the test with following options:
Number of threads: 1

Extra file open flags: 0
1 files, 10Gb each
10Gb total file size
Block size 4Kb
Number of random requests for random IO: 0
Read/Write ratio for combined random IO test: 1.50
Calling fsync() after each write operation.
Using synchronous I/O mode
Doing random write test
Threads started!
Time limit exceeded, exiting...
Done.

Operations performed:  0 Read, 13524 Write, 13524 Other = 27048 Total
Read 0b  Written 52.828Mb  Total transferred 52.828Mb  (1.7608Mb/sec)
    450.75 Requests/sec executed

Test execution summary:
      total time:                          30.0032s
      total number of events:              13524
      total time taken by event execution: 29.9921
      per-request statistics:
           min:                                  0.10ms
           avg:                                  2.22ms
           max:                                145.75ms
           approx.  95 percentile:              12.35ms

Threads fairness:
      events (avg/stddev):           13524.0000/0.00
      execution time (avg/stddev):   29.9921/0.00

-फाइल-ब्लॉक-साइज = 4096 के साथ 15 एमबी गंदे_बाइट बेकार सिस्टम पर:

sysbench 0.4.12: मल्टी-थ्रेडेड सिस्टम मूल्यांकन बेंचमार्क

Running the test with following options:
Number of threads: 1

Extra file open flags: 0
1 files, 10Gb each
10Gb total file size
Block size 4Kb
Number of random requests for random IO: 0
Read/Write ratio for combined random IO test: 1.50
Calling fsync() after each write operation.
Using synchronous I/O mode
Doing random write test
Threads started!
Time limit exceeded, exiting...
Done.

Operations performed:  0 Read, 43801 Write, 43801 Other = 87602 Total
Read 0b  Written 171.1Mb  Total transferred 171.1Mb  (5.7032Mb/sec)
 1460.02 Requests/sec executed

Test execution summary:
      total time:                          30.0004s
      total number of events:              43801
      total time taken by event execution: 29.9662
      per-request statistics:
           min:                                  0.10ms
           avg:                                  0.68ms
           max:                                275.50ms
           approx.  95 percentile:               3.28ms

Threads fairness:
      events (avg/stddev):           43801.0000/0.00
      execution time (avg/stddev):   29.9662/0.00

टेस्ट सिस्टम:

  • एडेप्टेक 5405Z (जो कि सुरक्षा के साथ 512 एमबी राइट-कैश है)
  • इंटेल Xeon L5520
  • 6 GiB RAM @ 1066 MHz
  • मदरबोर्ड सुपरमाइक्रो X8DTN (5520 चिपसेट)
  • 12 सीगेट बाराकुडा 1 टीबी डिस्क
    • लिनक्स सॉफ्टवेयर RAID 10 में 10
  • कर्नेल 2.6.32
  • फ़ाइल सिस्टम xfs
  • डेबियन अस्थिर

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


'15MB के लिए गंदे_बर्फर्स इष्टतम है 'भाग में पहुंचने के लिए आपकी कार्यप्रणाली क्या है?
मार्सिन

1
परीक्षण त्रुटि विधि। जैसे, अगली बार आधी राशि बदलें, आदि, जब तक मैं मात्र 15 एमबी और ओके आईओपीएस के साथ समाप्त नहीं हो गया। वर्तमान कर्नेल 3.2 बहुत भिन्न हो सकता है, BTW।
कॉर्कमैन

2
बस मुझे सही रास्ते पर लाने के लिए धन्यवाद कहना चाहता था। कुछ इसी तरह के मुद्दों के साथ एक XenServer नोड था। गंदा पन्नों के कारण PHP-FPM / APC कैश निकला। एपीसी कैश मेमोरी मॉडल को समायोजित करने से हमारे लिए समस्या हल हो गई। डिस्कियो 20% उपयोग से 0.
जेफेट्रैकैड

तार्किक रूप से dirty_bytesसीपीयू को स्टाल नहीं करने के लिए पर्याप्त रूप से उच्च होना चाहिए जबकि प्रक्रियाएं लिख रही हैं यदि प्रक्रिया डिवाइस के थ्रूपुट के साथ औसतन लिख रही है। यदि आपका एप्लिकेशन कोड विशाल संगणना का चक्रण कर रहा है, जिसके बाद भारी मात्रा में डेटा लिखा जाता है, अगर इसे अनुकूलित करना बहुत कठिन होगा क्योंकि कम समय का औसत लंबे समय के औसत से काफी भिन्न होता है। सही समाधान प्रक्रिया विशिष्ट dirty_bytesसेटिंग को समायोजित करने के लिए होगा, लेकिन लिनक्स जहां तक ​​मुझे पता है ऐसी चीज का समर्थन नहीं करता है।
मिकको रेंटालिनेन

3

भले ही ट्यूनिंग कर्नेल मापदंडों ने समस्या को रोक दिया, यह वास्तव में संभव है कि आपके प्रदर्शन के मुद्दे Adaptec 5405Z नियंत्रक पर बग के परिणाम थे जो 1 फरवरी 2012 के फर्मवेयर अपडेट में तय किए गए थे। रिलीज नोट्स कहते हैं "फिक्स्ड एक मुद्दा जहां फर्मवेयर उच्च I / O तनाव के दौरान लटका सकता है।" शायद आई / ओ को फैलाने के रूप में आपने इस बग को ट्रिगर होने से रोकने के लिए पर्याप्त था, लेकिन यह सिर्फ एक अनुमान है।

यहाँ जारी नोट हैं: http://download.adaptec.com/pdfs/readme/relnotes_arc_fw-b18937_asm-18837.pdf

यहां तक ​​कि अगर यह आपकी विशेष स्थिति के लिए ऐसा नहीं था, तो मुझे लगा कि इससे भविष्य में इस पोस्ट पर आने वाले उपयोगकर्ताओं को लाभ मिल सकता है। हमने अपने dmesg आउटपुट में निम्नलिखित कुछ संदेश देखे, जो अंततः हमें फर्मवेयर अपडेट में ले गए:

aacraid: Host adapter abort request (0,0,0,0)
[above was repeated many times]
AAC: Host adapter BLINK LED 0x62
AAC0: adapter kernel panic'd 62.
sd 0:0:0:0: timing out command, waited 360s
sd 0:0:0:0: Unhandled error code
sd 0:0:0:0: SCSI error: return code = 0x06000000
Result: hostbyte=DID_OK driverbyte=DRIVER_TIMEOUT,SUGGEST_OK
sd 0:0:0:0: timing out command, waited 360s
sd 0:0:0:0: Unhandled error code
sd 0:0:0:0: SCSI error: return code = 0x06000028
Result: hostbyte=DID_OK driverbyte=DRIVER_TIMEOUT,SUGGEST_OK
sd 0:0:0:0: timing out command, waited 360s
sd 0:0:0:0: Unhandled error code
sd 0:0:0:0: SCSI error: return code = 0x06000028

यहां Adaptec RAID नियंत्रकों के मॉडल नंबर दिए गए हैं जो फर्मवेयर के लिए जारी नोटों में सूचीबद्ध हैं जिनमें उच्च I / O हैंग फिक्स हैं: 2045, 2405, 2405Q, 2805, 5085, 5405, 5405Z, 5445, 5445Z, 5805 5805Q, 5805Z, 5805ZQ, 51245, 51645, 52445।


1
वाह, आपके इनपुट के लिए धन्यवाद। यद्यपि यह मेरे लिए मामला नहीं था, फिर भी आप मुझे HW RAID से पूरी तरह बचने और HBA के केवल सेटअप पर जाने का एक और कारण देते हैं। HW RAID में अभी भी BBWC का लाभ है, लेकिन bcache जैसी चीजों के साथ कर्नेल में घूमना, यहां तक ​​कि गायब हो जाता है। HW RAID के लिए con साइड आपके द्वारा वर्णित फर्मवेयर बग की तरह है। मेरे पास डीआरबीडी सेटअप और उच्च आई / ओ लोड के साथ एक और सिस्टम है, जिसके कारण फर्मवेयर-रीसेट होते हैं, इसलिए यह भर में आना दुर्लभ नहीं है (हो सकता है कि वास्तव में यह बग हो)।
कॉर्कमैन

1

एक कर्नेल जिसमें "WBT" शामिल है:

ब्लॉक लेयर में सुधार , LWN.net

राइटबैक थ्रॉटलिंग के साथ, [ब्लॉक लेयर] कॉडेल नेटवर्क शेड्यूलर से उधार ली गई रणनीति का उपयोग करके अत्यधिक I / O विलंबता के बिना अधिकतम प्रदर्शन प्राप्त करने का प्रयास करता है। CoDel नेटवर्क पैकेटों की देखी गई न्यूनतम विलंबता को ट्रैक करता है और अगर यह एक थ्रेशोल्ड मान से अधिक है, तो यह पैकेट छोड़ना शुरू कर देता है। ड्रॉपिंग राइट्स को I / O सबसिस्टम में रखा जाता है, लेकिन एक समान रणनीति का पालन किया जाता है कि कर्नेल दोनों रीड और राइट की न्यूनतम विलंबता पर नज़र रखता है और यदि वह थ्रेशोल्ड मान से अधिक है, तो यह बैकग्राउंड राइटबैक की मात्रा को बंद करना शुरू कर देता है। यह किया जा रहा है। यह व्यवहार 4.10 में जोड़ा गया था; Axboe ने कहा कि बहुत अच्छे परिणाम देखे गए हैं।

WBT को नए ब्लक-mq ब्लॉक लेयर पर स्विच करने की आवश्यकता नहीं है। उस ने कहा, यह CFQ या BFQ I / O शेड्यूलर्स के साथ काम नहीं करता है। आप डेडलाइन / mq-deadline / noop / none अनुसूचियों के साथ WBT का उपयोग कर सकते हैं। मेरा मानना ​​है कि यह नए "कीबर" I / O अनुसूचक के साथ भी काम करता है।

विलंबता को नियंत्रित करने के लिए कतार आकार को स्केल करने के साथ-साथ, WBT कोड परिकलित कतार सीमा के अनुपात के रूप में पृष्ठभूमि राइटबैक अनुरोधों की संख्या को सीमित करता है।

रनटाइम कॉन्फ़िगरेशन में है /sys/class/block/*/queue/wbt_lat_usec

बिल्ड कॉन्फ़िगरेशन विकल्प देखने के लिए हैं

/boot/config-4.20.8-200.fc29.x86_64:CONFIG_BLK_WBT=y
/boot/config-4.20.8-200.fc29.x86_64:# CONFIG_BLK_WBT_SQ is not set
/boot/config-4.20.8-200.fc29.x86_64:CONFIG_BLK_WBT_MQ=y

WBT के लेखक द्वारा आपके समस्या कथन की पुष्टि 100% है - अच्छी तरह से किया गया :-)।

[PATCHSET] ब्लॉक: बफ़र थ्रोटबैक थ्रॉटलिंग

समय के भोर के बाद से, हमारी पृष्ठभूमि ने राइटबैक को चूसा है। जब हम बैकग्राउंड बफ़र करते हैं, तो इसका अग्रभूमि गतिविधि पर बहुत कम प्रभाव पड़ता है। यह पृष्ठभूमि की गतिविधि की परिभाषा है ... लेकिन जब तक मैं याद रख सकता हूं, तब तक भारी बफर लेखकों ने ऐसा व्यवहार नहीं किया है। उदाहरण के लिए, अगर मैं ऐसा कुछ करता हूं:

$ dd if=/dev/zero of=foo bs=1M count=10k

मेरे लैपटॉप पर, और फिर कोशिश करें और क्रोम शुरू करें, यह मूल रूप से बफ़र लिखने से पहले शुरू नहीं होगा। या, सर्वर उन्मुख वर्कलोड के लिए, जहां एक बड़ा RPM (या समान) की स्थापना डेटाबेस के रीडर्स या सिंक राइट्स पर प्रतिकूल प्रभाव डालती है। जब ऐसा होता है, मैं लोगों को मुझ पर चिल्लाता हूं।

कुछ हालिया परीक्षण के परिणाम यहां देखे जा सकते हैं:

https://www.facebook.com/axboe/posts/10154074651342933

पैचसेट के बड़े विवरण के लिए पिछली पोस्टिंग देखें।


मुझे यह देखकर खुशी हो रही है कि समस्या को पहचान लिया गया है और अब कर्नेल के अंदर से निपटा जा रहा है। ध्यान रखें ब्लाक-माक काफी नया है और शायद अभी तक परिपक्व नहीं हुआ है।
कॉर्कमैन

@korkman आह, मुझे लगता है कि मैं झूठे निहितार्थ से बचने के लिए बोली लगाऊंगा। मुझे लगता है कि यह पिछले कुछ वर्षों में जोड़ा गया सामान है, वहाँ अभी भी प्रदर्शन प्रतिगमन या बदतर हो सकते हैं। AFAIR अनुरक्षक डेटा भ्रष्टाचार को इस मायने में खारिज करता है कि यह एक अस्थायी है। यदि आप कर्नेल संस्करणों का उपयोग कर रहे हैं जहाँ blk-mq विकसित किया गया था, तो यह तर्क है कि "विरासत" ब्लॉक लेयर का उपयोग करने से कीड़े से कितना बचा जाएगा। मैंने जो सस्पेंड बग तय किया था, वह एक बग था, जो blk-mq में उत्पन्न हुआ था, फिर इसे रिफैक्ट किया गया या कुछ और प्रभावित किया गया। github.com/torvalds/linux/commit/1dc3039bc87a
sourcejedi

0

Dirty in / proc / meminfo के लिए आपका औसत क्या है? यह आमतौर पर आपके / proc / sys / vm / dirty_ratio से अधिक नहीं होना चाहिए। समर्पित फ़ाइल सर्वर पर मेरे पास मैमोरी (90) के बहुत अधिक प्रतिशत के लिए गंदे_प्रपात है, क्योंकि मैं इसे कभी भी पार नहीं करूंगा। आपका गंदा_करण बहुत कम है, जब आप इसे मारते हैं, तो सब कुछ बाहर निकलता है, इसे बढ़ाएं।


यह समस्या नहीं है प्रक्रियाओं को अवरुद्ध किया जा रहा है जब गंदे_आराट को मार रहा है। मैं उसके साथ ठीक हूं। लेकिन डिस्क को गंदा डेटा लिखने की "पृष्ठभूमि" प्रक्रिया दया के बिना कतारों को भर देती है और आईओपीएस प्रदर्शन को मार देती है। यह IO भुखमरी मुझे लगता है कि कहा जाता है। वास्तव में, गंदे_रैटो_बाइट्स को बहुत कम सेट करना (जैसे 1 एमबी) अलॉट करने में मदद करता है, क्योंकि फ्लशिंग लगभग तुरंत हो जाएगा और कतारों को खाली रखा जाएगा। अनुक्रमिक के लिए ड्रॉबैक संभवतः कम थ्रूपुट है, लेकिन यह ठीक है।
कॉर्कमैन

आपने सभी लिफ्ट बंद कर दी हैं? वनिला सिस्टम से आपने और क्या ट्विक किया?
ल्यूक

1
मेरा आत्म-उत्तर देखिए। कहानी का अंत गंदे कैशिंग को हटाने और एचडब्ल्यू नियंत्रक को उस हिस्से को छोड़ने के लिए था। एलेवेटर एचडब्ल्यू राइट-कैश के साथ थोड़े अप्रासंगिक हैं। कंट्रोलर के पास खुद का एलेवेटर एल्गोरिदम होता है इसलिए सॉफ्टवेयर में कोई भी एलेवेटर होने से केवल ओवरहेड जुड़ता है।
कॉर्कमैन

सॉफ्टवेयर में एलेवेटर एक ट्रेडऑफ़ है: बैंडविड्थ में सुधार करने के लिए विलंबता का त्याग। उदाहरण के लिए, यादृच्छिक क्रम में प्रस्तुत सॉफ्टवेयर कतार में 100K ऑप्स लिखने की कल्पना करें; यदि सॉफ्टवेयर एलेवेटर एक विशाल बफर का उपयोग करके उन ऑप्स को ऑर्डर कर सकता है, तो यह डिवाइस को केवल 5K बहुत बड़े अनुरोध भेजना समाप्त कर सकता है। हालांकि, परिणामस्वरूप, विलंबता को 100K ऑप्स तक बढ़ाने की आवश्यकता है क्योंकि यह हो सकता है कि पहले 2k ऑप्स और अंतिम 1K ऑप्स वास्तव में डिवाइस पर एक दूसरे के पास हों। अतिरिक्त विलंबता के बिना, उन लोगों को विलय करना असंभव होगा।
मिकको रेंटालिनेन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.