MD模塊之處理讀寫過程分析-1

md可以說是一個虛擬的設備驅動層,它屬於塊設備驅動,擁有塊設備驅動的特點。所以,他實現了塊設備操作接口

  1. static struct block_device_operations md_fops =  
  2. {  
  3. .owner      = THIS_MODULE,  
  4. .open       = md_open,  
  5. .release    = md_release,  
  6. .ioctl      = md_ioctl,  
  7. .getgeo     = md_getgeo,  
  8. .media_changed  = md_media_changed,  
  9. .revalidate_disk= md_revalidate,  
  10. }; 
 

(對MD的大部分操作均是有md_ioctl接口來實現,少數部分也可由sys文件系統來實現)

       按我的理解,我可以把MD模塊分爲2個部分,一個是控制管理部分,另一個是raid級別實現部分。控制管理部分是一個大的框架,它控制各raid級別模塊,他們之間的如何聯繫的呢?想必看過代碼的人都知道了,就是md_k.h中定義的結構體struct mdk_personality,這個結構體中主要定義了一些函數操作集(就像io調度中elevator中定義的一樣),這些函數分別由各個raid級別來實現,有些raid級別是不實現某些函數的,這個結構體內容如下:

  1. struct mdk_personality  
  2. {  
  3. char *name;  
  4. int level;  
  5. struct list_head list;  
  6. struct module *owner;  
  7. int (*make_request)(request_queue_t *q, struct bio *bio);  
  8. int (*run)(mddev_t *mddev);  
  9. int (*stop)(mddev_t *mddev);  
  10. void (*status)(struct seq_file *seq, mddev_t *mddev);  
  11. /* error_handler must set ->faulty and clear ->in_sync  
  12. * if appropriate, and should abort recovery if needed  
  13. */ 
  14. void (*error_handler)(mddev_t *mddev, mdk_rdev_t *rdev);  
  15. int (*hot_add_disk) (mddev_t *mddev, mdk_rdev_t *rdev);  
  16. int (*hot_remove_disk) (mddev_t *mddev, int number);  
  17. int (*spare_active) (mddev_t *mddev);  
  18. sector_t (*sync_request)(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster);  
  19. int (*resize) (mddev_t *mddev, sector_t sectors);  
  20. int (*check_reshape) (mddev_t *mddev);  
  21. int (*start_reshape) (mddev_t *mddev);  
  22. int (*reconfig) (mddev_t *mddev, int layout, int chunk_size);  
  23. /* quiesce moves between quiescence states  
  24. * 0 - fully active  
  25. * 1 - no new requests allowed  
  26. * others - reserved  
  27. */ 
  28. void (*quiesce) (mddev_t *mddev, int state);  
  29. };  
 

       make_request:塊設備處理請求函數。

       run:各raid模塊啓動函數,例如分配內存、建立線程等。

       stop:各raid模塊停止函數,釋放資源。

       status:/proc文件系統接口

       error_handler:處理讀寫發生錯誤的接口

       hot_add_disk:在重建過程中,將熱備盤加到陣列中。

       hot_remove_disk:在重建過程中,移除失效盤接口

       spare_active:激活熱備盤接口

       check_reshape:陣列擴展檢查接口

       start_reshape:啓動擴展接口

 

       這些函數是在raid模塊加載時候註冊的。

       說了這麼多還沒說到正題呢,呵呵。。。接下來就步入正題。Linxu中md設備是可以通過文件系統訪問的,當創建一個MD設備時,用戶態的讀寫請求通過文件系統發送到MD設備中。熟悉linxu內核的人知道,轉發請求的函數就是generic_make_request,這個函數最終會調用隊列的make_request_fn方法,如果發送到MD設備中,那麼這個方法就由md層中的make_request函數來實現(在struct mdk_personality中定義,由各個raid模塊來實現)。由於raid算法定義不同,make_request實現的方式也不同。本質上來說,md層的make_request就是把文件系統發送過來的bio根據各raid算法進行重新分發到各個磁盤上。而md層中的make_request函數最終還會調用generic_make_request來下發bio,如果這次下發的對象是具體的物理設備,make_request_fn方法就由系統的__make_request來實現,那麼進入io調度層(我會在以後專門一節分析之)。

       這裏我們以raid5爲例,分析make_request是如何轉發bio的。其他raid算法這裏就不做介紹了。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章