標籤:lock_mount graft_tree mount mount_hashtable mountpoint_hashtable
術語表:
struct mount:掛載點
struct mountpoint掛載點節點
struct vfsmount:掛載項
源檔案系統使用者將要掛載的檔案系統
目的檔案系統掛載源檔案系統的檔案系統
一、目的
本文將介紹linux掛載檔案系統的過程,從系統調用mount()函數開始解析,主要分為三個階段:
1、建立源檔案系統;
2、尋找目的檔案系統的掛載目錄;
3、將源檔案系統掛載到目的檔案系統的掛載目錄;
本文以linux 3.10版本為基礎進行講解。
二、函數調用關係
mount系統調用的定義在fs/namespace.c檔案中,具體的定義為:SYSCALL_DEFINE5(mount,char __user *, dev_name, char __user *, dir_name, char __user *,type, unsigned long, flags, void __user *, data)。
其中,dev_name定義了裝置路徑;di_name定義了掛載目錄;type定義了檔案系統類型;flags和data定義了一些選項內容。我們重點關注前三個參數,後兩個參數目前不關注。
描述了主要的函數調用關係,linux掛載檔案系統主要分為三個階段:
1、vfs_kern_mount()負責建立源檔案系統;
2、lock_mount()負責在目的檔案系統中尋找掛載目錄;
3、graft_tree()負責將源檔案系統掛載到目的檔案系統的掛載目錄上;
三、目的檔案系統
為了便於描述,我們假設當前系統已經掛載了ext2檔案系統(即目的檔案系統),tmp目錄將是目的檔案系統的掛載目錄。
下面我們將要把ext3檔案系統掛載到ext2的tmp掛載目錄上,使用的命令是mount(/dev/sda1, /tmp, ext3)(省略了flags和data參數)。
四、建立源檔案系統
首先do_mount()->do_new_mount()->vfs_kern_mount()根據type參數指定的檔案系統類型,建立一個ext3檔案系統。其中需要重點關注的是,vfs_kern_mount()->moutn_fs()根據實際檔案系統的超級塊mount回調鉤子函數,填充超級塊和檔案系統內容(為了簡化,圖中只給出了最簡單的ext3檔案系統,即只有根目錄)。
五、尋找掛載目錄並建立掛載節點 do_mount()->do_new_mount()->do_add_mount()->lock_mount()的功能是遞迴的尋找最終的掛載目錄,這裡的代碼比較難懂,所以下面將詳細描述。
linux允許掛載目錄上掛載多個檔案系統,後面掛載的檔案系統將“覆蓋”之前掛載的檔案系統。例如,minix檔案系統掛載到ext3檔案系統的tmp掛載目錄下,nfs檔案系統掛載到minix檔案系統的/掛載目錄下,最終使用ls命令將只能看見nfs檔案系統,而minix被nfs“覆蓋”了。
其中,tmp目錄指向minix掛載點的紅色虛線僅僅表示邏輯關係,實際並不存在這樣的指向關係,linux使用<掛載點,掛載目錄>二元組作為雜湊因子構成雜湊表mount_hashtable的表項,用來尋找已經掛載的檔案系統。例如,minix掛載到ext3的tmp目錄,那麼linux就根據<ext3, tmp>二元組構成雜湊表項,並且將minix記錄到<ext3, tmp>雜湊表項的鏈表中。當需要尋找ext3的tmp目錄下掛載了哪個檔案系統時,可以根據<ext3, tmp>二元組找到相應的雜湊表項,然後找到對應的已掛載檔案系統minix。
有了以上基礎後,我們再回過頭來看lock_mount()的功能,lock_mount()首先根據當前的<ext3, tmp>二元組找到已掛載的minix檔案系統,然後根據<minix, />二元組找到已掛載的nfs檔案系統,當找到最後一個檔案系統時,根據nfs的根目錄調用new_mountpoint()建立掛載節點(因為minix和nfs掛載到同一個掛載目錄tmp下,所以在掛載minxi時已經建立了掛載節點,所以實際上nfs共用了minix的掛載節點,只是將掛載節點的掛載次數統計加1)。
下面回到第四節描述的情形繼續講述,因為當前檔案系統中只存在ext2檔案系統,因此lock_mount()將根據ext2的掛載目錄tmp調用new_mountpoint()建立掛載節點,並且將掛載節點指向掛載目錄tmp,掛載次數統計加1,最後將掛載節點加入到mountpoint_hashtable雜湊表中(該雜湊表使用掛載目錄tmp作為雜湊因子)。
六、掛載源檔案系統
do_mount()->do_new_mount()->do_add_mount()->graft_tree()負責把建立的源檔案系統ext3掛載到掛載節點上。mnt_set_mountpoint()負責將源檔案系統指向掛載節點,commit_tree()負責將源檔案系統ext3加入到mount_hashtable雜湊表中。(註:圖中省略了目的檔案系統和源檔案系統之間的父子關係)
七、總結
linux掛載檔案系統主要分為三個階段:建立源檔案系統,尋找目的檔案系統的最終掛載目錄並建立掛載節點,最後將源檔案系統關聯到掛載節點上。
著作權聲明: 原創作品,如非商業性轉載,請註明出處;如商業性轉載出版,請與作者聯絡。
linux檔案系統調用(1)---mount